XSalsa20-Poly1305 относится к классу схем Authenticated Encryption with Associated Data (AEAD), где одна конструкция одновременно обеспечивает:
В библиотеке NaCl и её JavaScript-реализациях (TweetNaCl.js, nacl.js) эта связка является базовым примитивом для симметричного шифрования сообщений.
Ключевая идея: XSalsa20 используется для шифрования поточным способом, Poly1305 — для вычисления кода аутентификации (MAC).
Salsa20 — это поточный шифр, который генерирует псевдослучайный поток байтов (keystream), зависящий от:
Шифрование выполняется операцией XOR:
ciphertext = plaintext ⊕ keystream
Проблема классического Salsa20 — ограниченный размер nonce (64 бита), что повышает риск повторов при больших объёмах данных.
XSalsa20 решает эту проблему, увеличивая nonce до 192 бит.
Это достигается через промежуточную функцию:
HSalsa20 не генерирует поток шифрования напрямую. Вместо этого она:
Формально:
subkey = HSalsa20(key, nonce_part)
Далее:
Таким образом структура становится:
XSalsa20(key, nonce_192):
subkey = HSalsa20(key, nonce[0..127])
return Salsa20(subkey, nonce[128..191])
После генерации keystream алгоритм работает так:
Keystream формируется блоками по 64 байта. Каждый блок зависит от:
keystream_block[i] = Salsa20_block(subkey, nonce, i)
Шифрование:
C[i] = P[i] ⊕ KS[i]
Дешифрование идентично:
P[i] = C[i] ⊕ KS[i]
Ключевой момент: поточный шифр не модифицирует данные, он только накладывает поток.
Poly1305 — это высокоскоростной MAC-алгоритм, основанный на арифметике полиномов по модулю (2¹³⁰ − 5).
Сообщение интерпретируется как последовательность чисел и подставляется в полином:
P = m₁·rⁿ + m₂·rⁿ⁻¹ + ... + mₙ
Где:
Poly1305 критически зависит от:
один ключ = одно сообщение
Если использовать ключ повторно, безопасность полностью ломается.
В XSalsa20-Poly1305 используется конструкция Encrypt-then-MAC, но с важной оптимизацией: ключ для Poly1305 не задаётся вручную.
Ключ для Poly1305 генерируется из XSalsa20:
otk = XSalsa20(key, nonce).first_32_bytes
Далее:
Вход:
Nonce делится:
subkey = HSalsa20(key, nonce1)
keystream = XSalsa20(subkey, nonce2)
otk = keystream[0..31]
ciphertext = plaintext ⊕ keystream[32..]
tag = Poly1305(otk, ciphertext)
output = nonce || ciphertext || tag
Любое изменение ciphertext приводит к:
XSalsa20 с 192-битным nonce практически исключает коллизии.
Ключ MAC не передаётся напрямую, он:
В JavaScript-реализации (TweetNaCl.js / nacl.js):
Типичный интерфейс:
nacl.secretbox(message, nonce, key)
Где:
key — 32 байтаnonce — 24 байта (XSalsa20)message — произвольные данныеРезультат включает:
Nonce должен быть уникальным. Повтор nonce = повтор keystream = компрометация.
MAC проверяется до расшифровки, что исключает утечки через ошибки формата.
Любое изменение ciphertext ломает MAC, поэтому модификация невозможна без ключа.
XSalsa20-Poly1305 можно рассматривать как:
AEAD(K, N, M) = (C, T)
Где:
В NaCl-подобных библиотеках эта схема используется как основной примитив:
Она считается одной из наиболее простых и при этом надёжных AEAD-конструкций, доступных для прикладной криптографии.