Генерация случайных байт и слов

Архитектура генератора случайных чисел

В основе криптографической стойкости Stanford JavaScript Crypto Library лежит модуль sjcl.random, реализующий накопление энтропии и генерацию псевдослучайных значений, пригодных для криптографических операций.

Генератор не опирается на один источник случайности. Вместо этого используется пул энтропии, который наполняется событиями окружения:

  • движения мыши
  • события клавиатуры
  • изменения времени между событиями
  • данные от window.crypto (если доступно)
  • системные источники браузера

Каждое событие преобразуется в числовые данные и добавляется в внутренний буфер энтропии.

Ключевой принцип — накопление достаточного количества неопределённости перед генерацией криптографически стойких значений.


Представление данных: слова и байты

SJCL оперирует не байтами напрямую, а 32-битными словами (word).

Определение слова

Слово (word) — это беззнаковое 32-битное целое число.

Один элемент массива слов:

[0x12345678, 0x9abcdef0]

Такой формат используется во всех внутренних криптографических операциях: шифрование, хеширование, генерация ключей.

Байты и слова

Преобразование:

  • 1 слово = 4 байта
  • массив слов = поток байтов кратный 4

При необходимости байтового представления используется преобразование:

  • sjcl.codec.hex
  • sjcl.codec.base64
  • sjcl.codec.utf8String

Основной генератор случайных слов

Функция генерации:

sjcl.random.randomWords(n, paranoia)

Параметры

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

Пример

var words = sjcl.random.randomWords(4);

Результат:

  • массив из 4 случайных 32-битных чисел
  • общий размер: 16 байт

Уровни паранойи

В SJCL используется концепция уровней требуемой энтропии:

Уровень Описание
0 минимальная защита
1 базовая криптография
2 средний уровень
3 высокий уровень
4 максимальная защита

Чем выше уровень, тем больше энтропии требуется перед генерацией результата.

Пример:

var strong = sjcl.random.randomWords(8, 3);

Если энтропии недостаточно, выполнение блокируется.


Блокирующее поведение генерации

При недостатке энтропии функция может:

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

Для асинхронного ожидания используется callback:

sjcl.random.randomWords(4, 3, function (words) {
    console.log(words);
});

Такой подход предотвращает использование слабых случайных данных.


Генерация случайных байтов

Хотя базовая единица — слово, часто требуется байтовый поток.

Преобразование слов в байты

var words = sjcl.random.randomWords(2);

var hex = sjcl.codec.hex.fromBits(words);

Каждые 2 слова:

  • 8 байт данных
  • представление в hex — 16 символов

Использование в криптографических ключах

Случайные слова используются для:

  • генерации ключей AES
  • создания nonce
  • формирования соли (salt)
  • инициализационных векторов (IV)

Пример генерации ключа:

var key = sjcl.random.randomWords(8, 2);
var aesKey = new sjcl.cipher.aes(key);

Размер ключа:

  • 8 слов = 256 бит

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

Модуль sjcl.random поддерживает подключение источников вручную.

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

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

Параметры:

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

Пример:

sjcl.random.addEntropy([mouseX, mouseY], 2, "mouse");

Встроенные сборщики энтропии

SJCL может автоматически подключать:

  • addEventListener для mousemove
  • события клавиатуры
  • таймеры performance.now()

Пример включения сборщика:

sjcl.random.startCollectors();

После этого библиотека начинает автоматически наполнять пул энтропии.


Проверка готовности генератора

Перед генерацией можно проверить уровень энтропии:

if (sjcl.random.isReady()) {
    var words = sjcl.random.randomWords(4);
}

Также доступна более детальная проверка:

sjcl.random.getProgress(3);

Результат:

  • число от 0 до 1
  • отражает готовность на заданном уровне паранойи

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

В некоторых сценариях требуется сброс пула:

sjcl.random.reset();

После сброса:

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

Практика генерации криптографической соли

Соль часто используется для хеширования паролей:

var salt = sjcl.random.randomWords(4, 3);
var saltHex = sjcl.codec.hex.fromBits(salt);

Размер:

  • 4 слова = 128 бит
  • достаточный уровень для уникальности

Генерация nonce

Nonce должен быть уникальным и непредсказуемым:

var nonce = sjcl.random.randomWords(3, 2);

Использование:

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

Ошибки и ограничения

Основные проблемы генерации:

  • недостаточная энтропия
  • отсутствие пользовательских событий в headless-окружениях
  • блокировка callback при высоком уровне paranoia

Решение:

  • предварительный прогрев генератора
  • добавление системной энтропии вручную
  • использование window.crypto как дополнительного источника

Использование в серверных и браузерных средах

В браузере SJCL автоматически получает энтропию из событий DOM.

В Node.js окружении требуется ручное добавление:

sjcl.random.addEntropy(require('crypto').randomBytes(16), 8, "node");

Без этого генератор может оставаться в состоянии “не готов”.


Особенности внутреннего буфера

Пул энтропии:

  • хранит накопленные биты
  • перемешивается криптографическим PRNG
  • обновляется при каждом событии

Внутренний алгоритм обеспечивает:

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

Связь с криптографическими операциями SJCL

Случайные слова используются не изолированно, а как базовый строительный блок:

  • AES ключи формируются из word-массивов
  • HMAC использует случайные соли
  • PBKDF2 требует случайного seed

Таким образом, качество sjcl.random напрямую определяет стойкость всей криптосистемы.