Java的SecureRandom重复使用的问题

8
我很困惑如何使用SecureRandom。我需要在一个循环中生成n安全的随机数。在每次生成时,使用同一个SecureRandom实例是否安全?下面两种解决方案在加密强度方面有区别吗?
1) 不使用种子的单个实例
SecureRandom sr = new SecureRandom();
for(int i = 0; i < n; ++i) sr.nextInt();

2) 每一代都要新建实例

for(int i = 0; i < n; ++i) new SecureRandom().nextInt();

3) 带有种子的单实例

SecureRandom sr = new SecureRandom()
for(int i = 0; i < n; ++i) {
    byte[] seed = sr.generateSeed(32);
    sr.setSeed(seed);
    sr.nextInt();
}

1
我需要在一个循环中生成n个随机数 - 第一个问题是,你需要随机数还是安全的随机数。如果是前者,那么你不需要SecureRandom。你可以使用线性同余生成器。LCG适用于模拟,在这种情况下你需要来自均匀分布的快速数字。 - jww
2个回答

12

或许与直觉相反,第三种方法几乎可以确定是最弱的,因为在循环迭代时重新播种是一个可怕的想法。第二种方法也不好,但比第三种稍微好一些,因为SecureRandom()包括一个强大的默认播种策略。按照要求,第一种方法几乎可以确定是最安全的,因为它最大化了熵期。基于这个原因,我建议将其提取为类级常量。

private static final Random RANDOM = new SecureRandom();
// ...
// your method,
for (int i = 0; i < n; ++i) { 
    int num = RANDOM.nextInt();
}

2
也许有些违反直觉,但第三种方法几乎可以确定是最弱的,在循环迭代上重新生成种子是一个糟糕的想法......” - 也有一些论文可能不同意您的看法。这些论文建议在生成器被要求产生位之前重新设置生成器实例的种子。 - jww
“第二个不好,但相对较差,因为SecureRandom()包括强大的默认种子策略” - 反例证明:Android SecureRandom。在使用生成器之前始终进行种子生成。不要依赖他人。 - jww
@jww,我认为这仍然比第三个选项更好。 - Elliott Frisch

2

我建议您阅读这篇有趣的文章

一般情况下,没有必要创建多个SecureRandom()实例,正如@ElliottFrisch所说,static final是最合适的解决方案。

然而,如果您将使用SecureRandom生成大量随机输出序列,则应定期重新生成种子,以防止恶意软件确定种子并因此预测所有未来输出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接