Структура библиотеки: пространство имён nacl и nacl.util

Библиотека построена вокруг двух основных пространств имён: nacl и nacl.util. Такое разделение отражает архитектурный принцип: криптографическое ядро изолировано от вспомогательных функций работы с данными, кодировками и представлениями байтовых массивов.

nacl содержит низкоуровневые криптографические примитивы, реализованные на основе спецификаций NaCl (Networking and Cryptography library). В контексте JavaScript-реализации (TweetNaCl.js / nacl.js) это пространство выступает как основной API для всех операций, связанных с шифрованием, подписью и генерацией ключей.

Ключевая особенность — работа исключительно с бинарными данными в формате Uint8Array. Все функции внутри nacl принимают и возвращают строго байтовые массивы без какой-либо встроенной сериализации или кодирования строк.

Основные криптографические примитивы

Симметричное шифрование

Функции:

  • nacl.secretbox(message, nonce, key)
  • nacl.secretbox.open(box, nonce, key)

secretbox реализует аутентифицированное шифрование. Внутри используется комбинация XSalsa20 (потоковый шифр) и Poly1305 (MAC). Это означает, что результат шифрования одновременно обеспечивает конфиденциальность и целостность данных.

Ключевые параметры:

  • message — исходные данные в виде Uint8Array
  • nonce — уникальное значение для каждого сообщения (24 байта)
  • key — симметричный ключ (32 байта)

Результат secretbox уже включает MAC-метку, встроенную в шифротекст.

Асимметричное шифрование

Функции:

  • nacl.box(message, nonce, publicKey, secretKey)
  • nacl.box.open(box, nonce, publicKey, secretKey)
  • nacl.box.keyPair()

Асимметричный механизм основан на Curve25519. Он предназначен для обмена зашифрованными сообщениями между двумя сторонами.

keyPair() генерирует пару ключей:

  • publicKey — может распространяться открыто
  • secretKey — должен храниться в секрете

box использует комбинацию ключей отправителя и получателя для вычисления общего секретного значения.

Подписи

Функции:

  • nacl.sign(message, secretKey)
  • nacl.sign.open(signedMessage, publicKey)
  • nacl.sign.keyPair()
  • nacl.sign.detached(message, secretKey)
  • nacl.sign.detached.verify(message, signature, publicKey)

Подписи реализованы на Ed25519. В отличие от шифрования, здесь основная задача — проверка подлинности данных, а не их скрытие.

detached-вариант отделяет подпись от сообщения, что удобно при работе с протоколами, где данные и подпись передаются отдельно.

Хэширование и утилиты (в зависимости от сборки)

В некоторых сборках присутствуют:

  • nacl.hash(message) — SHA-512 хэширование

Хэш-функция возвращает фиксированный 64-байтовый результат и не требует ключей.


Пространство имён nacl.util

nacl.util представляет собой слой вспомогательных функций, который решает проблему работы с бинарными данными в JavaScript. Так как криптографическое ядро оперирует Uint8Array, а в приложениях часто используются строки, Base64 и другие форматы, nacl.util выполняет преобразования между представлениями.

Работа с кодировками

Преобразование строк в байты

Функции:

  • nacl.util.decodeUTF8(string)

Преобразует UTF-8 строку в Uint8Array. Это основной способ подготовки текстовых данных для криптографических операций.

Особенность заключается в строгом соответствии UTF-8: любые символы Unicode корректно разбиваются на байтовое представление.

Преобразование байтов в строки

Функции:

  • nacl.util.encodeUTF8(uint8Array)

Обратное преобразование позволяет восстановить исходную строку из бинарных данных после расшифрования.


Работа с Base64

Кодирование в Base64

  • nacl.util.encodeBase64(uint8Array)

Используется для представления бинарных данных в текстовом формате, удобном для хранения и передачи через JSON, HTTP или URL-параметры.

Декодирование Base64

  • nacl.util.decodeBase64(base64String)

Преобразует строку Base64 обратно в Uint8Array.

Base64 в nacl.util реализован с учётом компактности и минимальных накладных расходов, поскольку криптографические операции часто требуют высокой производительности при обработке больших объёмов данных.


Генерация случайных данных

Функция:

  • nacl.util.encodeBase64(nacl.randomBytes(n)) (косвенное использование)

Хотя генерация случайных значений формально находится в nacl.randomBytes(n), именно через nacl.util часто формируется человекочитаемое представление ключей и nonce.

nacl.randomBytes(n) возвращает криптографически стойкий массив случайных байтов. В браузере и Node.js реализация опирается на соответствующие системные источники энтропии.


Взаимодействие nacl и nacl.util

Разделение на два пространства имён создаёт чёткую архитектурную границу:

  • nacl — строго криптографическое ядро
  • nacl.util — слой адаптации данных

Такой подход устраняет смешивание логики и снижает вероятность ошибок, связанных с неправильной кодировкой или преобразованием типов.

Типичный поток данных выглядит следующим образом:

  1. Строка преобразуется в байты через decodeUTF8
  2. Байты передаются в криптографическую функцию nacl.*
  3. Результат (байты) преобразуется обратно через encodeUTF8 или encodeBase64

Особенности работы с Uint8Array

Вся модель библиотеки строится вокруг Uint8Array как универсального контейнера данных. Это связано с несколькими факторами:

  • предсказуемая работа с памятью
  • отсутствие скрытых преобразований типов
  • совместимость с WebCrypto и низкоуровневыми API
  • оптимизация под криптографические операции

nacl.util выступает как слой, компенсирующий неудобство прямой работы с бинарными массивами в JavaScript, где строковый тип доминирует в прикладной разработке.


Роль утилитного слоя в безопасности

Несмотря на то, что nacl.util не содержит криптографических алгоритмов, его корректное использование напрямую влияет на безопасность всей системы.

Ошибки в кодировке могут приводить к:

  • изменению входных данных перед шифрованием
  • невозможности проверки подписи
  • некорректному восстановлению исходного сообщения

Поэтому преобразования в nacl.util рассматриваются как часть криптографического конвейера, а не как вспомогательная логика.


Структурная изоляция API

Разделение на nacl и nacl.util формирует двухуровневую модель:

  • криптографический уровень (алгоритмы, ключи, операции)
  • прикладной уровень (кодировки, представления, совместимость с текстовыми форматами)

Такая архитектура позволяет использовать библиотеку как в низкоуровневых протоколах, так и в веб-приложениях, где требуется работа с JSON и строками без ручного управления байтами.


Особенности реализации TweetNaCl.js

В JavaScript-версии библиотека сохраняет минималистичную структуру:

  • отсутствуют классы и сложные абстракции
  • функции статичны и независимы
  • нет скрытого состояния
  • все операции детерминированы входными данными

nacl.util при этом остаётся единственным слоем, который выходит за пределы чистой криптографии и взаимодействует с типами JavaScript высокого уровня.


Преобразование данных как центральный элемент архитектуры

Вся практическая работа с библиотекой сводится к постоянному циклу преобразований:

  • строка → байты → криптографическая функция → байты → строка

Именно nacl.util делает этот цикл возможным без необходимости ручной реализации сериализации, что особенно важно при работе с ключами, nonce и зашифрованными сообщениями.


Роль пространства имён в читаемости кода

Разделение API на nacl и nacl.util влияет на структуру прикладного кода:

  • криптографические вызовы становятся очевидными и изолированными
  • преобразования данных явно отделены
  • снижается вероятность смешивания логики

Такое разделение создаёт предсказуемую модель использования библиотеки, где каждое пространство имён отвечает за строго определённый класс задач.