Механизм цифровой подписи в TweetNaCl.js основан на алгоритме Ed25519, который обеспечивает высокую скорость и криптографическую стойкость. В библиотеке реализованы два основных подхода к подписи данных: «attached» и «detached». В случае detached-подписи результатом является отдельный массив байт фиксированной длины, не содержащий исходное сообщение.
Подход detached используется там, где необходимо хранить или передавать подпись отдельно от данных, например в протоколах обмена сообщениями, API-запросах и системах верификации файлов.
Ed25519 относится к эллиптическим криптографическим схемам с использованием кривой Curve25519. В контексте подписи используются два ключа:
TweetNaCl.js работает с ключами в бинарном формате
Uint8Array, а не строками.
Ключевая пара создаётся через nacl.sign.keyPair(), либо
из заранее известного seed.
const nacl = require('tweetnacl');
// генерация новой пары ключей
const keyPair = nacl.sign.keyPair();
const publicKey = keyPair.publicKey;
const secretKey = keyPair.secretKey;
Также можно восстановить пару из seed:
const keyPair = nacl.sign.keyPair.fromSeed(seedUint8Array);
Seed должен быть длиной 32 байта.
Функция nacl.sign.detached создаёт криптографическую
подпись без упаковки сообщения.
nacl.sign.detached(message, secretKey)
message — данные в виде Uint8ArraysecretKey — закрытый ключ (64 байта)Uint8Array длиной 64 байта (подпись Ed25519)const nacl = require('tweetnacl');
const message = new TextEncoder().encode("secure message");
const keyPair = nacl.sign.keyPair();
const signature = nacl.sign.detached(message, keyPair.secretKey);
TextEncoder используется для преобразования строки в
байты, так как криптографические функции работают только с бинарными
данными.
Проверка выполняется отдельно от сообщения, что и определяет модель detached.
nacl.sign.detached.verify(message, signature, publicKey)
message — исходное сообщение
(Uint8Array)signature — подпись (64 байта)publicKey — открытый ключ (32 байта)boolean:
true — подпись валиднаfalse — подпись не соответствует даннымconst nacl = require('tweetnacl');
const message = new TextEncoder().encode("secure message");
const keyPair = nacl.sign.keyPair();
const signature = nacl.sign.detached(message, keyPair.secretKey);
const isValid = nacl.sign.detached.verify(
message,
signature,
keyPair.publicKey
);
console.log(isValid); // true
Все входные данные должны быть представлены как
Uint8Array. Строки необходимо явно кодировать.
new TextEncoder().encode("text")
Любое отклонение в размере приводит к некорректной работе функций.
Detached-подпись используется в сценариях, где важно разделение данных и метаданных:
При работе с объектами данные необходимо сериализовать.
const data = {
user: "alice",
amount: 100
};
const message = new TextEncoder().encode(JSON.stringify(data));
const signature = nacl.sign.detached(message, keyPair.secretKey);
При проверке важно использовать абсолютно идентичную сериализацию.
Даже незначительное изменение строки делает подпись недействительной:
// неправильно
nacl.sign.detached("message", secretKey);
// правильно
nacl.sign.detached(new TextEncoder().encode("message"), secretKey);
Подпись является бинарным массивом, поэтому для передачи по сети её обычно кодируют:
Пример с Base64:
const signatureBase64 = Buffer.from(signature).toString("base64");
Обратное преобразование:
const signature = Uint8Array.from(Buffer.from(signatureBase64, "base64"));
Detached-подпись часто применяется как защита запросов:
{ data, signature }Ed25519, используемый в TweetNaCl.js, обеспечивает:
В библиотеке присутствует связанная функциональность:
nacl.sign.keyPair() — генерация ключейnacl.sign.detached() — создание подписиnacl.sign.detached.verify() — проверка подписиnacl.sign() — attached-вариант (со встроенным
сообщением)Detached-вариант предпочтителен при необходимости независимого хранения подписи и данных.