2

我想使用该PBEWITHHMACSHA256ANDAES_256算法,但不支持。我已将充气城堡提供程序添加到我的测试中,希望它能够工作但无济于事。谁能告诉我如何修复下面PBEWITHHMACSHA256ANDAES添加到Supported列表中的测试?

import java.security.Security;
import java.util.Set;
import java.util.TreeSet;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.jasypt.exceptions.EncryptionOperationNotPossibleException;
import org.jasypt.registry.AlgorithmRegistry;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

public class EncryptionTest {
    @BeforeClass
    public static void beforeClass() {
        Security.addProvider(new BouncyCastleProvider());
    }

    @Test
    public void test() {
        Set<String> supported = new TreeSet<>();
        Set<String> unsupported = new TreeSet<>();
        for (Object oAlgorithm : AlgorithmRegistry.getAllPBEAlgorithms()) {
            String algorithm = (String) oAlgorithm;
            try {
                SimpleStringPBEConfig pbeConfig = new SimpleStringPBEConfig();
                pbeConfig.setAlgorithm(algorithm);
                pbeConfig.setPassword("changeme");
                StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
                encryptor.setConfig(pbeConfig);

                String encrypted = encryptor.encrypt("foo");
                String decrypted = encryptor.decrypt(encrypted);
                Assert.assertEquals("foo", decrypted);
                supported.add(algorithm);
            } catch (EncryptionOperationNotPossibleException e) {
                unsupported.add(algorithm);
            }
        }
        System.out.println("Supported");
        supported.forEach((String alg) -> System.out.println("   " + alg)); 
        System.out.println("Unsupported");
        unsupported.forEach((String alg) -> System.out.println("   " + alg)); 
    }
}            

输出:

Supported
   PBEWITHMD2ANDDES
   PBEWITHMD5AND128BITAES-CBC-OPENSSL
   PBEWITHMD5AND192BITAES-CBC-OPENSSL
   PBEWITHMD5AND256BITAES-CBC-OPENSSL
   PBEWITHMD5ANDDES
   PBEWITHMD5ANDRC2
   PBEWITHSHA1ANDDES
   PBEWITHSHA1ANDDESEDE
   PBEWITHSHA1ANDRC2
   PBEWITHSHA1ANDRC2_128
   PBEWITHSHA1ANDRC2_40
   PBEWITHSHA1ANDRC4_128
   PBEWITHSHA1ANDRC4_40
Unsupported
   PBEWITHHMACSHA1ANDAES_128
   PBEWITHHMACSHA1ANDAES_256
   PBEWITHHMACSHA224ANDAES_128
   PBEWITHHMACSHA224ANDAES_256
   PBEWITHHMACSHA256ANDAES_128
   PBEWITHHMACSHA256ANDAES_256
   PBEWITHHMACSHA384ANDAES_128
   PBEWITHHMACSHA384ANDAES_256
   PBEWITHHMACSHA512ANDAES_128
   PBEWITHHMACSHA512ANDAES_256
   PBEWITHMD5ANDTRIPLEDES
   PBEWITHSHA256AND128BITAES-CBC-BC
   PBEWITHSHA256AND192BITAES-CBC-BC
   PBEWITHSHA256AND256BITAES-CBC-BC
   PBEWITHSHAAND128BITAES-CBC-BC
   PBEWITHSHAAND128BITRC2-CBC
   PBEWITHSHAAND128BITRC4
   PBEWITHSHAAND192BITAES-CBC-BC
   PBEWITHSHAAND2-KEYTRIPLEDES-CBC
   PBEWITHSHAAND256BITAES-CBC-BC
   PBEWITHSHAAND3-KEYTRIPLEDES-CBC
   PBEWITHSHAAND40BITRC2-CBC
   PBEWITHSHAAND40BITRC4
   PBEWITHSHAANDIDEA-CBC
   PBEWITHSHAANDTWOFISH-CBC

* 编辑 *

@EbbeMPedersen 建议该算法由 SunJCE 提供,但我可以看到使用以下代码启用了 SunJCE 提供程序

for (Provider provider : Security.getProviders()) {
    System.out.println(provider.getName() + " " + provider.getClass().getName());
}

输出

