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

时间:2013-08-14 09:55:47

标签: java encryption aes jce

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

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

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

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

3 个答案:

答案 0 :(得分:73)

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

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

让提供商选择计划如何获取随机性 - 不要定义可能不如提供商已选择的内容。

此代码示例假定(as Maarten points out below)您已将java.security文件配置为在列表顶部包含首选提供程序。如果您想手动指定提供者,只需致电KeyGenerator.getInstance("AES", "providerName");

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

答案 1 :(得分:22)

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

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

但您使用的方法仍有优势:KeyGenerator专门用于生成密钥。这意味着代码可以针对这一代进行优化。 可以具有效率和安全性优势。例如,它可以被编程为避免暴露密钥的定时侧信道攻击。请注意,清除任何包含密钥信息的byte[]可能已经是一个好主意,因为它们可能会泄漏到交换文件中(尽管如此可能就是这种情况)。

此外,如上所述,并非所有算法都使用完全随机密钥。因此,使用KeyGenerator可以更轻松地切换到其他算法。更现代的密码只接受完全随机密钥;这被视为比例如DES。

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

Duncan's answer所示:始终明确指定密钥大小(和任何其他参数)。不要依赖提供程序默认值,因为不清楚您的应用程序正在做什么,并且每个提供程序可能都有自己的默认值。

答案 2 :(得分:4)

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

Key key;
SecureRandom rand = new SecureRandom();
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(256, rand);
key = generator.generateKey();

如果你需要另一个随机性提供者,我有时会为测试目的而做,只需用

替换rand
MySecureRandom rand = new MySecureRandom();