Создание действительно уникальных 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 внутри)?
-
Использует ли AS3 Math.random() браузер Math.random()? Он сам реализует один и тот же алгоритм?
-
Использует ли 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, вы должны быть в порядке.