nacl.secretbox реализует симметричное шифрование на
основе алгоритма Salsa20 (потоковый шифр) и аутентификационного кода
Poly1305. Комбинация этих двух примитивов формирует схему authenticated
encryption (AEAD), в которой одновременно обеспечивается:
Ключевая особенность подхода заключается в том, что
secretbox не разделяет шифрование и проверку целостности —
обе операции выполняются как единый процесс.
В основе работы secretbox лежит схема
XSalsa20-Poly1305:
Таким образом, результатом является:
ciphertext + authentication tag
Любое изменение зашифрованных данных приводит к провалу проверки при расшифровке.
nacl.secretbox использует симметричный ключ длиной 32
байта.
const key = nacl.randomBytes(32);
Свойства ключа:
Ключ не должен быть производным от пароля без использования KDF (например, Argon2 или PBKDF2), так как библиотека не выполняет деривацию ключа самостоятельно.
Nonce (number used once) — это 24-байтовое значение, которое обязано быть уникальным для каждой операции шифрования с одним и тем же ключом.
const nonce = nacl.randomBytes(24);
Свойства nonce:
Функция шифрования:
nacl.secretbox(message, nonce, key)
Параметры:
message — Uint8Array с исходными даннымиnonce — 24-байтовый noncekey — 32-байтовый секретный ключПример:
const message = new TextEncoder().encode("секретное сообщение");
const key = nacl.randomBytes(32);
const nonce = nacl.randomBytes(24);
const boxed = nacl.secretbox(message, nonce, key);
Результат:
boxed содержит зашифрованный текст + MACФункция расшифровки:
nacl.secretbox.open(boxedMessage, nonce, key)
Пример:
const opened = nacl.secretbox.open(boxed, nonce, key);
if (!opened) {
throw new Error("Ошибка расшифровки или повреждение данных");
}
const decoded = new TextDecoder().decode(opened);
Особенности поведения:
nullПроцесс шифрования можно представить в виде последовательности:
Генерация keystream через XSalsa20:
stream = XSalsa20(key, nonce)XOR исходного сообщения с keystream:
ciphertext = message XOR streamВычисление Poly1305 MAC:
tag = Poly1305(ciphertext)Объединение результата:
output = ciphertext + tagПри расшифровке выполняется обратная процедура с обязательной проверкой MAC перед восстановлением сообщения.
Критическое требование:
Практическая схема:
const nonce = nacl.randomBytes(24);
Для потоковой передачи данных используется счётчик или комбинированный nonce (например, timestamp + random suffix).
Рекомендуемые подходы:
secretbox не накладывает ограничений на размер данных,
однако:
Самая критическая ошибка:
Все входные данные должны быть бинарными:
const message = new TextEncoder().encode("text");
Передача строки напрямую недопустима.
const msg = nacl.secretbox.open(box, nonce, key);
Если msg === null, дальнейшая обработка недопустима.
Для интеграции с текстовыми данными используются:
TextEncoder / TextDecoder
Пример полного цикла:
const encoder = new TextEncoder();
const decoder = new TextDecoder();
const message = encoder.encode("данные");
const key = nacl.randomBytes(32);
const nonce = nacl.randomBytes(24);
const encrypted = nacl.secretbox(message, nonce, key);
const decrypted = nacl.secretbox.open(encrypted, nonce, key);
const text = decoder.decode(decrypted);
Характеристики:
Ограничения:
nacl.secretbox — симметричное шифрованиеnacl.box — асимметричное шифрование (Curve25519)nacl.sign — цифровая подписьsecretbox применяется в случаях, где:
Формат результата:
[ ciphertext || 16-byte Poly1305 tag ]
Nonce хранится отдельно и не входит в результат, поэтому его необходимо передавать вместе с сообщением через внешний протокол (например, JSON или бинарный контейнер).