В библиотеке TweetNaCl.js реализована схема цифровой подписи Ed25519,
предоставляющая компактную и высокоскоростную криптографию на основе
эллиптических кривых. Основной точкой входа для создания ключей является
функция nacl.sign.keyPair.
Функция генерирует пару ключей, состоящую из:
Вызов без аргументов приводит к генерации криптографически стойкой случайной пары:
import nacl from "tweetnacl";
const keyPair = nacl.sign.keyPair();
const publicKey = keyPair.publicKey;
const secretKey = keyPair.secretKey;
Обе сущности представлены в виде Uint8Array
фиксированной длины:
publicKey: 32 байтаsecretKey: 64 байтаОсобенность структуры secretKey заключается в том, что
она включает не только сам секретный компонент, но и соответствующий ему
публичный ключ, что оптимизирует последующие операции подписи.
Алгоритм Ed25519 основан на детерминированной генерации ключевого материала из случайного 32-байтового seed. В процессе формируется расширенный секрет, из которого вычисляются:
TweetNaCl.js скрывает эти преобразования, предоставляя готовый
интерфейс через keyPair.
Для сценариев, где требуется воспроизводимость ключевой пары, используется метод:
const seed = crypto.getRandomValues(new Uint8Array(32));
const keyPair = nacl.sign.keyPair.fromSeed(seed);
Полученная пара обладает теми же характеристиками:
const publicKey = keyPair.publicKey;
const secretKey = keyPair.secretKey;
Поведение двух методов различается принципиально:
Все ключи представлены в бинарном виде (Uint8Array), что
исключает необходимость дополнительного кодирования на уровне
библиотеки.
При необходимости хранения или передачи обычно используется преобразование:
const base64PublicKey = btoa(String.fromCharCode(...publicKey));
const base64SecretKey = btoa(String.fromCharCode(...secretKey));
Однако такие преобразования выходят за рамки самой криптографической библиотеки и относятся к уровню прикладной инфраструктуры.
Закрытый ключ в TweetNaCl.js имеет удвоенный размер по сравнению с математическим определением ключа Ed25519. Структура включает:
Это упрощает операции подписи, поскольку повторное вычисление публичного ключа не требуется.
При вызове nacl.sign.keyPair() критически важно наличие
корректного источника энтропии. В браузерной среде используется:
window.crypto.getRandomValuesВ Node.js аналогично:
crypto.randomBytes (внутри реализации библиотеки или
через полифил)Слабая энтропия приводит к полной компрометации ключевой пары, поскольку алгоритм Ed25519 детерминирован после получения seed.
Использование одного seed в нескольких контекстах приводит к идентичным ключам, что нарушает изоляцию идентичностей.
Любое изменение длины seed (например, 16 байт вместо 32) делает ключевую пару некорректной или непредсказуемо изменённой.
Преобразование Uint8Array через строковые функции без
явного кодирования приводит к потере данных:
String.fromCharCode(...secretKey) // потенциально опасно при хранении
Сгенерированная пара используется в следующих функциях:
const message = new TextEncoder().encode("data");
const signature = nacl.sign(message, secretKey);
const verified = nacl.sign.open(signature, publicKey);
Ключевая пара напрямую связана с устойчивостью подписи: любой
компрометированный secretKey делает невозможной проверку
подлинности данных.
Каждый вызов nacl.sign.keyPair() приводит к созданию
новой независимой пары. Повторяемость отсутствует, если не используется
fromSeed.
Это свойство критично для:
Ключевая пара часто используется как основа идентификации субъекта в системах:
Открытый ключ выступает как публичный идентификатор, закрытый — как средство контроля доступа к действиям подписи.