Java PBEWithHMACSHA256和U 256加密抛出加密操作不可能例外
我想使用Java PBEWithHMACSHA256和U 256加密抛出加密操作不可能例外,java,encryption,aes,jasypt,sha2,Java,Encryption,Aes,Jasypt,Sha2,我想使用pbewithhmacsha256andaes256算法,但它不受支持。我已经将提供者添加到我的测试中,希望它能工作,但没有效果。有谁能告诉我如何修复下面的测试,以便将PBEWITHHMACSHA256ANDAES添加到支持的列表中 import java.security.Security; import java.util.Set; import java.util.TreeSet; import org.bouncycastle.jce.provider.BouncyCastle
pbewithhmacsha256andaes256
算法,但它不受支持。我已经将提供者添加到我的测试中,希望它能工作,但没有效果。有谁能告诉我如何修复下面的测试,以便将PBEWITHHMACSHA256ANDAES
添加到支持的
列表中
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));
}
}
*编辑*
@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
我认为问题在于Jasypt无法保留派生的
算法参数
,在加密
和解密
之间切换密码时无法重复使用这些参数。Jasypt掩盖的基本异常是java.security.invalidalgorithParameterException:缺少参数类型:IV预期为,但如果您提供salt
(或本例中的SaltGenerator
)和密钥获取迭代次数
(即调用HMAC/SHA-256
“密钥摘要函数”),Jasypt仍然抱怨,因为它不知道如何将计算出的参数传递给解密密码。(您可以通过调试测试并在StandardPByteEncryptor.java
第1055行设置断点来验证这一点(Jasypt 1.9.2))--在这里,您可以捕获底层异常,并使用表达式窗口验证:
encryptCipher.getParameters().getEncoded() -> 306206092a864886f70d01050d3055303406092a864886f70d01050c30270410f5a439e8dc12642972dbbf3e1867edaf020203e8020120300c06082a864886f70d02090500301d060960864801650304012a0410caacd97ae953ae257b1b4a0bb70ccc2e
但是
下面是一个(Groovy)测试,它演示了Jasypt的失败以及使用所需算法的成功方法(注意:1000次迭代不足以针对现代硬件提供强大的安全性,但仅用于演示目的):
请查看BouncyCastle支持的算法..pbewithhmacsha256andaes256不在列表中。它可能从其他安全提供商的列表中弹出。例如,请参阅我的编辑部分,com.sun.crypto.provider.SunJCE
位于security.getProviders()
返回的数组中
encryptCipher.getParameters().getEncoded() -> 306206092a864886f70d01050d3055303406092a864886f70d01050c30270410f5a439e8dc12642972dbbf3e1867edaf020203e8020120300c06082a864886f70d02090500301d060960864801650304012a0410caacd97ae953ae257b1b4a0bb70ccc2e
decryptCipher.getParameters().getEncoded() -> java.security.ProviderException: Could not construct CipherSpi instance
@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"
}