如何在Java中创build一个安全的随机AES密钥?
使用标准JDK在Java中生成安全,随机的AES密钥的推荐方法是什么?
在其他文章中,我发现这一点,但使用SecretKeyFactory
可能是一个更好的主意:
KeyGenerator keyGen = KeyGenerator.getInstance("AES"); SecureRandom random = new SecureRandom(); // cryptograph. secure random keyGen.init(random); SecretKey secretKey = keyGen.generateKey();
如果答案中包含了解释为什么这是生成随机密钥的好方法,那将是非常好的。 谢谢!
我会使用你的build议代码,但稍作简化:
KeyGenerator keyGen = KeyGenerator.getInstance("AES"); keyGen.init(256); // for example SecretKey secretKey = keyGen.generateKey();
让提供者select计划如何获得随机性 – 不要定义一些不像提供者已经select的东西。
这个代码示例假设( 正如Maarten指出的那样 ),您已经configuration了您的java.security
文件,将您的首选提供者包含在列表顶部。 如果你想手动指定提供者,只需调用KeyGenerator.getInstance("AES", "providerName");
。
对于真正安全的密钥,您需要使用硬件安全模块 (HSM)来生成和保护密钥。 HSM制造商通常会提供一个JCE提供商,使用上述代码为您提供所有关键代码。
使用KeyGenerator
将是首选的方法。 正如Duncan指出的那样,我肯定会在初始化时给出密钥大小。 KeyFactory
是一种应该用于预先存在的密钥的方法。
好吧,让我们来谈谈这个问题的实质。 原则上AES密钥可以有任何价值。 (3)DES中没有“弱密钥”。 在(3)DES奇偶校验位中也没有任何具有特定含义的位。 因此,生成一个密钥可以像生成一个随机值的字节数组一样简单,并在其周围创build一个SecretKeySpec
。
但是,您使用的方法仍然有优势: KeyGenerator
专门用于生成密钥。 这意味着代码可能会针对这一代进行优化。 这可能有效率和安全的好处。 例如,它可以被编程来避免会暴露密钥的定时通道攻击。 请注意,清除任何保存密钥信息的byte[]
可能已经是一个好主意,因为它们可能会泄漏到交换文件中(尽pipe如此,也可能是这种情况)。
而且,如前所述,并不是所有的algorithm都使用完全随机的密钥。 所以使用KeyGenerator
可以更容易切换到其他algorithm。 更现代的密码只能接受完全随机的密钥; 这被看作是比DES更重要的一个优点。
最后,在我的情况下,最重要的原因是, KeyGenerator
方法是处理安全令牌(智能卡,TPM,USB令牌或HSM)中的AES密钥的唯一有效方法。 如果使用SecretKeySpec
创buildbyte[]
,则密钥必须来自内存。 这意味着密钥可以放在安全令牌中,但不pipe密钥在内存中是否被暴露。 通常,安全令牌只能使用在安全令牌中生成的密钥或通过例如智能卡或钥匙典礼注入的密钥。 KeyGenerator
可以与提供者一起提供,以便在安全令牌内直接生成密钥。
正如Duncan的回答所指出的那样:总是明确指定密钥大小(以及其他参数)。 不要依赖提供者的默认值,因为这会使你不清楚你的应用程序在做什么,而且每个提供者可能都有自己的默认值。
在其他职位很多好的advince。 这是我使用的:
Key key; SecureRandom rand = new SecureRandom(); KeyGenerator generator = KeyGenerator.getInstance("AES"); generator.init(256, rand); key = generator.generateKey();
如果您需要另一个随机性提供程序,我曾经为了testing目的而提供,请将randreplace为
MySecureRandom rand = new MySecureRandom();