是否保证对安全随机的2次连续调用会给出不同的数字?

时间:2015-07-15 20:04:36

标签: java random integer sha1 secure-random

使用SecureRandom是否有保证,2个连续的来电不会返回相同的号码?
如果这是客户端API方面的严格要求,那么代码中的以下循环是否冗余?

Random random = SecureRandom.getInstance("SHA1PRNG");  
long value1 = (long)(r.nextDouble() * LIMIT) + 1;  
long value2 = (long)(r.nextDouble() * LIMIT);  

while(value1 == value2) {  
   value2 = (long)(r.nextDouble() * LIMIT);  
}

3 个答案:

答案 0 :(得分:4)

我不希望有。每个呼叫都应该是独立的 - 要求下一个呼叫不能提供与前一个呼叫相同的结果,这意味着它不是随机的,IMO。

举一个较小的例子,假设我们没有nextDouble但是一个返回1到3范围内值的方法。通过消除两次返回相同值的可能性,您可以有效地将每次调用约束为50/50选择,原因并非明显。您可以提供有关下一次电话会议的额外信息,以便能够观察到这些人员。调用

现在很明显double范围更大 - 所以两个真正随机选择的值中的两个相同的值要小得多。不是1 in 2 64 ,但相当大。

当然,你的算术有所减少 - 即使nextDouble() 确实保证总是返回不同的值,但两个{完全有可能} {1}}值乘以double后会得到相同的结果,然后转换为LIMIT。想象一下,如果long为2,那么......您希望看到多少可能的值?

所以不,如果您有严格的客户要求,我不认为您所拥有的代码是多余的。

答案 1 :(得分:3)

没有。它不能保证并保证会降低安全性,因为攻击者可能会利用这些知识,即在连续呼叫中永远不会获得相同的数字。随机数字序列完全可以包含数字的“运行”。如果你有一个数字列表,你有相同的机会选择任何号码,那么你很可能两次选择相同的号码。当然,发生这种情况的可能性低于获得两个不同数字序列的概率,但它不是零。

此外,CSPRNG的要求之一是给定状态,您不应该能够预测下一个状态(即,您范围内的所有数字都有相同的显示概率)。但根据您的要求,您可以预测,如果您的随机数在x0范围内生成一个n,那么在下次通话中,您将获得任意数字 x

虽然CSPRNG中可能存在某种状态机,但每次呼叫基本上都与先前的呼叫无关,并且不应受它们的影响。

如果你想要唯一性,你应该使用像UUID这样的东西。这些可以随机生成,具有您获得唯一性的优势(如果您使用的是CSPRNG且种子源具有足够的熵)。

如果要求客户端获得两个相同的随机数,则代码不是冗余的。但它会违反“随机性”属性;这有多重要,取决于你的具体情况。

答案 2 :(得分:2)

通过致电LIMIT,您实际上正在呼叫nextDouble() - Random.nextDouble()延长SecureRandom并且不会覆盖Random

根据nextDouble()的文档 - 没有保证,2个顺序调用不会返回相同的数字 - 也就是说,它发生的可能性非常低。