Псевдослучайные генераторы (PRNG) в JavaScript, прежде всего
Math.random(), строятся на детерминированных алгоритмах. Их
поведение полностью определяется внутренним состоянием генератора,
которое обновляется при каждом вызове функции. Несмотря на внешнюю
«случайность» последовательности значений, при наличии начального
состояния или возможности его восстановления последовательность может
быть воспроизведена.
Ключевая характеристика таких генераторов — предсказуемость при достаточном количестве информации о состоянии. Это делает их непригодными для задач, где требуется криптографическая стойкость.
PRNG в стандартной библиотеке JavaScript проектировался для задач моделирования, визуализации, тестирования и прочих некритичных сценариев. Основные ограничения:
Даже современные реализации Math.random() используют
улучшенные алгоритмы (например, xorshift, Mersenne Twister-подобные
подходы в исторических реализациях), но они не предназначены для
противостояния анализу состояния.
Web Crypto API предоставляет механизм генерации случайных значений через:
crypto.getRandomValues(typedArray)
Этот метод использует криптографически стойкий генератор случайных чисел (CSPRNG), встроенный в операционную систему или криптографический слой браузера. В отличие от PRNG, его выходные данные должны быть:
CSPRNG опирается на реальные источники энтропии системы:
Далее энтропия проходит через криптографические преобразования (например, хэш-функции или блочные шифры), что исключает возможность восстановления внутреннего состояния.
| Характеристика | PRNG (Math.random) |
CSPRNG (crypto.getRandomValues) |
|---|---|---|
| Предсказуемость | возможна | практически исключена |
| Назначение | симуляции, UI | криптография, безопасность |
| Источник | алгоритм | системная энтропия |
| Восстановление состояния | возможно при анализе | неосуществимо в нормальной модели |
| Стойкость к атаке | отсутствует | криптографическая |
Генерация случайных байтов выполняется через типизированные массивы:
const array = new Uint8Array(16);
crypto.getRandomValues(array);
Каждый байт массива заполняется случайным значением от 0 до 255.
Особенность заключается в том, что API не возвращает число напрямую, а работает только с буферами фиксированного размера. Это снижает риск ошибок, связанных с преобразованием типов и масштабированием диапазонов значений.
Использование Math.random() в контексте безопасности
приводит к фундаментальным уязвимостям:
Даже при высокой энтропии входных данных Math.random()
не предназначен для защиты от анализа состояния генератора.
Web Crypto API унифицирован на уровне спецификации, но реализация зависит от платформы:
/dev/urandom, macOS SecRandom)cryptoПри этом Math.random() всегда остаётся частью
JavaScript-движка и не имеет доступа к криптографическим источникам
системы.
CSPRNG в Web Crypto API проходит набор криптографических тестов:
PRNG может проходить базовые статистические проверки, но проваливать криптографические сценарии анализа.
Генерация через Web Crypto API обычно медленнее, чем
Math.random(), поскольку:
Однако эта стоимость оправдана задачами безопасности, где предсказуемость критична.
Разделение областей применения строго определяется требованиями к устойчивости:
Math.random() применяется для визуальных эффектов,
симуляций, некритичных расчетов
crypto.getRandomValues() применяется для:
PRNG ориентирован на воспроизводимость и вычислительную эффективность, тогда как CSPRNG ориентирован на непредсказуемость и криптографическую стойкость. Эта разница делает их несовместимыми по области применения, несмотря на внешнее сходство результата — последовательности чисел.