Архитектура PRNG в SJCL

В библиотеке SJCL генератор псевдослучайных чисел (PRNG) реализован как криптографически стойкая система, построенная вокруг потокового шифра и механизма накопления энтропии. Архитектура ориентирована на работу в среде браузера, где отсутствуют гарантированные источники качественной случайности, и потому особое внимание уделяется сбору и оценке энтропии.

PRNG в SJCL представлен объектом sjcl.prng, который управляет внутренним состоянием, пулами энтропии и механизмами переработки случайных данных. Его архитектура включает несколько ключевых компонентов:

  • аккумуляторы энтропии (entropy pools)
  • счётчики и оценки энтропии
  • криптографическое ядро генерации
  • механизм reseed (пересева)
  • интерфейсы добавления внешней энтропии

Пулы энтропии и их роль

Для повышения устойчивости к атакам используется несколько пулов энтропии. Каждый пул представляет собой хэш-аккумулятор (обычно на основе SHA-256), в который поступают события из различных источников:

  • движения мыши
  • нажатия клавиш
  • тайминги событий
  • системные значения времени

Каждый пул индексируется и используется поочерёдно, чтобы предотвратить предсказуемость накопления энтропии.

Особенности:

  • количество пулов фиксировано (обычно 32)
  • каждый пул обновляется независимо
  • используется циклический выбор пула для записи новых данных

Это снижает риск компрометации всей системы при утечке состояния одного пула.


Оценка энтропии

Каждое добавление случайных данных сопровождается оценкой количества энтропии в битах. Это значение передаётся вместе с данными:

sjcl.random.addEntropy(data, estimatedEntropy, source);

Где:

  • data — входные данные
  • estimatedEntropy — оценка случайности
  • source — строка-идентификатор источника

PRNG ведёт внутренний счётчик накопленной энтропии и не разрешает генерацию криптографически стойких чисел, пока не достигнут минимальный порог (обычно 128 бит).


Криптографическое ядро генерации

Основу генератора составляет потоковый шифр, реализованный через блочный шифр AES в режиме счётчика (CTR). Внутреннее состояние PRNG включает:

  • ключ (key)
  • счётчик (counter)

Генерация случайных данных происходит путём шифрования возрастающего счётчика:

output = AES_encrypt(counter, key);
counter++;

Ключевые свойства:

  • детерминированность при фиксированном состоянии
  • высокая производительность
  • криптографическая стойкость при условии секретности ключа

Механизм reseed

Reseed — это процесс обновления внутреннего состояния генератора на основе накопленной энтропии. Он выполняется:

  • при достижении достаточного уровня энтропии
  • периодически при использовании генератора
  • при явном вызове

Во время reseed:

  1. Собираются данные из пулов энтропии
  2. Объединяются в один буфер
  3. Пропускаются через хэш-функцию
  4. Используются для обновления ключа PRNG

Формально:

new_key = SHA256(old_key || entropy_data)

Это обеспечивает:

  • обновление состояния
  • защиту от восстановления предыдущих значений (forward secrecy)
  • защиту от предсказания будущих значений (backward secrecy)

Уровни готовности генератора

PRNG в SJCL имеет несколько состояний готовности:

  1. Неинициализирован — недостаточно энтропии
  2. Готов частично — возможно использование, но не рекомендуется для криптографии
  3. Готов полностью — безопасен для криптографических операций

Метод проверки:

sjcl.random.isReady();

Возвращает уровень готовности:

  • 0 — не готов
  • 1 — частично готов
  • 2 — полностью готов

Источники энтропии

В браузерной среде SJCL автоматически подключает следующие источники:

  • события пользователя (mouse, keyboard)
  • Date.now() и performance.now()
  • данные окружения (например, navigator)

При наличии поддерживаемого API используется:

crypto.getRandomValues()

Это предпочтительный источник, так как он предоставляет криптографически стойкие случайные данные от операционной системы.


Добавление внешней энтропии

Допускается ручное добавление энтропии:

sjcl.random.addEntropy([1,2,3,4], 2, "manual");

Рекомендуется использовать:

  • случайные значения с сервера
  • аппаратные источники
  • пользовательские события с высокой непредсказуемостью

Важно корректно оценивать энтропию, так как завышение оценки может привести к ослаблению безопасности.


Генерация случайных чисел

Основной метод:

sjcl.random.randomWords(n, paranoia);

Где:

  • n — количество 32-битных слов
  • paranoia — уровень требуемой энтропии

Пример:

var random = sjcl.random.randomWords(4, 6);

Уровень paranoia влияет на:

  • частоту reseed
  • требования к накопленной энтропии

Защита от атак

Архитектура PRNG в SJCL учитывает несколько классов атак:

1. Предсказание состояния

  • решается использованием AES и регулярным reseed

2. Компрометация состояния

  • защита через обновление ключа
  • использование нескольких пулов

3. Недостаток энтропии

  • строгая проверка уровня готовности

4. Replay-атаки

  • счётчик гарантирует уникальность выходных блоков

Внутренние структуры данных

Ключевые поля объекта PRNG:

  • _pools — массив хэш-пулов
  • _poolEntropy — оценка энтропии по пулам
  • _reseedCount — количество reseed
  • _key — текущий ключ
  • _counter — счётчик
  • _strength — текущий уровень энтропии

Особенности реализации в браузере

  • асинхронное накопление энтропии
  • зависимость от пользовательской активности
  • необходимость fallback-механизмов
  • использование Web Crypto API при наличии

Практические ограничения

  • при отсутствии активности пользователя генератор может долго оставаться неинициализированным
  • на сервере (Node.js) предпочтительнее использовать встроенные средства (crypto.randomBytes)
  • оценка энтропии остаётся приближённой и не гарантирует абсолютную случайность

Поведение при недостатке энтропии

При попытке генерации без достаточной энтропии:

  • выбрасывается исключение
  • или возвращается статус “не готов”

Это предотвращает использование слабых случайных данных в криптографических операциях.


Расширяемость архитектуры

PRNG допускает:

  • добавление новых источников энтропии
  • изменение параметров reseed
  • интеграцию с внешними криптографическими модулями

Это делает SJCL гибким инструментом для различных сценариев, включая браузерные приложения с повышенными требованиями к безопасности.