Атаки на схему box и способы защиты

Схема box в TweetNaCl.js реализует асимметричное шифрование с аутентификацией на основе комбинации:

  • алгоритма обмена ключами Curve25519 (X25519),
  • симметричного шифрования XSalsa20,
  • аутентификации Poly1305.

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


Атака повторного воспроизведения (Replay Attack)

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

Причина уязвимости:

  • схема box не содержит встроенной защиты от повторов;
  • nonce (одноразовый номер) может быть корректным, но повторно использованным.

Последствия:

  • дублирование операций (например, повторная транзакция);
  • нарушение бизнес-логики.

Методы защиты:

  • Ведение списка использованных nonce на стороне получателя.
  • Использование счетчиков сообщений (sequence numbers).
  • Привязка сообщений к временным меткам и проверка их актуальности.
  • Применение уникальных идентификаторов сообщений (UUID).

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

Критическая уязвимость.

Суть: использование одного и того же nonce с одинаковой парой ключей приводит к компрометации шифрования.

Причина:

  • XSalsa20 — потоковый шифр;
  • повторный nonce ⇒ повторный поток ключа ⇒ возможность XOR-анализа.

Последствия:

  • восстановление открытого текста;
  • утечка ключевой информации.

Пример ошибки:

const nonce = new Uint8Array(24); // всегда нули — опасно

Методы защиты:

  • Генерация nonce через nacl.randomBytes(24) для каждого сообщения.
  • Использование детерминированных nonce только при строгом контроле (например, счетчики + уникальный контекст).
  • Никогда не повторять nonce с одной и той же парой ключей.

Атака “человек посередине” (MITM)

Суть: злоумышленник подменяет открытые ключи при обмене.

Причина:

  • отсутствие проверки подлинности публичных ключей;
  • доверие к неаутентифицированному каналу передачи ключей.

Последствия:

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

Методы защиты:

  • Использование доверенных каналов для передачи публичных ключей.
  • Проверка отпечатков ключей (fingerprints).
  • Применение сертификатов или PKI.
  • Хранение ранее известных ключей (TOFU — Trust On First Use).
  • Подпись ключей через nacl.sign.

Компрометация приватного ключа

Суть: утечка секретного ключа полностью разрушает безопасность.

Причины:

  • хранение ключей в небезопасной среде (localStorage, plain text);
  • XSS-атаки;
  • утечки памяти.

Последствия:

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

Методы защиты:

  • Хранение ключей в защищённых контейнерах (например, Web Crypto API, secure enclave).
  • Минимизация времени жизни ключей в памяти.
  • Использование ephemeral-ключей (одноразовых).
  • Очистка буферов после использования (fill(0)).
  • Изоляция выполнения (например, Web Workers).

Атака по сторонним каналам (Side-channel attack)

Суть: извлечение информации через анализ времени выполнения, энергопотребления или других побочных эффектов.

Причина:

  • различия во времени выполнения операций;
  • использование небезопасных сравнений.

TweetNaCl.js защита:

  • реализует константное время выполнения для критичных операций (например, crypto_verify).

Проблемные места:

  • пользовательский код;
  • сравнение строк/байтов вне библиотеки.

Методы защиты:

  • Использование nacl.verify для сравнения массивов.
  • Избегание стандартных операторов === для чувствительных данных.
  • Минимизация утечек через тайминги.

Подмена ciphertext (Ciphertext manipulation)

Суть: попытка изменить зашифрованное сообщение.

Защита в box:

  • Poly1305 обеспечивает аутентификацию;
  • при изменении ciphertext расшифровка завершится неудачей.

Потенциальные проблемы:

  • игнорирование ошибки расшифровки;
  • некорректная обработка null результата.

Пример уязвимости:

const msg = nacl.box.open(box, nonce, pk, sk);
// отсутствие проверки msg === null

Методы защиты:

  • Обязательная проверка результата:
if (!msg) {
  throw new Error("Данные повреждены или подделаны");
}

Атака на генератор случайных чисел

Суть: предсказуемые nonce или ключи.

Причина:

  • использование слабых RNG;
  • переопределение window.crypto.

TweetNaCl.js:

  • полагается на crypto.getRandomValues.

Методы защиты:

  • Проверка наличия безопасного RNG:
if (!window.crypto || !window.crypto.getRandomValues) {
  throw new Error("Нет криптографически стойкого RNG");
}
  • Запрет на использование в небезопасных окружениях.
  • Аудит среды выполнения.

Ошибки сериализации и кодирования

Суть: некорректное преобразование данных перед шифрованием.

Причины:

  • использование UTF-16 строк без явного кодирования;
  • потеря байтов при преобразовании.

Последствия:

  • невозможность расшифровки;
  • логические ошибки.

Методы защиты:

  • Использование TextEncoder / TextDecoder:
const encoder = new TextEncoder();
const decoder = new TextDecoder();

const message = encoder.encode("text");

Утечка через метаданные

Суть: даже при защищённом содержимом утечка информации возможна через:

  • длину сообщения;
  • частоту отправки;
  • время передачи.

Методы защиты:

  • Паддинг сообщений до фиксированного размера.
  • Добавление случайных задержек.
  • Батчинг сообщений.

Использование неподходящих ключей

Суть: смешивание ключей для разных целей.

Ошибка:

  • использование одного ключа для box и sign.

Методы защиты:

  • Разделение ключей по назначению:

    • ключи для шифрования (box);
    • ключи для подписи (sign).
  • Генерация отдельных пар ключей:

const boxKeyPair = nacl.box.keyPair();
const signKeyPair = nacl.sign.keyPair();

Отсутствие прямой секретности (Forward Secrecy)

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

Причина:

  • box использует статические ключи по умолчанию.

Методы защиты:

  • Использование ephemeral-ключей:

    • генерация новой пары ключей для каждой сессии;
    • обмен ephemeral-публичными ключами.
  • Комбинирование с протоколами типа Double Ratchet.


Атаки на уровень протокола

Суть: уязвимости возникают не в криптографии, а в логике протокола.

Примеры:

  • отсутствие аутентификации отправителя;
  • смешивание сообщений разных сессий;
  • отсутствие контекста (например, ID пользователя).

Методы защиты:

  • Включение контекста в сообщение:
{
  userId,
  timestamp,
  payload
}
  • Подпись сообщений (nacl.sign) при необходимости.
  • Явное разграничение сессий.

Неправильная обработка ошибок

Суть: игнорирование ошибок расшифровки или некорректное поведение при сбоях.

Последствия:

  • принятие поддельных данных;
  • утечка информации через поведение системы.

Методы защиты:

  • Явная обработка всех ошибок.
  • Отказ по умолчанию (fail-safe).
  • Логирование без раскрытия чувствительных данных.

Итоговые принципы безопасного использования box

  • Уникальный nonce для каждого сообщения.
  • Проверка подлинности ключей.
  • Обработка всех ошибок.
  • Изоляция ключевого материала.
  • Использование безопасного RNG.
  • Разделение криптографических ролей.
  • Защита на уровне протокола, а не только алгоритма.

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