Криптографическая стойкость любых операций в JavaScript, связанных с
ключами, токенами, подписями и идентификаторами, напрямую зависит от
качества генератора случайных чисел. В контексте Jsrsasign этот аспект
реализован через криптографически стойкие генераторы, интегрированные в
пространство KJUR.crypto.
Использование Math.random() в криптографических задачах
приводит к предсказуемости значений. Алгоритм генерации псевдослучайных
чисел в JavaScript не предназначен для защиты данных и может быть
восстановлен при наличии достаточного количества наблюдений.
Типичные проблемы слабой генерации:
Любая криптографическая операция, основанная на таком источнике, теряет смысл как средство защиты.
Jsrsasign использует специализированный модуль
SecureRandom, реализующий CSPRNG (Cryptographically Secure
Pseudo Random Number Generator). В основе лежат системные источники
энтропии:
window.crypto.getRandomValues в браузереcrypto.randomBytes или аналогичные API в Node.js (при
интеграции через полифилы)Основной принцип заключается в том, что генерация байтов не должна быть воспроизводимой даже при частичном знании внутреннего состояния.
В Jsrsasign генерация случайных данных реализуется через объект
KJUR.crypto.SecureRandom.
Ключевые элементы:
Uint8ArrayВнутренне используется подход, при котором системный генератор заполняет массив фиксированной длины, после чего данные преобразуются в требуемый формат.
var rng = new KJUR.crypto.SecureRandom();
var ba = new Array(32);
rng.nextBytes(ba);
Массив ba заполняется криптографически стойкими
значениями. Каждый элемент представляет байт в диапазоне 0–255.
Часто требуется получение случайных идентификаторов или nonce:
var hex = KJUR.crypto.Util.getRandomHexOfNbytes(16);
Результат — строка из 32 символов, представляющая 16 байт случайных данных.
Такой формат используется для:
В криптографических протоколах важна не только строковая форма, но и числовая интерпретация.
var bi = new KJUR.crypto.BigInteger();
bi.fromBuffer(new KJUR.crypto.SecureRandom().nextBytes(32));
Такая конструкция используется при работе с RSA, DSA и ECC, где требуются случайные значения большой длины.
При создании асимметричных ключей случайность определяет безопасность всей системы.
Пример генерации RSA ключа:
var kp = KEYUTIL.generateKeypair("RSA", 2048);
Внутри процесса генерации происходит многократный вызов
SecureRandom для:
Слабый RNG в этом процессе делает факторизацию ключа практически тривиальной задачей.
В браузерной среде основным источником является:
window.crypto.getRandomValues
Он обеспечивает:
Jsrsasign оборачивает этот API, стандартизируя его использование во всех операциях.
При отсутствии crypto библиотека может переходить на
fallback-режим, что снижает криптографическую стойкость и требует явного
контроля окружения.
В Node.js предпочтительным источником является:
require("crypto").randomBytes
Интеграция с Jsrsasign может происходить через адаптер, обеспечивающий совместимость интерфейса SecureRandom с системным RNG Node.js.
Некоторые реализации PRNG позволяют задавать seed вручную. В криптографии это критическая ошибка, так как делает последовательность воспроизводимой.
var token = Math.random().toString(36);
Такая конструкция не обеспечивает ни уникальности, ни безопасности.
Обрезка случайных значений (например, использование только младших бит) приводит к уменьшению пространства поиска при атаке перебором.
Типичный безопасный подход:
function generateId() {
return KJUR.crypto.Util.getRandomHexOfNbytes(12);
}
Такой идентификатор содержит 96 бит энтропии, что делает перебор практически невозможным при корректной реализации RNG.
В протоколах, реализуемых через Jsrsasign (PKCS#1, PKCS#5, ECDSA), случайность используется на всех уровнях:
Особенно чувствителен ECDSA: повторное использование nonce приводит к восстановлению приватного ключа.
Хотя PBKDF2 основан на паролях, начальный salt должен быть случайным:
var salt = KJUR.crypto.Util.getRandomHexOfNbytes(16);
Предсказуемый salt делает атаки с радужными таблицами эффективными.
SecureRandom в Jsrsasign стремится минимизировать влияние состояния среды:
Это снижает риск восстановления состояния генератора при частичной компрометации.
При низкоуровневых операциях часто требуется работа напрямую с байтами:
var rng = new KJUR.crypto.SecureRandom();
var bytes = [];
rng.nextBytes(bytes);
Далее байты могут быть преобразованы в:
Каждое преобразование сохраняет исходную энтропию без потерь при корректной реализации.
Косвенные признаки проблем с RNG:
Использование системного crypto API минимизирует такие
риски, так как генерация переносится на уровень ОС.
Криптографическая библиотека может быть математически корректной, но при слабом генераторе случайных чисел вся система деградирует до уровня предсказуемого протокола.
SecureRandom в Jsrsasign выступает фундаментальным компонентом, от которого зависят: