Криптографические библиотеки вроде TweetNaCl.js и nacl.js работают с данными, для которых критична корректность обработки каждого байта. Любое отклонение в поведении при некорректном вводе может привести не просто к ошибке выполнения, а к деградации безопасности: утечке информации, некорректной проверке подписи или предсказуемости ключевого материала.
TweetNaCl.js реализует облегчённую версию NaCl (Networking and Cryptography library), ориентированную на постоянное время выполнения и минимизацию поверхности атаки. nacl.js является более ранней JavaScript-реализацией, во многом схожей по API, но отличающейся деталями реализации и обработкой входных данных.
Ключевая особенность таких библиотек — отсутствие «мягких» ошибок. Некорректный ввод не должен приводить к неопределённому поведению или частичному успеху криптографической операции. Именно это делает их важной целью для fuzzing-тестирования.
Fuzzing представляет собой метод автоматизированного тестирования, при котором функции получают случайные или полу-случайные входные данные с целью выявления:
Для криптографических функций важны не только ошибки исполнения, но и логические уязвимости. Например:
TweetNaCl.js оперирует несколькими основными примитивами:
nacl.box / nacl.box.open (асимметричное
шифрование)nacl.sign / nacl.sign.open (подписи)nacl.secretbox / nacl.secretbox.open
(симметричное шифрование)Каждая из этих функций принимает строго типизированные бинарные
данные (обычно Uint8Array). Однако в JavaScript границы
типов размыты, и часто возможна передача:
Fuzzing в этом контексте направлен на проверку устойчивости к любым отклонениям от ожидаемого формата.
На практике fuzzing криптографических функций включает несколько классов модификаций входных данных.
1. Длина данных
Изменение длины входных буферов:
Криптографические функции часто предполагают фиксированные размеры ключей (например, 32 байта), и нарушение этого условия должно корректно обрабатываться.
2. Битовые искажения
Входные данные подвергаются:
Цель — проверить стабильность алгоритма при минимальных изменениях входа.
3. Некорректные ключи и nonce
Особое внимание уделяется:
Повтор nonce в схемах вроде secretbox или
box может приводить к серьёзным криптографическим
последствиям, поэтому fuzzing часто специально генерирует коллизии
nonce.
4. Неканонические представления
JavaScript позволяет легко создавать неоднозначные представления данных:
Uint8Array vs ArrayFuzzing проверяет, как библиотека реагирует на такие несоответствия.
Для тестирования TweetNaCl.js и nacl.js применяются несколько подходов.
1. Property-based testing
Библиотеки вроде fast-check позволяют задавать свойства криптографических операций:
Такие свойства формализуют ожидаемое поведение.
2. Coverage-guided fuzzing
Инструменты вроде AFL++ или libFuzzer могут использоваться через WebAssembly-обёртки. В этом случае JavaScript-код компилируется или адаптируется для исполнения в среде, где возможно отслеживание покрытия кода.
Цель — максимизация количества посещённых веток исполнения внутри криптографических функций.
3. Pure JavaScript fuzzers
Простейшие реализации используют:
Такие подходы менее эффективны, но применимы для базовой проверки устойчивости.
import nacl from "tweetnacl";
function randomBytes(len) {
const arr = new Uint8Array(len);
for (let i = 0; i < len; i++) {
arr[i] = Math.floor(Math.random() * 256);
}
return arr;
}
for (let i = 0; i < 100000; i++) {
const key = randomBytes(32);
const nonce = randomBytes(24);
const message = randomBytes(Math.floor(Math.random() * 128));
try {
const encrypted = nacl.secretbox(message, nonce, key);
const decrypted = nacl.secretbox.open(encrypted, nonce, key);
if (decrypted !== null) {
const sameLength = decrypted.length === message.length;
if (!sameLength) {
throw new Error("Length mismatch");
}
}
} catch (e) {
// исключения фиксируются как потенциальные дефекты
}
}
В подобной схеме проверяется не только отсутствие падений, но и сохранение криптографических свойств при корректных входных данных.
Fuzzing в криптографии часто опирается на набор формальных инвариантов:
Нарушение любого из этих свойств указывает на критическую ошибку реализации.
JavaScript создаёт дополнительные сложности:
Криптографические библиотеки вроде TweetNaCl.js стремятся минимизировать влияние оптимизаций, однако fuzzing может выявить случаи, где оптимизатор меняет поведение при необычных входах.
В процессе тестирования криптографических функций часто обнаруживаются следующие проблемы:
TweetNaCl.js и nacl.js часто сравниваются между собой как эталонные реализации. Дифференциальный fuzzing использует следующий принцип:
Такой подход позволяет выявить:
Ключевой источник проблем — преобразование данных:
Fuzzing часто специально генерирует некорректные преобразования:
Это позволяет выявлять ошибки в слоях сериализации, которые формально не относятся к криптографии, но влияют на безопасность.
Одним из требований к TweetNaCl.js является выполнение криптографических операций за постоянное время. Fuzzing может использоваться для проверки косвенных признаков нарушения этого свойства:
Хотя JavaScript затрудняет точный timing-analysis, статистический fuzzing позволяет выявить аномалии.
Наиболее эффективные схемы тестирования комбинируют:
Такой подход позволяет выявлять как явные ошибки, так и логические нарушения криптографических инвариантов.