Проверка целостности в криптографических протоколах на базе TweetNaCl.js строится вокруг аутентифицированных конструкций, где шифрование и контроль целостности объединены в одну операцию. Основной механизм, обеспечивающий защиту от подмены данных, — MAC на основе Poly1305, используемый совместно с поточным шифром XSalsa20.
Poly1305 — это быстрый одноразовый код аутентификации сообщений (MAC), который вычисляет 128-битный тег для произвольного сообщения и секретного ключа. Его ключевая особенность заключается в том, что он предназначен для работы только с уникальным ключом на каждое сообщение.
В TweetNaCl.js Poly1305 не используется как самостоятельный примитив в большинстве сценариев. Он встроен в конструкцию:
Эта связка образует схему secretbox, обеспечивающую одновременно конфиденциальность и целостность.
Функция nacl.secretbox(message, nonce, key) реализует
аутентифицированное шифрование. Внутри происходит несколько этапов:
Итоговая структура:
ciphertext = XSalsa20(message, nonce, key)
tag = Poly1305(ciphertext, one_time_key)
output = tag || ciphertext
Ключевой момент: Poly1305 применяется не к исходному сообщению, а к уже зашифрованным данным.
При вызове:
nacl.secretbox.open(box, nonce, key)
происходит обратный процесс:
Если теги не совпадают — данные считаются повреждёнными или
поддельными, и функция возвращает null.
Nonce (number used once) — обязательный параметр, который напрямую влияет на безопасность Poly1305 в данной конструкции.
Важно:
Даже если сообщение разное, повтор nonce позволяет атакующему восстановить информацию о ключе аутентификации.
Poly1305 работает в поле по модулю (2^{130} - 5) и вычисляет полиномиальную функцию от блоков сообщения:
(m, r, s) = (_{i=1}^{n} m_i r^i (2^{130}-5)) + s
где:
В практической реализации TweetNaCl.js все эти операции скрыты внутри оптимизированного C-подобного кода, компилированного в JavaScript.
Безопасность обеспечивается комбинацией факторов:
Таким образом, атакующий не может:
В TweetNaCl.js существует две основные схемы, использующие Poly1305:
Фактически:
nacl.box = nacl.secretbox + ECDH key exchange
Poly1305 остаётся неизменным элементом на уровне аутентификации.
Библиотека не предоставляет прямую функцию типа:
nacl.poly1305()
Вместо этого Poly1305 встроен внутрь secretbox.
Проверка MAC реализована так, чтобы избежать timing attacks:
Poly1305 генерирует 16-байтный (128-bit) аутентификационный тег:
tag.length === 16
[ 16 bytes Poly1305 tag | encrypted message (XSalsa20) ]
Nonce при этом передаётся отдельно и не включается в пакет.
const nacl = require('tweetnacl');
nacl.util = require('tweetnacl-util');
const key = nacl.randomBytes(32);
const nonce = nacl.randomBytes(24);
const message = nacl.util.decodeUTF8("секретное сообщение");
const box = nacl.secretbox(message, nonce, key);
const opened = nacl.secretbox.open(box, nonce, key);
if (opened === null) {
throw new Error("Повреждённые или поддельные данные");
}
const decoded = nacl.util.encodeUTF8(opened);
Самая критичная ошибка:
Если игнорировать результат secretbox.open, можно
обработать поддельные данные.
Poly1305 полностью зависит от секретного ключа, утечка которого компрометирует всю схему.
Poly1305 здесь выполняет строго одну роль — защиту целостности уже зашифрованного текста. Он не участвует в шифровании и не влияет на конфиденциальность напрямую.
Его значение в системе:
Без Poly1305 потоковое шифрование XSalsa20 было бы уязвимо к битовым модификациям.
Комбинация XSalsa20 + Poly1305 в TweetNaCl.js реализует модель:
Именно Poly1305 отвечает за последние два свойства, выступая криптографическим фильтром перед этапом расшифрования.