10

这段代码安全吗?

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

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

4

3 回答 3

26

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

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

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

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

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

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

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

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

另请参阅如何使用 Java SecureRandom 解决性能问题?
和这篇博文:http ://www.cigital.com/justice-league-blog/2009/08/14/proper-use-of-javas-securerandom/

于 2012-09-03T16:35:48.827 回答
2

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

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

您想使用 SHA1PRNG,因为它保证了快速的非阻塞实现,即使在 Linux 上也是如此,默认情况下不是这样。

于 2012-09-04T12:10:44.280 回答
1

该代码是相当安全的,因为它不只是使用给定的种子来播种随机化器。

它并不比仅仅使用更随机。

SecureRandom randomizer = new SecureRandom();
于 2012-09-03T13:56:00.370 回答