В Stanford JavaScript Crypto Library генерация криптографически
стойких случайных значений основана на глобальном генераторе
sjcl.random. Его устойчивость напрямую зависит от качества
и количества накопленной энтропии. Энтропия здесь понимается как мера
непредсказуемости входных данных, используемых для инициализации
внутреннего состояния генератора псевдослучайных чисел.
Ключевая особенность модели заключается в том, что генератор не считается готовым к криптографически безопасной работе до достижения определённого порога энтропии. Это защищает от ситуации, когда недостаточно случайные данные приводят к предсказуемым ключам, IV или nonce.
sjcl.random в браузерной среде собирает энтропию из
событий пользовательской активности и системных данных. Основные
источники:
Date.now,
performance.now)addEntropyКаждое событие преобразуется в числовую форму и добавляется в пул энтропии с оценкой количества битов случайности.
sjcl.random.addEntropy(data, 32, "mouse");
Во втором аргументе указывается оценка количества бит энтропии, что критически важно: библиотека не вычисляет истинную энтропию, а опирается на доверенную оценку источника.
Внутреннее состояние sjcl.random представляет собой пул
энтропии, который постепенно заполняется поступающими данными. Эти
данные не используются напрямую для генерации чисел, а перемешиваются в
состоянии генератора.
Каждое добавление энтропии проходит через хеш-функции (обычно SHA-256), что обеспечивает диффузию и предотвращает восстановление исходных событий.
Пул можно рассматривать как накопитель, который должен достичь определённого уровня насыщения перед тем, как генератор станет криптографически допустимым.
Генератор имеет параметр уровня безопасности — paranoia level, который определяет, сколько энтропии необходимо накопить для начала генерации безопасных чисел.
sjcl.random.setDefaultParanoia(10);
Чем выше уровень, тем больше энтропии требуется. Это напрямую влияет на задержку доступности генератора.
Типичная градация:
Система не блокирует выполнение кода, но может временно выдавать предупреждение о недостаточной готовности.
isReady, getProgressОсновной механизм контроля состояния энтропии реализован через метод
isReady.
if (sjcl.random.isReady(10)) {
const bytes = sjcl.random.randomWords(8);
}
Метод принимает уровень паранойи и возвращает:
1 — достаточно энтропии накоплено0 — энтропия недостаточнаДополнительно используется getProgress, позволяющий
оценить процент готовности.
const progress = sjcl.random.getProgress(10);
Результат обычно выражается в диапазоне от 0 до
1, где:
0 — полное отсутствие накопленной энтропии1 — достаточный уровень для выбранного paranoia
levelЭта функция используется в системах, где важно визуализировать или контролировать состояние генератора до начала криптографических операций.
sjcl.random поддерживает событийную модель. Это
позволяет реагировать на момент достижения достаточного уровня
энтропии.
sjcl.random.addEventListener("seeded", function () {
const key = sjcl.random.randomWords(8);
});
Событие seeded вызывается один раз при переходе
состояния в “готово”. Это важный механизм для асинхронных приложений,
где генерация ключей не должна выполняться до завершения накопления
энтропии.
Дополнительно может использоваться событие изменения состояния, позволяющее отслеживать постепенное заполнение пула.
Криптографические операции, зависящие от случайности, должны учитывать состояние генератора до выполнения.
Типичный паттерн:
function secureRandomBytes(n) {
if (!sjcl.random.isReady(10)) {
throw new Error("Недостаточно энтропии");
}
return sjcl.random.randomWords(n);
}
В более устойчивых системах вместо исключения применяется отложенное выполнение:
function waitForEntropy(callback) {
if (sjcl.random.isReady(10)) {
callback();
} else {
sjcl.random.addEventListener("seeded", callback);
}
}
Такой подход предотвращает использование слабого состояния генератора.
В браузерной среде проблема недостатка энтропии особенно заметна при:
В этих условиях пул энтропии может оставаться пустым длительное время. Для компенсации используется:
addEntropysjcl.random.addEntropy(Date.now(), 32, "init-time");
Однако такие источники не всегда эквивалентны реальной пользовательской энтропии, и их вклад ограничен.
На практике проверка достаточности энтропии часто игнорируется, что приводит к ряду проблем:
seededОсобенно критична ситуация, когда randomWords вызывается
сразу после загрузки страницы без проверки состояния:
const key = sjcl.random.randomWords(8);
В таком случае результат может зависеть от предсказуемого seed, что снижает криптографическую стойкость всей системы.
Корректная модель всегда предполагает явную проверку состояния генератора перед использованием его выхода в безопасности-критичных операциях.