Гибридное шифрование: симметрика + асимметрика

Базовая модель гибридной криптографии

Гибридное шифрование строится на разделении ответственности между двумя криптографическими подходами:

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

Классическая проблема асимметричных алгоритмов заключается в их низкой производительности. Симметричные алгоритмы, наоборот, быстры, но требуют заранее общего секрета. Гибридная схема объединяет их сильные стороны.

В контексте TweetNaCl.js это выражается через комбинацию:

  • nacl.box — асимметричное шифрование на основе Curve25519 + XSalsa20-Poly1305
  • nacl.secretbox — симметричное шифрование на основе XSalsa20-Poly1305

Криптографические примитивы TweetNaCl.js

nacl.box

Механизм публичного шифрования:

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

Основные функции:

  • nacl.box.keyPair() — генерация ключевой пары
  • nacl.box.before(publicKey, secretKey) — вычисление общего секрета
  • nacl.box(message, nonce, publicKey, secretKey) — шифрование
  • nacl.box.open(...) — расшифрование

nacl.secretbox

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

  • требует заранее общий ключ (32 байта)
  • использует nonce (24 байта)
  • обеспечивает конфиденциальность и целостность

Функции:

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

Причины использования гибридной схемы

Асимметричное шифрование в чистом виде плохо подходит для:

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

Симметричное шифрование не решает проблему:

  • безопасного обмена ключами
  • инициализации доверенного канала

Гибридная схема решает обе задачи:

  • асимметрия защищает ключ
  • симметрия защищает данные

Модель KEM–DEM

Гибридная криптосистема обычно строится по модели:

  • KEM (Key Encapsulation Mechanism) — обёртка ключа
  • DEM (Data Encapsulation Mechanism) — шифрование данных

В TweetNaCl.js роль KEM выполняет:

  • nacl.box.before() или nacl.box

Роль DEM выполняет:

  • nacl.secretbox

Вычисление общего секрета

При использовании Curve25519 обе стороны могут вычислить общий секрет:

import nacl from "tweetnacl";
import util from "tweetnacl-util";

const alice = nacl.box.keyPair();
const bob = nacl.box.keyPair();

const aliceShared = nacl.box.before(bob.publicKey, alice.secretKey);
const bobShared = nacl.box.before(alice.publicKey, bob.secretKey);

Оба значения aliceShared и bobShared идентичны.

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

  • секрет не передаётся по сети
  • он вычисляется независимо

Производный симметричный ключ

Полученный shared secret нельзя всегда напрямую использовать как ключ для secretbox. Обычно его:

  • либо используют напрямую (в TweetNaCl допустимо)
  • либо хешируют для усиления разделения контекста

Простой вариант:

const symmetricKey = aliceShared;

Более строгий вариант:

const symmetricKey = nacl.hash(aliceShared).slice(0, 32);

Шифрование данных через secretbox

После получения симметричного ключа используется быстрый механизм:

const nonce = nacl.randomBytes(24);
const message = util.decodeUTF8("секретные данные");

const encrypted = nacl.secretbox(message, nonce, symmetricKey);

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

const decrypted = nacl.secretbox.open(encrypted, nonce, symmetricKey);
const text = util.encodeUTF8(decrypted);

Полная гибридная схема

Шаг 1. Генерация ключей сторон

const alice = nacl.box.keyPair();
const bob = nacl.box.keyPair();

Шаг 2. Вычисление общего секрета

const shared = nacl.box.before(bob.publicKey, alice.secretKey);

Шаг 3. Производный ключ для симметрии

const key = shared;

Шаг 4. Шифрование сообщения

const nonce = nacl.randomBytes(24);
const msg = util.decodeUTF8("конфиденциальное сообщение");

const cipher = nacl.secretbox(msg, nonce, key);

Шаг 5. Расшифрование

const plain = nacl.secretbox.open(cipher, nonce, key);
const result = util.encodeUTF8(plain);

Альтернативная гибридная схема через nacl.box

TweetNaCl.js уже содержит встроенный механизм гибридного шифрования:

const nonce = nacl.randomBytes(24);
const message = util.decodeUTF8("данные");

const encrypted = nacl.box(
  message,
  nonce,
  bob.publicKey,
  alice.secretKey
);

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

const decrypted = nacl.box.open(
  encrypted,
  nonce,
  alice.publicKey,
  bob.secretKey
);

В этом случае библиотека сама:

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

Сравнение подходов

nacl.box

  • проще в использовании
  • встроенная гибридная схема
  • подходит для сообщений небольшого и среднего размера

box.before + secretbox

  • больше контроля над архитектурой
  • возможность кешировать shared secret
  • подходит для многократных операций между узлами

Управление nonce

Nonce является критическим элементом безопасности:

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

Практический подход:

const nonce = nacl.randomBytes(24);

Для потоковых систем nonce часто:

  • увеличивается как счётчик
  • или комбинируется с случайной частью

Разделение ключевых контекстов

Одной из частых ошибок является повторное использование одного и того же ключа для разных целей.

Корректная схема:

  • отдельный ключ для шифрования сообщений
  • отдельный ключ для MAC (в TweetNaCl уже встроено)
  • отдельный ключ для разных каналов

При необходимости можно разделять:

const chatKey = nacl.hash(shared).slice(0, 32);
const fileKey = nacl.hash(chatKey).slice(0, 32);

Производительность гибридной схемы

Ассиметрическая часть (Curve25519):

  • дорогая операция
  • выполняется один раз на сессию

Симметрическая часть (XSalsa20-Poly1305):

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

Это делает модель оптимальной для:

  • мессенджеров
  • API сессий
  • защищённых каналов обмена данными
  • peer-to-peer систем

Типичная архитектура сессии

  1. Обмен публичными ключами
  2. Вычисление shared secret
  3. Кэширование симметрического ключа
  4. Шифрование всех сообщений через secretbox
  5. Обновление ключа при новой сессии

Такая модель позволяет снизить нагрузку и одновременно сохранить криптографическую стойкость канала связи