Схема encrypt-then-sign vs sign-then-encrypt

В криптографических протоколах композиция операций подписи и шифрования определяет не только свойства безопасности, но и границы того, что именно защищается: содержимое сообщения, его происхождение, либо оба свойства одновременно. В контексте TweetNaCl.js / nacl.js эти схемы реализуются поверх примитивов подписи (nacl.sign) и симметричного или асимметричного шифрования (nacl.secretbox, nacl.box), которые сами по себе не задают строгого протокольного порядка применения.

Схема encrypt-then-sign предполагает, что сначала сообщение шифруется, а затем полученный шифротекст подписывается.

Формально:

C = Enc(K_enc, M)
S = Sign(K_sign, C)

Передача:

(C, S)

На стороне получателя:

  1. Проверка подписи S над C
  2. Расшифрование C

Ключевая особенность

Подпись накладывается на уже зашифрованные данные. Это означает, что:

  • подпись защищает целостность шифротекста;
  • любая модификация ciphertext выявляется до попытки расшифрования;
  • расшифровка выполняется только после проверки подлинности.

Свойства безопасности

  • Аутентичность шифротекста: гарантируется до дешифрования
  • Защита от DoS через дешифрование: некорректные данные отбрасываются до дорогостоящей операции
  • Разделение криптографических доменов: подпись и шифрование не влияют друг на друга

Реализация в TweetNaCl.js

Типичный подход с nacl.sign.detached и nacl.box:

const nonce = nacl.randomBytes(nacl.box.nonceLength);

const ciphertext = nacl.box(
  message,
  nonce,
  recipientPublicKey,
  senderSecretKey
);

const signature = nacl.sign.detached(
  ciphertext,
  senderSigningSecretKey
);

const packet = {
  nonce,
  ciphertext,
  signature
};

Проверка:

const valid = nacl.sign.detached.verify(
  ciphertext,
  signature,
  senderSigningPublicKey
);

if (!valid) {
  throw new Error("Invalid signature");
}

const message = nacl.box.open(
  ciphertext,
  nonce,
  senderPublicKey,
  recipientSecretKey
);

Sign-then-Encrypt

Схема sign-then-encrypt предполагает сначала создание подписи над открытым текстом, после чего сообщение вместе с подписью шифруется.

Формально:

S = Sign(K_sign, M)
P = (M, S)
C = Enc(K_enc, P)

Передача:

C

На стороне получателя:

  1. Расшифрование C → (M, S)
  2. Проверка подписи S над M

Ключевая особенность

Подпись скрыта внутри шифротекста и становится доступной только после расшифрования.

Свойства безопасности

  • Конфиденциальность подписи: подпись скрыта от наблюдателя
  • Возможность лишней обработки: дешифрование выполняется до проверки подлинности
  • Уязвимость к DoS-атакам на дешифрование: атакующий может заставлять выполнять дорогостоящие операции расшифрования

Реализация в TweetNaCl.js

const signature = nacl.sign.detached(
  message,
  senderSigningSecretKey
);

const payload = new Uint8Array(message.length + signature.length);
payload.set(message);
payload.set(signature, message.length);

const nonce = nacl.randomBytes(nacl.box.nonceLength);

const ciphertext = nacl.box(
  payload,
  nonce,
  recipientPublicKey,
  senderSecretKey
);

Расшифрование:

const payload = nacl.box.open(
  ciphertext,
  nonce,
  senderPublicKey,
  recipientSecretKey
);

const message = payload.slice(0, payload.length - nacl.sign.signatureLength);
const signature = payload.slice(payload.length - nacl.sign.signatureLength);

const valid = nacl.sign.detached.verify(
  message,
  signature,
  senderSigningPublicKey
);

if (!valid) {
  throw new Error("Invalid signature");
}

Сравнение свойств схем

1. Порядок криптографических операций

  • encrypt-then-sign: подпись над шифротекстом
  • sign-then-encrypt: подпись внутри зашифрованного контейнера

2. Проверка подлинности

  • encrypt-then-sign: проверка возможна до расшифрования
  • sign-then-encrypt: проверка возможна только после расшифрования

3. Поведение при атаке

encrypt-then-sign:

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

sign-then-encrypt:

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

4. Видимость подписи

  • encrypt-then-sign: подпись видна внешнему наблюдателю
  • sign-then-encrypt: подпись скрыта

Влияние на протоколы поверх NaCl

В NaCl-экосистеме (и в TweetNaCl.js как минималистичной реализации) важно учитывать, что базовые примитивы разделены:

  • nacl.box обеспечивает только шифрование и аутентификацию между двумя сторонами
  • nacl.sign обеспечивает цифровую подпись без шифрования

Комбинация этих примитивов не навязывает порядок, но выбор схемы влияет на:

  • устойчивость к DoS
  • архитектуру обработки сообщений
  • требования к ранней валидации входных данных

encrypt-then-sign чаще используется как более строгая схема композиции, поскольку позволяет выстроить фильтрацию неподлинных сообщений до выполнения криптографически дорогих операций расшифрования.


Причины различий в практической криптографии

Различие схем связано не только с порядком операций, но и с тем, где именно фиксируется целостность данных:

  • в encrypt-then-sign целостность фиксируется поверх результата шифрования
  • в sign-then-encrypt целостность фиксируется на уровне исходного сообщения

Эти уровни приводят к разному поведению при повторном использовании ciphertext, модификациях и попытках анализа трафика.


Практическая интерпретация в прикладных системах

В системах, построенных на TweetNaCl.js, encrypt-then-sign часто используется в сценариях, где:

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

Sign-then-encrypt встречается в архитектурах, где:

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

Композиционные риски

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

  • повторное использование nonce в nacl.box полностью разрушает конфиденциальность
  • отсутствие проверки подписи до использования данных создаёт возможность атак на логику приложения
  • смешивание ключей подписи и шифрования без строгого разделения доменов приводит к ошибкам привязки контекста

В NaCl-подобных библиотеках ключевое значение имеет не только выбор схемы, но и строгая дисциплина обработки: разделение ключей, неизменяемость nonce и детерминированный порядок проверок.