Криптографические библиотеки в JavaScript особенно чувствительны к некорректным входным данным: любые неожиданные байтовые последовательности, обрезанные строки, неверные кодировки или частично повреждённые структуры могут приводить не только к исключениям, но и к некорректной криптографической обработке. В случае Stanford JavaScript Crypto Library (SJCL) это особенно критично, поскольку библиотека рассчитана на строго определённые форматы входов — битовые массивы, корректно сериализованные JSON-структуры и валидные ключи.
SJCL оперирует несколькими типами данных:
sjcl.bitArray)Каждый из этих типов предполагает строгую структуру. Например,
sjcl.encrypt ожидает корректный пароль и валидный
plaintext, а sjcl.decrypt — строго форматированный JSON с
полями iv, salt, ct,
iter, ks, mode,
adata.
Фаззинг в этом контексте означает систематическую подачу некорректных, случайных или полуслучайных входов для выявления:
throw, undefined behavior)SJCL не использует нативные бинарные типы JavaScript (ArrayBuffer в ранних версиях), а работает через абстракцию битовых массивов:
var sjcl = require("sjcl");
var bits = sjcl.codec.utf8String.toBits("test");
Это означает, что многие ошибки возникают не на уровне типов JS, а на уровне преобразования:
Перед запуском фаззинга важно обернуть целевые функции в безопасные ловушки:
function safeDecrypt(password, data) {
try {
return sjcl.decrypt(password, data);
} catch (e) {
return null;
}
}
Однако для полноценного тестирования такая защита должна быть отключена или логироваться, иначе ошибки будут скрыты.
Фаззинг криптографических функций SJCL требует не просто случайных строк, а структурно разнообразных входов.
function randomBitArray(len) {
var arr = [];
for (var i = 0; i < len; i++) {
arr.push(Math.floor(Math.random() * 0xffffffff));
}
return arr;
}
Используется для тестирования sjcl.bitArray
операций:
SJCL encrypt возвращает JSON:
{
"iv": "...",
"v": 1,
"iter": 1000,
"ks": 128,
"ct": "..."
}
Фаззинг модификаций:
function fuzzCiphertext(ct) {
let obj = JSON.parse(ct);
const keys = Object.keys(obj);
const randomKey = keys[Math.floor(Math.random() * keys.length)];
obj[randomKey] = Math.random().toString(36);
return JSON.stringify(obj);
}
Типичные мутации:
SJCL активно использует кодеки:
sjcl.codec.utf8Stringsjcl.codec.hexsjcl.codec.base64Фаззинг здесь включает:
const inputs = [
"\u0000\u0000\u0000",
"\uffff\uffff",
"????",
"\x00\xff\x10\x80",
String.fromCharCode(...Array(256).keys())
];
Особенно важно проверять:
Для SJCL чаще всего используют:
Пример простого fuzz-loop:
const sjcl = require("sjcl");
for (let i = 0; i < 100000; i++) {
try {
let password = randomBitArray(4).toString();
let data = fuzzCiphertext(sjcl.encrypt("pass", "data"));
sjcl.decrypt(password, data);
} catch (e) {
// логируем только неожиданные ошибки
if (!(e instanceof Error)) {
console.log("Unexpected:", e);
}
}
}
Ключи в SJCL проходят через KDF (обычно PBKDF2). Ошибки возникают при:
Фаззинг ключей:
function fuzzPassword() {
const variants = [
"",
"\u0000\u0000\u0000",
"a".repeat(10000),
null,
undefined,
{ toString: () => "pass" }
];
return variants[Math.floor(Math.random() * variants.length)];
}
Особенно важно не только искать падения, но и логические ошибки:
Пример проверки:
const enc = sjcl.encrypt("password", "secret");
const mutated = JSON.parse(enc);
mutated.ct = mutated.ct.replace(/A/g, "B");
const dec = sjcl.decrypt("password", JSON.stringify(mutated));
Если декодирование прошло успешно — это сигнал о проблеме в проверке целостности.
SJCL активно использует побитовые операции, что делает его чувствительным к:
Фаззинг таких случаев:
for (let i = -1000; i < 1000; i++) {
try {
sjcl.bitArray.bitSlice([i, i*2, i*3], i, i+64);
} catch (e) {}
}
Эффективный метод для криптографии:
Пример:
const sjclOut = sjcl.decrypt(pass, data);
const webcryptoOut = await subtleDecrypt(pass, data);
if (sjclOut !== webcryptoOut) {
console.log("Mismatch detected");
}
После нахождения ошибки важно сократить вход:
На практике эффективная схема выглядит как конвейер:
Генерация входа (структурного, а не полностью случайного)
Мутация ciphertext / key / codec
Запуск encrypt/decrypt
Проверка:
Логирование минимального воспроизводимого случая
Фаззинг криптографических входов в SJCL особенно ценен тем, что библиотека часто используется как “reference implementation” в проектах, где безопасность зависит не только от алгоритма, но и от корректности обработки нестандартных данных. Даже небольшие отклонения в обработке битовых массивов или сериализации могут приводить к серьёзным последствиям на уровне протоколов, построенных поверх SJCL.