1. 概述

java.security包中的SecureRandom类专为加密目的和关键安全情况设计,它使用保证高度不可预测性的算法。在这个教程中,我们将讨论如何使用SecureRandom生成一个唯一的正长整值,并探索在生成多个值时,它的碰撞安全性。

2. 使用nextLong()

SecureRandomnextLong()方法返回一个long类型的随机64位数。这些值分布在非常宽广的范围内,从Long.MIN_VALUE(-2^63)到Long.MAX_VALUE(2^63 - 1)。

这个方法是从Random类继承来的,但由于使用了更多的种子位,它在碰撞概率上得到了保证更安全。

在内部,它结合了伪随机数生成器(PRNG,也称为确定性随机位生成器或DRBG)以及由操作系统提供的熵源。

让我们看看如何使用它来生成一个随机的long值:

new SecureRandom().nextLong();

如果我们打印出这个方法的几个结果,可能会看到如下输出:

4926557902899092186
-2282075914544479463
-4653180235857827604
6589027106659854836

如果只需要正数值,我们还需要额外使用Math.abs()

SecureRandom secureRandom = new SecureRandom();
long randomPositiveLong = Math.abs(secureRandom.nextLong());

这样,结果就始终保证是正的:

assertThat(randomPositiveLong).isNotNegative();

3. 碰撞概率

由于我们需要生成唯一值,确保碰撞的概率足够低是很重要的。

如前所述,nextLong()方法生成的64位随机long值范围在-2^63到2^63 - 1之间。通过应用Math.abs(),我们消除了任何负号。因此,0到2^63范围的随机性减少了2倍。因此,碰撞的概率计算为1 / 2^62。用十进制表示,这个概率大约是0.000000000000000000216840434497100900。对于大多数实际应用来说,我们可以认为这个低概率是可以忽略不计的。

假设每秒生成一个值,平均来说,大约需要大约(2^62) / (60) / (60) / (24) / (365.25)年的时间才会发生一次碰撞,即大约146,135,511,523年。这个超长的时间跨度进一步强调了碰撞事件的罕见性。

4. 总结

在这篇文章中,我们讨论了如何使用SecureRandom生成唯一的正长整值。这种方法被认为是有效的,因为它保证了高度的不可预测性,而且对于大多数应用来说,碰撞的概率可以视为微不足道,因此适用于各种场景。

如往常一样,完整的源代码可在GitHub上找到。


原始标题:Generating Unique Positive Long Using SecureRandom in Java | Baeldung