来自java的UUID.randomUUID()的重复UUID集



我们观察到这组近 200,000 个 UUID 相隔两个月重播,我想知道是否有人见过类似的东西。

UUID 是使用 UUID.randomUUID() 生成的。 在深入研究这个问题(查看java源代码)时,randomUUID()在引擎盖下使用了SecureRandom(),而SecureRandom()又使用NativePRNG。 据我了解,NativePRNG 使用/dev/urandom 来获取其种子。 当然,这意味着令人困惑 - 不知何故,/dev/urandom 将相同的种子返回给 NativePRNG 两个月。 据我所知,一旦实例化,PRNG 就不会重新播种。 这是一个长时间运行的作业,它侦听消息并使用 UUID 作为它的 ID。 伪代码很简单:

< receive message> String uuid = UUID.randomUUID().toString(); String fname = h.composeArtifact(uuid);

操作系统是 Centos 6,位于运行 JDK1.6 的 AWS EC2 实例上。 这是任何人过去见过/经历过的事情吗? 似乎是那种不应该"永远不会发生"的事情......

实际上,从 JDK 1.6 源代码中,UUID.randomUUID()java.util.SecureRandom实例为源。如果你得到了一个重复的 UUID 序列,那么要么你非常幸运(或者非常不幸,取决于你的观点),要么有人玩过虚拟机快照,要么你的 Java 配置中有一些可疑的东西。

拍摄虚拟机快照时,您可以记录计算机、进程和 RAM 的完整实时状态(包括)。如果存在一个已实例化的 SecureRandom 实例的实时进程,则还原快照将恢复该状态,因此每次还原发生时,该SecureRandom输出的随机值序列将相同,直到SecureRandom/dev/urandom/dev/urandom不断收集"随机"物理事件)重新设定种子, 但在下一次重新播种之前,这些不会影响SecureRandom状态)。

Java 配置可能会影响SecureRandom,因为SecureRandom不是 PRNG,而是围绕正式注册的加密提供程序提供的SecureRandomSpi实例的 shell。Sun的JDK带有一个默认的实现,通常以系统的资源为源(在Linux上/dev/urandom)。但是,这可以配置;查找 java.security.egd 系统属性,以及java.security文件中的 securerandom.source 属性。默认提供程序也可以完全替换为执行不同操作(并且可能非常糟糕)的替代实现。有关一些详细信息,请参阅此答案。验证确实使用了哪个随机源可能有点复杂,但您可以尝试使用 strace 启动进程,这将显示系统调用,因此在某个时候是否打开了/dev/random/dev/urandom

如果您的 Java 配置很好,并且没有带有 VM 快照的游戏,并且您确定您确实获得了与以前相同的 UUID 序列,那么您真的应该购买强力球票(但我不诚实地相信这种情况)。

最新更新