Источники энтропии в криптографических библиотеках определяют устойчивость всех последующих операций: генерации ключей, nonce, одноразовых значений и любых случайных идентификаторов. В контексте TweetNaCl.js и nacl.js функция случайных байтов — это фундаментальный строительный блок, от которого зависит безопасность всей криптосистемы.
В криптографии случайность не является абстрактным понятием. Она должна быть:
Любая деградация этих свойств превращает ключи и nonce в уязвимость, а не защиту. Поэтому nacl.randomBytes в экосистеме TweetNaCl.js всегда опирается на системные криптографические источники, а не на псевдослучайные генераторы общего назначения.
В среде браузера основной механизм получения криптографически стойких случайных значений — Web Crypto API:
window.crypto.getRandomValuesЭтот интерфейс реализуется непосредственно браузером и использует энтропию операционной системы. Он гарантирует:
В типичной реализации TweetNaCl.js в браузере функция генерации случайных байтов выглядит концептуально так:
function randomBytes(n) {
const array = new Uint8Array(n);
crypto.getRandomValues(array);
return array;
}
Ключевой момент заключается в том, что Web Crypto API:
Даже при высокой нагрузке или многопоточности результат остаётся криптографически корректным.
В Node.js источником энтропии выступает модуль crypto,
который опирается на системные CSPRNG (Cryptographically Secure Pseudo
Random Number Generator).
Основной метод:
require('crypto').randomBytesПринцип работы:
/dev/urandom в Linux,
CryptGenRandom в Windows)Пример реализации:
const crypto = require('crypto');
function randomBytes(n) {
return crypto.randomBytes(n);
}
В отличие от браузера, Node.js может возвращать Buffer,
а не Uint8Array, хотя по сути это один и тот же бинарный
массив с разной обёрткой.
Библиотека TweetNaCl.js изначально спроектирована как минималистичная и не зависящая от окружения. Поэтому функция генерации случайных байтов не жёстко зашита, а определяется внешне.
Типичная архитектура:
crypto.getRandomValuescrypto.randomBytesВнутренне это выглядит как присваивание:
nacl.randomBytes = function (n) {
// реализация зависит от среды
};
Идея заключается в том, что криптографическая библиотека не должна сама угадывать среду, а должна получать корректный источник энтропии извне.
Все ключевые операции NaCl зависят от randomBytes:
Ошибка в этом слое приводит к следующим последствиям:
Важно различать:
| Тип генератора | Пример | Применимость |
|---|---|---|
| CSPRNG | crypto.getRandomValues | криптография |
| PRNG | Math.random | только для UI/логики |
| LCG/MT | внутренние алгоритмы | моделирование |
Использование Math.random в контексте nacl.randomBytes полностью разрушает безопасность, поскольку:
И браузер, и Node.js в конечном счёте используют энтропию операционной системы:
ОС агрегирует эти источники в пул энтропии, из которого CSPRNG извлекает данные.
Исторически существовали среды без Web Crypto API и без Node crypto:
В таких случаях библиотеки либо:
Типичный fallback:
function randomBytes(n) {
const arr = new Array(n);
for (let i = 0; i < n; i++) {
arr[i] = (Math.random() * 256) | 0;
}
return new Uint8Array(arr);
}
Такой код категорически непригоден для криптографии, но иногда встречается в учебных или деградированных сборках.
Операции генерации случайных байтов часто вызываются массово:
Поэтому реализация:
Node.js crypto.randomBytes оптимизирован на уровне C++ и
работает значительно быстрее чисто JS-реализаций.
В NaCl-архитектуре nonce не обязан быть секретным, но обязан быть уникальным. Поэтому nacl.randomBytes часто используется именно для:
Повтор nonce с тем же ключом приводит к:
В реальных проектах обычно применяется проверка окружения:
const getRandomBytes = (n) => {
if (typeof crypto !== 'undefined' && crypto.getRandomValues) {
const arr = new Uint8Array(n);
crypto.getRandomValues(arr);
return arr;
}
if (typeof require !== 'undefined') {
return require('crypto').randomBytes(n);
}
throw new Error('No secure random source available');
};
Такая схема исключает деградированный режим.
Подмена randomBytes на Math.random
Кэширование случайных значений
Использование одного seed для генерации всех ключей
Игнорирование различий Buffer / Uint8Array
Ручная реализация PRNG
TweetNaCl.js минимизирует поверхность атаки, поэтому:
Это снижает количество потенциальных уязвимостей, но увеличивает ответственность разработчика, интегрирующего библиотеку.
Если системный источник временно недоступен:
Попытка продолжить работу в таком состоянии означает нарушение базовых криптографических предположений модели безопасности.