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

如何在Java中创建安全的随机AES密钥?,java,encryption,aes,jce,Java,Encryption,Aes,Jce,使用标准JDK在Java中生成安全、随机AES密钥的推荐方法是什么 在其他帖子中,我发现了这一点,但使用SecretKeyFactory可能是一个更好的主意: keyGeneratorkeyGen=KeyGenerator.getInstance(“AES”); SecureRandom=新的SecureRandom();//密码术。安全随机 密钥初始(随机); SecretKey SecretKey=keyGen.generateKey(); 如果答案中包含一个解释,说明为什么它是生成随机密

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

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

keyGeneratorkeyGen=KeyGenerator.getInstance(“AES”);
SecureRandom=新的SecureRandom();//密码术。安全随机
密钥初始(随机);
SecretKey SecretKey=keyGen.generateKey();

如果答案中包含一个解释,说明为什么它是生成随机密钥的好方法,那就太好了。谢谢

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

KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256); // for example
SecretKey secretKey = keyGen.generateKey();
让提供者选择它计划如何获得随机性-不要定义可能不如提供者已经选择的好的东西

此代码示例假定()已将
java.security
文件配置为将首选提供程序包含在列表顶部。如果您想手动指定提供者,只需调用
KeyGenerator.getInstance(“AES”,“providerName”)


对于真正安全的密钥,您需要使用(HSM)来生成和保护密钥。HSM制造商通常会提供一个JCE提供商,该提供商将使用上述代码为您生成所有密钥。

使用
KeyGenerator
将是首选方法。正如Duncan指出的,我肯定会在初始化期间给出密钥大小
KeyFactory
是一种应用于现有密钥的方法

好吧,让我们来谈谈这个问题的实质。原则上,AES密钥可以有任何值。没有(3)DES中的“弱键”。也没有任何位具有(3)DES奇偶校验位中的特定含义。因此,生成一个键可以非常简单,只需生成一个带有随机值的字节数组,并在其周围创建一个
SecretKeySpec

但是您使用的方法仍然有一些优点:
KeyGenerator
是专门为生成密钥而创建的。这意味着可以针对这一代优化代码。这可能会带来效率和安全方面的好处。例如,它可能被编程为避免会暴露密钥的定时侧通道攻击。请注意,清除任何保存密钥信息的
字节[]
,可能已经是一个好主意,因为它们可能会泄漏到交换文件中(尽管可能是这种情况)

此外,如上所述,并非所有算法都使用完全随机密钥。因此,使用
KeyGenerator
可以更容易地切换到其他算法。更现代的密码只接受完全随机密钥;与DES相比,这被视为一个主要优势

最后,在我的例子中,最重要的原因是,
KeyGenerator
方法是在安全令牌(智能卡、TPM、USB令牌或HSM)中处理AES密钥的唯一有效方法。如果使用
SecretKeySpec
创建
字节[]
,则密钥必须来自内存。这意味着密钥可以放在安全令牌中,但无论如何,密钥都会暴露在内存中。通常,安全令牌仅适用于在安全令牌中生成的密钥或由智能卡或密钥注入的密钥。
KeyGenerator
可以与提供者一起提供,以便在安全令牌中直接生成密钥


如中所示:始终明确指定密钥大小(以及任何其他参数)。不要依赖提供商的默认设置,因为这会使您的应用程序的功能不明确,而且每个提供商可能都有自己的默认设置。

其他帖子中有很多好的建议。这就是我使用的:

Key key;
SecureRandom rand = new SecureRandom();
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(256, rand);
key = generator.generateKey();
如果您需要另一个随机性提供程序(我有时会出于测试目的这样做),只需将rand替换为

MySecureRandom rand = new MySecureRandom();

这可能有助于@Tala我就是在那里找到的。但是从那篇文章中,我无法确定如何创建随机密钥,以及为什么这是一种安全的方法,通常我也会忽略提供者的名称。配置平台(例如,使用
java.security
文件或使用
security.addProvider()
以编程方式配置
Provider
,以及类似方式)。否则,代码的可移植性会降低,并且不允许用户在不更改应用程序代码的情况下更改为HSM。为什么我需要指定提供程序?默认行为是使用支持该算法的最高优先级安装的提供程序,这在我看来已经足够了。并非所有密钥生成方法都是相同的,您可能希望明确选择提供程序的密钥生成方法。这尤其适用于安全令牌的提供者。不过,对于AES,随机数生成器可能更重要-例如,您可能希望使用较慢、更安全、FIPS认证的随机数生成器,而不是默认的随机数生成器;或keyGen.init(128)@HemanthPeela它定义了要生成的键的长度。256位密钥比128位密钥强。第一次指定随机生成器时,第二次指定要使用的AES密钥的长度(256)。它们是独立的init方法。