标准的Oracle JDK 7实现使用所谓的线性同余生成器在中生成随机值
java.util.Random。
取自
java.util.Random源代码(JDK 7u2),来自对method的注释,该注释
protected int next(int bits)是生成随机值的方法:
这是线性同余伪随机数生成器,由DH Lehmer定义并由Donald E. Knuth在 计算机编程艺术,第3卷: 半数值算法,第3.2.1节中进行了描述。
线性同余生成器的可预测性
Hugo Krawczyk就如何预测这些LCG撰写了一篇相当不错的论文(“如何预测同余生成器”)。如果你很幸运和感兴趣,你仍然可以在网络上找到它的免费下载版本。而且,还有更多的研究清楚地表明,绝对不应将LCG用于对安全性至关重要的目的。这也意味着你的随机数现在是可以预测的,对于会话ID等你不需要。
如何打破线性同余生成器
假设攻击者必须在一个完整的周期后必须等待LCG重复,这是错误的。即使具有最佳周期(其递归关系中的模数m),也很容易在比整个周期少的时间内预测未来值。毕竟,这只是一堆模块化方程式,需要解决,只要你观察到足够的LCG输出值,就可以轻松实现。
使用“更好”的种子无法提高安全性。不管你是否使用SecureRandom由多个骰子生成的随机值进行播种甚至生成该值都没关系。
攻击者只会根据观察到的输出值来计算种子。与的情况相比,这花费的时间明显少于 2 ^ 48
java.util.Random。不相信的人可以尝试此实验,该实验表明你可以预测未来的Random输出,而在大约2 ^ 16的时间内仅观察两个(!)输出值。现在,在现代计算机上甚至不需要一秒钟就可以预测随机数的输出。
结论
替换你当前的代码。
SecureRandom专门使用。然后,至少你可以保证结果很难预测。如果你需要加密安全的PRNG的属性(在你的情况下,这就是你想要的),那么你就
SecureRandom只能使用。聪明地改变应该使用的方式几乎总是会导致安全性降低。



