这有什么问题吗?
for (Object obj : java.security.Security.getAlgorithms("Cipher")) {
System.out.println(obj);
}
javax.crypto.SecretKeyFactory.getInstance("AES");
这是输出(Mac OS 10.6 上的 JDK 1.6):
BLOWFISH
ARCFOUR
PBEWITHMD5ANDDES
RC2
RSA
PBEWITHMD5ANDTRIPLEDES
PBEWITHSHA1ANDDESEDE
DESEDE
AESWRAP
AES
DES
DESEDEWRAP
PBEWITHSHA1ANDRC2_40
java.security.NoSuchAlgorithmException: AES SecretKeyFactory not available
at javax.crypto.SecretKeyFactory.<init>(DashoA13*..)
at javax.crypto.SecretKeyFactory.getInstance(DashoA13*..)
...
这是一个已验证的 Java 错误。请参阅https://bugs.openjdk.java.net/browse/JDK-7022467
编辑:不同的java版本支持不同的算法,您还可以使用自定义提供程序等进行扩展。 Oracle 在此处提供了 java 6 的列表 http://docs.oracle.com/javase/6/docs/technotes/guides/security/SunProviders.html 。对于 KeyFactory 来说,这是 DSA。
您真的不需要使用
SecretKeyFactory
。您可以使用以下内容创建 AES 密钥;
byte[] keyData = ........
SecretKeySpec key = new SecretKeySpec(keyData, "AES");
如果您想进行基于密码的加密 (PBE),那么只需选择一种安全散列算法,该算法可为您提供与所需密钥大小相同的散列。例如,如果您想要 AES 的 256 位密钥,这里有一个构建密钥的方法;
private Key buildKey(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest digester = MessageDigest.getInstance("SHA-256");
digester.update(password.getBytes("UTF-8"));
byte[] key = digester.digest();
SecretKeySpec spec = new SecretKeySpec(key, "AES");
return spec;
}
编辑:
我建议不要使用 MD5 和 DES,除非这是一个游戏项目,两者都有弱点并且被认为是过时的。
并非所有版本的 Java 都在其默认提供程序中提供
SecretKeyFactory
表示“AES”。
如果您想生成新密钥,请从
SecureRandom
实例中选择所需的位数(128、192 或 256),然后使用该随机数来初始化 SecretKeySpec
实例。
如果您使用基于密码的加密,请为“PBKDF2WithHmacSHA1”算法创建
SecretKeyFactory
,并使用它来初始化 SecretKeySpec
实例,如下所示 所示。
如果您尝试打印所有提供商,您可能会错过您需要的提供商。 尝试调用这个方法,看看它打印出什么。
for (Object obj : java.security.Security.getProviders()) {
System.out.println(obj);
}
例如,如果您需要特定的提供程序(例如 Bouncy Castle),请将依赖项添加到您的应用程序并将其添加到安全提供程序中,如下所示:
java.security.Security.addProvider(new BouncyCastleProvider());
然后再次查看您的提供商列表。
尝试一下您的所有算法,看看支持哪一种。可以使用 jasypt 加密完成一个示例
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.jasypt.exceptions.EncryptionOperationNotPossibleException;
import org.jasypt.registry.AlgorithmRegistry;
使用以下代码:
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);
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));
对于 Java 17 JDK-17.0.7,我们遇到了类似的错误 Caused by: java.security.NoSuchAlgorithmException: PBKDF2with8BIT SecretKeyFactory not available。 尽管使用“Security.addProvider(new BouncyCastleProvider());”在代码中动态设置java安全性。我们继续面临错误。
有效的解决方案是
更改了JDK版本,从jdk-17.0.7更改为openJdk-17.0.7+7 这解决了问题,没有遇到任何异常。