nacl.box реализует схему публично-ключевого шифрования с
аутентификацией сообщений. В основе лежит комбинация Curve25519 для
обмена ключами и XSalsa20-Poly1305 для шифрования и проверки
целостности. Модель предполагает, что у каждой стороны есть пара ключей:
публичный и приватный, а также используется одноразовый nonce для
каждого сообщения.
nacl.box обеспечивает одновременно:
Шифрование всегда выполняется от отправителя к получателю с использованием публичного ключа получателя и приватного ключа отправителя.
Каждый участник коммуникации должен создать собственную пару ключей:
const nacl = require('tweetnacl');
nacl.util = require('tweetnacl-util');
const keyPair = nacl.box.keyPair();
console.log(keyPair.publicKey);
console.log(keyPair.secretKey);
publicKey передаётся другим участникамsecretKey хранится строго локальноРазмер ключей фиксирован:
Nonce (number used once) — это уникальное значение длиной 24 байта, которое обязано быть неповторимым для каждой пары ключей.
const nonce = nacl.randomBytes(nacl.box.nonceLength);
Ключевое правило: повтор nonce с теми же ключами полностью компрометирует безопасность сообщений
Nonce не является секретом, он передаётся вместе с зашифрованным сообщением.
nacl.boxОсновной метод шифрования:
const message = nacl.util.decodeUTF8("Привет");
const box = nacl.box(
message,
nonce,
recipientPublicKey,
senderSecretKey
);
Параметры:
message — Uint8Arraynonce — 24-байтовый уникальный векторrecipientPublicKey — публичный ключ получателяsenderSecretKey — приватный ключ отправителяРезультат:
nacl.box.openПолучатель использует собственный приватный ключ и публичный ключ отправителя:
const decrypted = nacl.box.open(
box,
nonce,
senderPublicKey,
recipientSecretKey
);
const text = nacl.util.encodeUTF8(decrypted);
Если:
результат будет null.
const A = nacl.box.keyPair();
const B = nacl.box.keyPair();
const nonce = nacl.randomBytes(nacl.box.nonceLength);
const message = nacl.util.decodeUTF8("Сообщение от A к B");
const encrypted = nacl.box(
message,
nonce,
B.publicKey,
A.secretKey
);
const decrypted = nacl.box.open(
encrypted,
nonce,
A.publicKey,
B.secretKey
);
const result = nacl.util.encodeUTF8(decrypted);
nacl.box.before)Для оптимизации повторных сообщений между двумя сторонами используется предварительное вычисление общего ключа.
const sharedKey = nacl.box.before(
recipientPublicKey,
senderSecretKey
);
Этот ключ можно использовать для ускоренного шифрования.
box.afterconst encrypted = nacl.box.after(
message,
nonce,
sharedKey
);
box.open.afterconst decrypted = nacl.box.open.after(
encrypted,
nonce,
sharedKey
);
box и
box.beforenacl.boxnacl.box.beforeВсе входные и выходные данные должны быть
Uint8Array.
Часто используется преобразование:
nacl.util.decodeUTF8(str)
nacl.util.encodeUTF8(bytes)
Для бинарных данных часто применяются Base64 или Hex через сторонние библиотеки.
Использование одного nonce с одинаковыми ключами приводит к:
Если публичный ключ не соответствует приватному — расшифровка невозможна.
const decrypted = nacl.box.open(...);
if (!decrypted) {
// сообщение повреждено или подделано
}
nacl.box обеспечивает:
Типичный протокол:
nacl.box{nonce + ciphertext}nacl.box.opennacl.box не ограничен текстом. Он работает с любыми
байтами:
Пример:
const fileBytes = new Uint8Array(fileBuffer);
const encrypted = nacl.box(
fileBytes,
nonce,
B.publicKey,
A.secretKey
);
nacl.box часто применяется как криптографический слой
в: