В основе генерации криптографически стойких случайных чисел в Stanford Javascript Crypto Library лежит механизм накопления энтропии. Он реализован через систему энтропийных пулов, которые постепенно заполняются данными из различных источников неопределённости среды исполнения JavaScript.
В SJCL используется несколько параллельных пулов энтропии, обычно 32. Такая структура заимствована из подходов криптографической библиотеки Fortuna.
Каждый пул представляет собой:
Ключевая идея состоит в том, что данные не помещаются в единый буфер, а распределяются по пулам циклически, снижая риск атак на предсказуемость состояния генератора.
Пулам назначается индекс, зависящий от количества уже добавленных энтропийных событий. Обычно используется следующий принцип распределения:
Такое распределение обеспечивает постепенное смешивание информации с разной «глубиной истории».
SJCL не полагается на единственный источник случайности. Вместо этого библиотека агрегирует данные из множества каналов среды браузера или Node.js.
Типичные источники:
Наиболее важный источник в браузере:
Каждое событие преобразуется в набор чисел:
Микроскопические различия во времени исполнения:
Менее надёжные, но используемые как дополнительный шум:
Если доступны:
Они могут использоваться как усилитель энтропии или первичный источник в окружениях с низкой интерактивностью.
Основной интерфейс накопления данных реализован через функцию:
sjcl.random.addEntropy(data, estimatedEntropyBits, source)
Параметры:
data — числовой массив или одиночное значениеestimatedEntropyBits — оценка количества случайных
битsource — идентификатор источникаКаждое добавление проходит несколько этапов:
Система не может точно измерить случайность, поэтому используется эвристика. Например:
Эти оценки консервативны, чтобы избежать переоценки качества данных.
Данные распределяются циклически:
Каждое значение добавляется в массив пула, но не используется сразу. Это предотвращает локальные предсказуемые зависимости.
SJCL использует автоматические сборщики (entropy collectors), которые подключаются к DOM или runtime.
Типичная инициализация включает:
mousemovemousedown, mouseupkeydown, keyuptouchstart, touchmoveКаждый обработчик извлекает «сырые» данные и передаёт их в систему энтропии.
Пример логики:
function mouseEvent(e) {
var x = e.clientX;
var y = e.clientY;
var t = (new Date()).getTime();
sjcl.random.addEntropy([x, y, t], 2, "mouse");
}
Важно, что SJCL не хранит полную историю событий — только агрегированную информацию.
Состояние системы энтропии определяется через:
sjcl.random.isReady(threshold)
Где threshold — требуемое количество бит.
Система проходит несколько уровней:
Также используется:
sjcl.random.getProgress(threshold)
возвращающая долю накопленной энтропии.
Когда накоплено достаточное количество энтропии, происходит инициализация PRNG.
Внутренне SJCL использует Fortuna-подобный механизм:
Процесс происходит лениво:
После инициализации используется функция:
sjcl.random.randomWords(n, paranoia)
n — количество 32-битных словparanoia — уровень требуемой безопасностиЕсли энтропии недостаточно, функция может:
SJCL вводит концепцию уровней безопасности:
Чем выше уровень, тем больше требуется накопленных бит перед генерацией.
Основные угрозы:
Если злоумышленник знает поведение пользователя, он может частично восстановить входные данные. Поэтому SJCL:
Если генератор используется до накопления энтропии, результат может быть слабым. Для этого применяется:
Fortuna-подобная архитектура предотвращает повторное использование одних и тех же seed-значений без пересидирования.
В серверных средах или headless-окружениях отсутствуют мышь и клавиатура. В этом случае SJCL использует альтернативные источники:
При этом энтропийный пул заполняется медленнее и может требовать явной инициализации.
Каждый пул представляет собой:
Перед использованием данные проходят через криптографическую функцию (обычно SHA-256 или аналог в SJCL), что обеспечивает:
Энтропийный пул является фундаментом всей системы генерации случайных чисел. Его корректное заполнение определяет:
Недостаточная энтропия приводит к:
Пулам не требуется очистка в классическом смысле. Вместо этого используется:
Это предотвращает:
В некоторых конфигурациях SJCL может заменять стандартный
Math.random:
Это обеспечивает единообразное поведение генерации случайных чисел во всей системе.
Вся система может быть представлена как поток: