Криптографическая случайность в JavaScript опирается на два принципиально разных подхода: системный источник энтропии, предоставляемый средой выполнения, и программно реализованные генераторы псевдослучайных чисел внутри библиотек общего назначения.
В современных браузерах и Node.js доступен интерфейс Web Crypto API, предоставляющий метод генерации криптографически стойких случайных значений:
crypto.getRandomValues(typedArray)
Этот метод заполняет переданный массив значениями, полученными из операционной системы. В основе лежит CSPRNG (Cryptographically Secure Pseudo-Random Number Generator), который использует системные источники энтропии: движения мыши, события устройства, аппаратные шумы и специализированные инструкции процессора.
Ключевая особенность — отсутствие предсказуемости. Даже при полном знании состояния программы восстановить последовательность значений невозможно.
Пример генерации случайного идентификатора:
const array = new Uint8Array(16);
crypto.getRandomValues(array);
const id = Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
Особенности:
Uint8Array, Uint32Array и др.)В Node.js аналогичный интерфейс доступен через модуль
crypto:
import { randomFillSync } from 'crypto';
const buffer = Buffer.alloc(16);
randomFillSync(buffer);
или через глобальный crypto.getRandomValues в новых
версиях среды.
Библиотека Crypto-js предоставляет собственный механизм генерации случайных данных:
CryptoJS.lib.WordArray.random(16)
На первый взгляд функциональность аналогична, однако источник случайности принципиально иной.
Внутри Crypto-js используется цепочка fallback-реализаций:
window.crypto — он используетсяMath.random()Критическая проблема заключается в том, что
Math.random() не является криптографически стойким
генератором. Он предназначен для моделирования и визуализации, но не для
безопасности.
Пример:
const key = CryptoJS.lib.WordArray.random(32);
В зависимости от среды выполнения этот код может опираться либо на безопасный источник, либо на предсказуемый PRNG.
crypto.getRandomValues:
Crypto-js:
Web Crypto API:
Crypto-js:
Math.random()Генерация через crypto.getRandomValues выполняется на
уровне нативного кода и обычно быстрее при больших объёмах данных.
Crypto-js реализует обёртки над массивами и дополнительную обработку WordArray, что увеличивает накладные расходы.
crypto.getRandomValues:
TypedArrayconst arr = new Uint8Array(32);
crypto.getRandomValues(arr);
Crypto-js:
WordArrayconst wa = CryptoJS.lib.WordArray.random(32);
Преобразование между форматами требует дополнительных операций:
const wordArray = CryptoJS.lib.WordArray.create(arr);
Использование случайных значений в криптографии затрагивает несколько критических областей:
Любая предсказуемость в этих значениях приводит к компрометации всей криптосистемы.
Пример уязвимого подхода:
const salt = CryptoJS.lib.WordArray.random(16);
Если среда использует Math.random, атакующий может
восстановить возможные значения соли и провести атаки на словарной
основе или предвычисление ключей.
Корректный подход:
const salt = new Uint8Array(16);
crypto.getRandomValues(salt);
Web Crypto API проектировался как часть стандарта безопасных веб-операций. Он:
Crypto-js — это прикладная библиотека, ориентированная на совместимость и удобство, а не на гарантию системной безопасности.
Наиболее распространённые проблемы:
WordArray.random для генерации
ключейОсобенно опасен сценарий кросс-платформенного кода, где браузер
использует crypto, а серверная среда деградирует до
Math.random.
При использовании Crypto-js в современных приложениях корректная архитектура разделяет генерацию случайности и криптографические операции.
Генерация случайных данных:
const iv = new Uint8Array(16);
crypto.getRandomValues(iv);
Использование в Crypto-js:
const ivWordArray = CryptoJS.lib.WordArray.create(iv);
Далее IV используется в алгоритмах шифрования:
const encrypted = CryptoJS.AES.encrypt(message, key, {
iv: ivWordArray
});
| Среда | crypto.getRandomValues | Crypto-js random |
|---|---|---|
| Современный браузер | CSPRNG ОС | CSPRNG через crypto |
| Node.js ≥ 19 | доступен глобально | через crypto модуль |
| Старые браузеры | отсутствует | Math.random fallback |
| Изолированные окружения | зависит от реализации | непредсказуемо |
Системный генератор случайных чисел представляет собой внешний доверенный источник энтропии. Crypto-js, напротив, является внутренней реализацией, зависящей от качества окружения.
Это различие определяет границу между криптографически безопасным кодом и условно безопасным псевдослучайным поведением.
Использование crypto.getRandomValues формирует
предсказуемую модель безопасности на уровне платформы, тогда как
Crypto-js требует дополнительного контроля и проверки среды
выполнения.