Создание действительно уникальных UUID в JavaScript и AS3 - PRNG и лежащих в основе алгоритмов

Я работаю над системой, которая генерирует около 2 миллиардов уникальных UUID в день. UUID создаются с использованием JavaScript\Flash (AS3) на клиенте.

Недавно мы заметили, что наши UUID не являются рядом с уникальными. У нас около 20% (!) Суточных дубликатов, большинство из которых (относительно объема трафика) поступают из хрома.

Я сделал некоторое чтение и узнал что реализация алгоритма псевдослучайного генерации (PRNG) на большинстве браузеров и, в частности, хром, является ошибочной. Chromium и Node.js используют движок javaScript V8, который реализует алгоритм MWC1616.

В теории UUID, сгенерированные с использованием хорошего PRNG, должны иметь вероятность 2 132 для столкновения, но с MWC1616, при некоторых очень реалистичных сценарии, эта вероятность составляет около 1: 30000.

Чтобы решить эту проблему, я рассмотрел следующие варианты:

  • Создайте идентификаторы на сервере (с помощью Go)
  • Создайте более сильный идентификатор на клиенте, путем хэширования некоторой информации, такой как IP, UA, временная метка и т.д. с UUID.
  • Замена Math.random() с лучшим случайным генератором.

Так как я предпочитаю держать вещи на клиенте, и я не хочу заново изобретать колесо и модифицировать логику создания UUID, я хочу придерживаться опции 3.

Хорошей новостью является то, что в новых браузерах есть getRandomValues api. К сожалению, мне нужно поддерживать старые браузеры.

Итак, мои вопросы:

  • Что такое хороший и надежный JavaScript polyfill для

crypto.getRandomValues ​​()

(который не использует Math.random внутри)?

  1. Использует ли AS3 Math.random() браузер Math.random()? Он сам реализует один и тот же алгоритм?

  2. Использует ли flash.crypto.generateRandomBytes() использование Math.random()? Использует ли он crypto.getRandomValues ​​()? Если нет, то какой алгоритм он реализует и будет ли это хорошим решением для той же проблемы в AS3? Если нет, какую библиотеку криптосистем AS3 вы бы порекомендовали?

P.S. Я настоятельно рекомендую статьи, которые я упомянул - 1- - 2- - 3-. Я много лет знал о проблемах с Math.random(), но эта статья действительно дала мне понять навсегда.

Ответ 1

Проведя более недели, исследуя это, я пришел к выводу: НИКОГДА НЕ ПОКАЗЫВАЙТЕ UUID на клиенте. Только не надо. Особенно, если вы намерены масштабировать.

В течение многих лет я знал, что реализация браузера Math.random была плохая, но я не понимал, насколько это было плохо, пока мы не достигли масштабов миллиардов событий в день.

Я решил пойти с самым простым техническим решением и перенести создание UUID на сервер. Процент дублированных идентификаторов, когда он составляет от ~ 25% в день до ~ 0,0008%.

P.S. Наш сервер реализован в Go. Node.js использует движок JavaScript V8 и может иметь одинаковые проблемы. Хотя кажется, что если вы используете последний Node.js, вы должны быть в порядке.