在JavaScript和AS3中生成真正独特的UUID - PRNG和底层算法

Liz*_*zom 5 javascript random algorithm cryptography actionscript-3

我正在研究一种每天产生大约20亿个独特UUID的系统.UUID是使用客户端上的JavaScript\Flash(AS3)生成的.

我们最近注意到我们的UUID并不是独一无二的.我们有大约20%(!)的每日重复,其中大部分(相对于交通量)来自铬.

我做了一些阅读, 并了解到 大多数浏览器上的伪随机生成(PRNG)算法实现,特别是chrome,是有缺陷的.Chromium和Node.js使用V8 javaScript引擎,该引擎实现了一个名为MWC1616的算法.

理论上,使用良好PRNG生成的UUID应该具有2 132概率的碰撞,但是对于MWC1616,在一些非常现实的情况下,这个概率大约是1:30000.

为了解决这个问题,我考虑了以下选项:

  1. 在服务器上生成ID(使用Go)
  2. 通过使用UUID散列一些信息(如IP,UA,时间戳等),在客户端上生成更强的ID.
  3. 用更好的随机生成器替换Math.random().

因为我更喜欢把东西放在客户端上而我不想重新发明轮子并修改UUID创建逻辑,所以我想坚持使用选项3.

好消息是,在较新的浏览器上,有getRandomValues api.不幸的是,我需要支持旧浏览器.

所以我的问题是:

  1. 什么是优秀可靠的JavaScript polyfill

crypto.getRandomValues()

(内部不使用Math.random)?

  1. AS3 Math.random()是否使用浏览器的Math.random()?它是否实现了相同的算法?

  2. flash.crypto.generateRandomBytes()是否使用Math.random()?它使用crypto.getRandomValues()吗?如果没有,它实现了哪种算法,并且它是AS3中同一问题的良好解决方案吗?如果没有,你会推荐哪个AS3加密库?

PS我强烈推荐我提到的文章-1- -2- -3-.多年来我一直意识到Math.random()的问题,但这篇文章真的让我很清楚.

Liz*_*zom 3

经过一个多星期的研究后,我的结论是:永远不要在客户端上生成 UUID。只是不要。特别是如果您打算扩大规模。

多年来,我知道浏览器的 Math.random 实现很差,但我不明白它有多糟糕,直到我们达到每天数十亿个事件的规模。

我决定采用最简单的技术解决方案,并将 UUID 生成移至服务器。重复 ID 的百分比从每天约 25%降至约 0.0008%

PS 我们的服务器是用 Go 实现的。Node.js 使用 JavaScript V8 引擎,可能存在相同的问题。虽然看起来如果您使用的是最新的 Node.js,应该没问题。

  • 我认为没有必要说“永远不要在客户端生成 UUID”。在创建数据实体的同时创建规范 ID 有很多好处,在我们日益以移动为中心的世界中,这种情况越来越频繁地发生在客户端上。还要注意,一旦您必须扩展到单个服务器之外,您就会遇到在服务器上生成 ID 时遇到的所有相同问题。这里真正的要点是永远不要假设您的 ID 保证是唯一的。对此进行检查,并在发生碰撞时优雅地失败。 (2认同)