如何在Java中创建安全的随机AES密钥?

2022-08-31 16:05:26

使用标准 JDK 在 Java 中生成安全、随机的 AES 密钥的推荐方法是什么?

在其他帖子中,我发现了这一点,但是使用a可能是一个更好的主意:SecretKeyFactory

KeyGenerator keyGen = KeyGenerator.getInstance("AES");
SecureRandom random = new SecureRandom(); // cryptograph. secure random 
keyGen.init(random); 
SecretKey secretKey = keyGen.generateKey();

如果答案包括解释为什么它是生成随机密钥的好方法,那就太好了。谢谢!


答案 1

我会使用你建议的代码,但稍微简化一下:

KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256); // for example
SecretKey secretKey = keyGen.generateKey();

让提供者选择它计划如何获得随机性 - 不要定义可能不如提供者已经选择的东西好的东西。

此代码示例假定(如 Maarten 在下面指出的那样)你已将文件配置为在列表顶部包含首选提供程序。如果要手动指定提供程序,只需调用 。java.securityKeyGenerator.getInstance("AES", "providerName");

要获得真正安全的密钥,您需要使用硬件安全模块 (HSM) 来生成和保护密钥。HSM 制造商通常会提供一个 JCE 提供程序,该提供程序将使用上述代码为您完成所有密钥生成。


答案 2

使用将是首选方法。正如 Duncan 所指出的,我肯定会在初始化期间给出密钥大小。 是一种应用于预先存在的密钥的方法。KeyGeneratorKeyFactory

好吧,让我们来看看这个的细节。原则上,AES 密钥可以具有任何值。没有像(3)DES中那样的“弱键”。也没有任何位具有特定含义,如(3)DES奇偶校验位。因此,生成密钥可以像生成具有随机值的字节数组并围绕它创建一个数组一样简单。SecretKeySpec

但是,您正在使用的方法仍然有一些优点:专门为生成密钥而创建的。这意味着代码可能会针对这一代进行优化。这可以提高效率和安全优势。例如,可以对它进行编程以避免时序侧信道攻击,从而暴露密钥。请注意,清除任何包含关键信息的信息可能已经是一个好主意,因为它们可能会泄漏到交换文件中(尽管情况可能确实如此)。KeyGeneratorbyte[]

此外,如前所述,并非所有算法都使用完全随机的密钥。因此,使用可以更轻松地切换到其他算法。不过,更现代的密码只接受完全随机的密钥。这被视为优于 DES 等产品的主要优势。KeyGenerator

最后,在我的情况下,最重要的原因是,该方法是在安全令牌(智能卡,TPM,USB令牌或HSM)中处理AES密钥的唯一有效方法。如果使用 创建,则密钥必须来自内存。这意味着密钥可以放在安全令牌中,但无论如何,密钥都会在内存中公开。通常,安全令牌仅适用于在安全令牌中生成或由智能卡或密钥仪式等注入的密钥。可以与提供程序一起提供 A,以便直接在安全令牌中生成密钥。KeyGeneratorbyte[]SecretKeySpecKeyGenerator

Duncan 的答案所示:始终显式指定密钥大小(以及任何其他参数)。不要依赖提供程序默认值,因为这会使应用程序不清楚正在执行的操作,并且每个提供程序可能都有自己的默认值。


推荐