“SecretKeyFactory 不可用”是什么意思?

问题描述 投票:0回答:5

这有什么问题吗?

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 security encryption
5个回答
7
投票

这是一个已验证的 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。


4
投票

您真的不需要使用

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,除非这是一个游戏项目,两者都有弱点并且被认为是过时的。


3
投票

并非所有版本的 Java 都在其默认提供程序中提供

SecretKeyFactory
表示“AES”。

如果您想生成新密钥,请从

SecureRandom
实例中选择所需的位数(128、192 或 256),然后使用该随机数来初始化
SecretKeySpec
实例。

如果您使用基于密码的加密,请为“PBKDF2WithHmacSHA1”算法创建

SecretKeyFactory
,并使用它来初始化
SecretKeySpec
实例,如下所示 所示。


2
投票

如果您尝试打印所有提供商,您可能会错过您需要的提供商。 尝试调用这个方法,看看它打印出什么。

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));

0
投票

对于 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 这解决了问题,没有遇到任何异常。

© www.soinside.com 2019 - 2024. All rights reserved.