В распределённых системах каждый сервис становится потенциальной точкой входа для атаки. Даже внутри доверенной инфраструктуры нельзя полагаться на «внутреннюю сеть» как на безопасную среду. Межсервисное взаимодействие должно рассматриваться как недоверенное по умолчанию: каждый запрос — потенциально перехваченный, модифицированный или подделанный.
Криптографическая библиотека TweetNaCl.js (и её интерфейсные обёртки вроде nacl.js) предоставляет минималистичный набор примитивов, достаточный для построения защищённого канала связи между сервисами без необходимости внедрения тяжёлых криптографических стеков.
TweetNaCl.js реализует проверенный набор алгоритмов из семейства NaCl (Networking and Cryptography library). Архитектура ориентирована на простоту и безопасность без конфигурируемых «опасных параметров».
Основные примитивы:
В микросервисной архитектуре каждый сервис рассматривается как автономный участник сети, обладающий собственным ключом:
TweetNaCl.js предоставляет генерацию ключей для асимметричного шифрования:
import nacl from "tweetnacl";
import util from "tweetnacl-util";
const keyPair = nacl.box.keyPair();
const publicKey = keyPair.publicKey;
const secretKey = keyPair.secretKey;
В контексте сервиса:
publicKey публикуетсяsecretKey никогда не покидает сервисМеханизм nacl.box реализует публично-ключевое шифрование
между двумя сторонами: отправителем и получателем.
Каждый участник имеет пару ключей. Для шифрования требуется:
const message = "transfer:1000:account42";
const nonce = nacl.randomBytes(nacl.box.nonceLength);
const encrypted = nacl.box(
util.decodeUTF8(message),
nonce,
receiverPublicKey,
senderSecretKey
);
const decrypted = nacl.box.open(
encrypted,
nonce,
senderPublicKey,
receiverSecretKey
);
const originalMessage = util.encodeUTF8(decrypted);
Nonce (number used once) — обязательный элемент защиты. Повторное использование nonce с тем же ключом приводит к компрометации шифрования.
В межсервисной архитектуре:
randomBytesКогда оба сервиса уже обменялись ключом сессии, эффективнее использовать симметричное шифрование.
const key = nacl.randomBytes(nacl.secretbox.keyLength);
const nonce = nacl.randomBytes(nacl.secretbox.nonceLength);
const message = util.decodeUTF8("update-cache:user:42");
const box = nacl.secretbox(message, nonce, key);
Расшифровка:
const opened = nacl.secretbox.open(box, nonce, key);
const result = util.encodeUTF8(opened);
Шифрование не гарантирует целостность источника без отдельной
проверки подписи. Для этого используется nacl.sign.
Подписывающая сторона:
const keyPair = nacl.sign.keyPair();
const message = util.decodeUTF8("event:order_created:123");
const signed = nacl.sign(message, keyPair.secretKey);
Проверка подписи:
const verified = nacl.sign.open(signed, keyPair.publicKey);
const payload = util.encodeUTF8(verified);
В межсервисной архитектуре важно разделять:
Типовая схема:
Типовой поток выглядит следующим образом:
Отправка защищённого события:
const payload = {
type: "payment",
amount: 250,
currency: "KZT"
};
const serialized = util.decodeUTF8(JSON.stringify(payload));
const signature = nacl.sign(serialized, senderSecretKey);
const nonce = nacl.randomBytes(nacl.box.nonceLength);
const encrypted = nacl.box(
signature,
nonce,
receiverPublicKey,
senderSecretKey
);
const decrypted = nacl.box.open(
encrypted,
nonce,
senderPublicKey,
receiverSecretKey
);
const verified = nacl.sign.open(
decrypted,
senderPublicKey
);
const message = JSON.parse(util.encodeUTF8(verified));
Ключевая проблема межсервисной безопасности — не алгоритмы, а управление ключами.
Практические подходы:
Replay-атаки особенно опасны в микросервисах: злоумышленник повторно отправляет валидное сообщение.
Механизмы защиты:
Пример проверки:
if (Date.now() - payload.timestamp > 30000) {
throw new Error("Message expired");
}
if (nonceCache.has(payload.nonce)) {
throw new Error("Replay detected");
}
Несмотря на надёжность примитивов, библиотека не решает архитектурные задачи:
Поэтому TweetNaCl.js используется как криптографический слой, а не как протокол.
На практике криптографический слой накладывается на:
Типичная интеграция:
Service A
→ encrypt + sign (TweetNaCl.js)
→ HTTP request
API Gateway
→ forward payload
Service B
→ verify + decrypt
TweetNaCl.js оптимизирован для:
Для высоконагруженных систем: