Структура зашифрованного сообщения и формат вывода

В библиотеке TweetNaCl.js реализованы два основных высокоуровневых подхода к шифрованию данных:

  • secretbox (симметричное шифрование)
  • box (асимметричное шифрование на основе ключевой пары)

Оба метода опираются на алгоритмы семейства NaCl и используют единый принцип формирования зашифрованного сообщения: данные преобразуются в бинарный буфер с обязательным наличием nonce и аутентификационного кода (MAC).


Базовые компоненты зашифрованного сообщения

Любое зашифрованное сообщение в TweetNaCl.js состоит из следующих элементов:

1. Nonce (одноразовый вектор)

  • Длина: 24 байта
  • Назначение: обеспечивает уникальность шифрования
  • Требование: не должен повторяться при одном и том же ключе

Nonce не является секретом, но критически важен для безопасности.


2. Ciphertext (зашифрованные данные)

  • Результат применения алгоритма XSalsa20

  • Включает в себя:

    • собственно зашифрованный текст
    • аутентификационный тег (MAC, Poly1305)

Важно: MAC не хранится отдельно — он встроен в конец ciphertext.


3. Authentication tag (Poly1305 MAC)

  • Длина: 16 байт
  • Назначение: проверка целостности и подлинности сообщения
  • Интегрирован в ciphertext, а не хранится как отдельное поле

Структура результата secretbox

При использовании nacl.secretbox структура результата выглядит логически так:

[ ciphertext || MAC ]

Nonce передаётся отдельно, но при сериализации часто объединяется:

[ nonce (24 байта) || ciphertext+MAC ]

Внутреннее представление в TweetNaCl.js

Фактический результат функции:

nacl.secretbox(message, nonce, key)

возвращает:

Uint8Array(ciphertext + 16 байт MAC)

Nonce не включается автоматически.


Типичный формат упаковки (serialization)

На практике разработчики почти всегда формируют единый пакет:

[ nonce ][ ciphertext ]

Где:

  • nonce = 24 байта
  • ciphertext = зашифрованные данные + MAC

Структура сообщения в nacl.box (асимметричное шифрование)

При использовании:

nacl.box(message, nonce, publicKey, secretKey)

структура результата аналогична secretbox, но ключи отличаются:

Состав:

  • nonce (24 байта)
  • ciphertext (message + 16-byte MAC)

Дополнительно внутри криптографии происходит:

  • вычисление общего ключа через Curve25519
  • использование XSalsa20 для шифрования
  • Poly1305 для аутентификации

Важная особенность box

В отличие от secretbox:

  • ключ не общий симметричный

  • используется пара ключей:

    • publicKey (32 байта)
    • secretKey (32 байта)

Но формат результата остаётся тем же:

ciphertext включает MAC, nonce хранится отдельно

Форматы хранения и передачи данных

В реальных приложениях бинарные данные редко передаются напрямую. Используются обёртки.

Вариант 1: Uint8Array (сырой формат)

{
  nonce: Uint8Array(24),
  ciphertext: Uint8Array(n)
}

Используется внутри приложений или WebCrypto-подобных систем.


Вариант 2: Base64-кодирование

Чаще всего применяется для JSON/API:

{
  "nonce": "base64...",
  "box": "base64..."
}

Преобразование:

  • Uint8Array → base64 перед отправкой
  • base64 → Uint8Array при получении

Вариант 3: Конкатенация в один буфер

Иногда используется компактный формат:

[ nonce || ciphertext ]

Длина итогового сообщения:

24 + ciphertext.length

Разбор структуры ciphertext

Ciphertext в TweetNaCl.js всегда включает:

[ encrypted_message || 16-byte MAC ]

Таким образом:

  • фактический текст скрыт
  • целостность защищена
  • любое изменение данных делает дешифрование невозможным

Пример логической структуры полного сообщения

Secretbox:

nonce (24 bytes)
+
ciphertext (message + 16 bytes MAC)

Box:

nonce (24 bytes)
+
ciphertext (message + 16 bytes MAC)

Важные особенности сериализации

1. Nonce обязателен отдельно

Без nonce расшифрование невозможно.

2. Ciphertext нельзя интерпретировать без ключа

Даже частичное чтение невозможно из-за XSalsa20.

3. MAC встроен в ciphertext

Отдельного поля проверки целостности нет.

4. Формат не фиксирован на уровне библиотеки

TweetNaCl.js не навязывает формат хранения — он только возвращает бинарные данные.


Практическая структура в реальных приложениях

Чаще всего используется следующая схема хранения:

{
  version: 1,
  algorithm: "xsalsa20-poly1305",
  nonce: base64,
  data: base64(ciphertext)
}

Причины:

  • возможность смены алгоритма
  • совместимость API
  • удобство логирования и хранения

Типичные ошибки при работе со структурой

Повторное использование nonce

Критическая ошибка, приводящая к утечке ключа при XOR-аналитике.


Потеря MAC при разборе ciphertext

Отделение последних 16 байт ломает проверку целостности.


Неверная длина nonce

TweetNaCl.js строго ожидает 24 байта — любое отклонение приводит к ошибке шифрования или дешифрования.


Итоговая логическая модель

Зашифрованное сообщение в TweetNaCl.js можно представить как фиксированную структуру:

nonce (24 bytes)
+
ciphertext (encrypted data)
    └── message + MAC (16 bytes)

или в сериализованном виде:

[ nonce || ciphertext ]