SecureRandom安全的Java种子

时间:2012-09-03 13:53:52

标签: java security encryption random cryptography

这段代码安全吗?

 SecureRandom randomizer = new SecureRandom(String.valueOf(new Date().getTime()).getBytes());

这是实例安全随机种子的正确方法吗?

3 个答案:

答案 0 :(得分:25)

不,你应该避免使用SecureRandom(byte[])构造函数。它既不安全又不便携。

它是不可移植的,因为它在Windows上与其他操作系统的行为不同。

在大多数操作系统上,默认算法是“NativePRNG”,它从操作系统中获取随机数据(通常为"/dev/random")并忽略您提供的种子。

在Windows上,默认算法是“SHA1PRNG”,它将种子与计数器组合在一起并计算结果的哈希值。

这在您的示例中是个坏消息,因为输入(当前UTC时间,以毫秒为单位)具有相对较小的可能值范围。例如,如果攻击者知道RNG在过去48小时内播种,他们可以将种子缩小到小于2 28 可能值,即你只有27位熵。

另一方面,如果您在Windows上使用了默认的SecureRandom()构造函数,它将调用本机CryptoGenRandom函数来获取128位种子。因此,通过指定自己的种子,你已经削弱了安全性。

如果您真的想要覆盖默认种子(例如,用于单元测试),您还应该指定算法。 E.g。

SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed("abcdefghijklmnop".getBytes("us-ascii"));

另见How to solve performance problem with Java SecureRandom?
和这篇博文:http://www.cigital.com/justice-league-blog/2009/08/14/proper-use-of-javas-securerandom/

答案 1 :(得分:2)

我认为最好让SecureRandom种子本身。这是通过在创建后立即调用nextBytes来完成的(调用setSeed将阻止它)。

final byte[] dummy = new byte[512];
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.nextBytes(dummy);

您希望使用SHA1PRNG,因为它可以保证快速非阻塞实现,即使在Linux上也是如此,默认情况下不是。

答案 2 :(得分:1)

代码是相当安全的,因为它不仅仅使用给种子来种子随机发生器。

它不仅仅是随机使用。

SecureRandom randomizer = new SecureRandom();