Гибридное шифрование строится на разделении ответственности между двумя криптографическими подходами:
Классическая проблема асимметричных алгоритмов заключается в их низкой производительности. Симметричные алгоритмы, наоборот, быстры, но требуют заранее общего секрета. Гибридная схема объединяет их сильные стороны.
В контексте TweetNaCl.js это выражается через комбинацию:
nacl.box — асимметричное шифрование на основе
Curve25519 + XSalsa20-Poly1305nacl.secretbox — симметричное шифрование на основе
XSalsa20-Poly1305Механизм публичного шифрования:
Основные функции:
nacl.box.keyPair() — генерация ключевой парыnacl.box.before(publicKey, secretKey) — вычисление
общего секретаnacl.box(message, nonce, publicKey, secretKey) —
шифрованиеnacl.box.open(...) — расшифрованиеСимметричное шифрование:
Функции:
nacl.secretbox(message, nonce, key)nacl.secretbox.open(ciphertext, nonce, key)Асимметричное шифрование в чистом виде плохо подходит для:
Симметричное шифрование не решает проблему:
Гибридная схема решает обе задачи:
Гибридная криптосистема обычно строится по модели:
В TweetNaCl.js роль KEM выполняет:
nacl.box.before() или nacl.boxРоль DEM выполняет:
nacl.secretboxПри использовании Curve25519 обе стороны могут вычислить общий секрет:
import nacl from "tweetnacl";
import util from "tweetnacl-util";
const alice = nacl.box.keyPair();
const bob = nacl.box.keyPair();
const aliceShared = nacl.box.before(bob.publicKey, alice.secretKey);
const bobShared = nacl.box.before(alice.publicKey, bob.secretKey);
Оба значения aliceShared и bobShared
идентичны.
Ключевая особенность:
Полученный shared secret нельзя всегда напрямую использовать как ключ
для secretbox. Обычно его:
Простой вариант:
const symmetricKey = aliceShared;
Более строгий вариант:
const symmetricKey = nacl.hash(aliceShared).slice(0, 32);
После получения симметричного ключа используется быстрый механизм:
const nonce = nacl.randomBytes(24);
const message = util.decodeUTF8("секретные данные");
const encrypted = nacl.secretbox(message, nonce, symmetricKey);
Расшифрование:
const decrypted = nacl.secretbox.open(encrypted, nonce, symmetricKey);
const text = util.encodeUTF8(decrypted);
const alice = nacl.box.keyPair();
const bob = nacl.box.keyPair();
const shared = nacl.box.before(bob.publicKey, alice.secretKey);
const key = shared;
const nonce = nacl.randomBytes(24);
const msg = util.decodeUTF8("конфиденциальное сообщение");
const cipher = nacl.secretbox(msg, nonce, key);
const plain = nacl.secretbox.open(cipher, nonce, key);
const result = util.encodeUTF8(plain);
TweetNaCl.js уже содержит встроенный механизм гибридного шифрования:
const nonce = nacl.randomBytes(24);
const message = util.decodeUTF8("данные");
const encrypted = nacl.box(
message,
nonce,
bob.publicKey,
alice.secretKey
);
Расшифрование:
const decrypted = nacl.box.open(
encrypted,
nonce,
alice.publicKey,
bob.secretKey
);
В этом случае библиотека сама:
Nonce является критическим элементом безопасности:
Практический подход:
const nonce = nacl.randomBytes(24);
Для потоковых систем nonce часто:
Одной из частых ошибок является повторное использование одного и того же ключа для разных целей.
Корректная схема:
При необходимости можно разделять:
const chatKey = nacl.hash(shared).slice(0, 32);
const fileKey = nacl.hash(chatKey).slice(0, 32);
Ассиметрическая часть (Curve25519):
Симметрическая часть (XSalsa20-Poly1305):
Это делает модель оптимальной для:
Такая модель позволяет снизить нагрузку и одновременно сохранить криптографическую стойкость канала связи