SUN sun.security.provider.Sun
SunRsaSign sun.security.rsa.SunRsaSign
SunEC sun.security.ec.SunEC
SunJSSE com.sun.net.ssl.internal.ssl.Provider
SunJCE com.sun.crypto.provider.SunJCE
SunJGSS sun.security.jgss.SunProvider
SunSASL com.sun.security.sasl.Provider
XMLDSig org.jcp.xml.dsig.internal.dom.XMLDSigRI
SunPCSC sun.security.smartcardio.SunPCSC
SunMSCAPI sun.security.mscapi.SunMSCAPI
BC org.bouncycastle.jce.provider.BouncyCastleProvider
4

1 回答 1

0

我认为问题在于 Jasypt 在和之间切换密码时无法保留派生和AlgorithmParameters重用它们。Jasypt 隐藏的潜在异常是,但是如果您提供(或在这种情况下)和(即调用“密钥摘要函数”的次数),Jasypt 仍然会抱怨,因为它不知道如何通过计算出的解密密码参数。(您可以通过调试测试并在行(Jasypt 1.9.2) 中放置断点来验证这一点)——在这里您可以捕获底层异常使用表达式窗口来验证:ENCRYPTDECRYPTjava.security.InvalidAlgorithmParameterException: Missing parameter type: IV expectedsaltSaltGeneratorkey obtention iterationsHMAC/SHA-256StandardPBEByteEncryptor.java1055

encryptCipher.getParameters().getEncoded() -> 306206092a864886f70d01050d3055303406092a864886f70d01050c30270410f5a439e8dc12642972dbbf3e1867edaf020203e8020120300c06082a864886f70d02090500301d060960864801650304012a0410caacd97ae953ae257b1b4a0bb70ccc2e

decryptCipher.getParameters().getEncoded() -> java.security.ProviderException: Could not construct CipherSpi instance

这是一个(Groovy)测试,它演示了 Jasypt 的失败以及使用所需算法的成功方法(注意:1000 次迭代不足以针对现代硬件提供强大的安全性,但仅用于演示目的):

@Test
void testShouldUseHS256andAES256() {
    // Arrange
    String algorithm = "PBEwithHMACSHA256andAES_256";
    SimpleStringPBEConfig pbeConfig = new SimpleStringPBEConfig();
    pbeConfig.setAlgorithm(algorithm);
    pbeConfig.setPassword("changeme");

    // Need an IV (derived from salt and iteration count)
    // pbeConfig.setKeyObtentionIterations(1000);
    // pbeConfig.setSaltGenerator(new RandomSaltGenerator());

    StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
    encryptor.setConfig(pbeConfig);

    // Act
    def msg = shouldFail(Exception) {
        String encrypted = encryptor.encrypt("foo");

        // Assert
        String decrypted = encryptor.decrypt(encrypted);
        Assert.assertEquals("foo", decrypted);
    }
    logger.info("Expected: ${msg}")

    // Required way
    Cipher rawCipher = Cipher.getInstance(algorithm)
    PBEKeySpec pbeKeySpec = new PBEKeySpec("changeme" as char[])
    final SecretKeyFactory factory = SecretKeyFactory.getInstance(algorithm);
    SecretKey tempKey = factory.generateSecret(pbeKeySpec);
    PBEParameterSpec saltParameterSpec = new PBEParameterSpec(Hex.decodeHex("0123456789ABCDEF" as char[]), 1000)
    rawCipher.init(Cipher.ENCRYPT_MODE, tempKey, saltParameterSpec)

    // Save the generated ASN.1-encoded parameters
    byte[] algorithmParameterBytes = rawCipher.getParameters().encoded

    byte[] cipherBytes = rawCipher.doFinal("foo".getBytes(StandardCharsets.UTF_8))

    AlgorithmParameters algorithmParameters = AlgorithmParameters.getInstance(algorithm)
    algorithmParameters.init(algorithmParameterBytes)
    rawCipher.init(Cipher.DECRYPT_MODE, tempKey, algorithmParameters)
    byte[] plainBytes = rawCipher.doFinal(cipherBytes)
    String recovered = new String(plainBytes, StandardCharsets.UTF_8)

    assert recovered == "foo"
}
于 2016-12-08T00:30:43.190 回答