В основе всей работы Stanford JavaScript Crypto Library лежит единый
тип представления бинарных данных — bitArray. Это не строка
и не классический ArrayBuffer, а специализированная
структура, оптимизированная под криптографические операции.
bitArray в SJCL — это массив 32-битных слов, где первые
4 бита служат для хранения длины в битах. Именно это отличие чаще всего
становится источником несовместимости при попытке интеграции с другими
библиотеками.
Ключевые свойства bitArray:
Uint8ArrayТипичный пример создания:
const arr = sjcl.codec.utf8String.toBits("secret");
Здесь строка немедленно преобразуется в bitArray, и
дальнейшие криптографические операции работают уже не с текстом, а с
бинарным представлением.
SJCL строго разделяет внутренние и внешние представления данных. Для
этого используется модуль sjcl.codec.
Основные кодеки:
utf8String — строки ↔︎ bitArrayhex — шестнадцатеричное представлениеbase64 — стандартное представление для передачи
данныхbase32 — редко используемый, но поддерживаемый
форматПример преобразования:
const bits = sjcl.codec.utf8String.toBits("data");
const hex = sjcl.codec.hex.fromBits(bits);
const base64 = sjcl.codec.base64.fromBits(bits);
Здесь важно понимать: все кодеки работают только через
bitArray. Любая попытка передать строку напрямую в
криптографическую функцию приведёт к некорректным результатам или
ошибке.
В SJCL ключ никогда не является “строкой” в классическом смысле. Даже
если API принимает пароль, внутри он всегда преобразуется в
bitArray.
Существует два принципиально разных сценария:
sjcl.encrypt("password", "message");
В этом случае происходит:
const key = sjcl.codec.hex.toBits("00112233445566778899aabbccddeeff");
Такой ключ уже считается готовым криптографическим материалом.
При использовании паролей SJCL применяет PBKDF2 (Password-Based Key Derivation Function 2), и здесь возникает ключевая проблема согласования параметров между системами.
Параметры PBKDF2 в SJCL:
salt — случайная соль (bitArray)iter — количество итерацийks — размер ключа в словах (32-битных)prf — HMAC функцияТипичный объект параметров:
{
iter: 10000,
ks: 128 / 32,
salt: sjcl.random.randomWords(4)
}
Критическая деталь: ks измеряется не в байтах, а в
32-битных словах. Это часто вызывает несовместимость с OpenSSL и
WebCrypto.
Результат sjcl.encrypt возвращается в JSON-структуре,
которая содержит строго определённые поля:
{
"iv": "...",
"v": 1,
"iter": 10000,
"ks": 128,
"salt": "...",
"ct": "...",
"mode": "ccm",
"adata": ""
}
Здесь происходит смешение кодировок:
iv, salt, ct — base64adata — строкаОдна из самых частых ошибок при интеграции — неправильная
интерпретация iv и salt.
В SJCL:
iv — bitArray → base64salt — bitArray → base64Но в других системах:
Пример проблемной ситуации:
ArrayBufferbitArrayПри интеграции с Web Crypto API возникает необходимость явного преобразования:
function bitArrayToUint8Array(arr) {
const bytes = sjcl.codec.hex.fromBits(arr);
const len = bytes.length / 2;
const out = new Uint8Array(len);
for (let i = 0; i < len; i++) {
out[i] = parseInt(bytes.substr(i * 2, 2), 16);
}
return out;
}
function uint8ArrayToBitArray(u8) {
let hex = "";
for (let i = 0; i < u8.length; i++) {
hex += u8[i].toString(16).padStart(2, "0");
}
return sjcl.codec.hex.toBits(hex);
}
Эти преобразования необходимы, потому что SJCL не использует нативные бинарные буферы.
В HMAC SJCL также использует bitArray, но проблема
возникает при передаче ключей между системами.
const key = sjcl.codec.utf8String.toBits("key");
const hmac = new sjcl.misc.hmac(key);
Если тот же ключ в другой библиотеке представлен как строка UTF-8 или hex, результат HMAC будет полностью отличаться.
SJCL поддерживает несколько режимов AES:
Параметры режима:
iv — обязательно 128 битadata — дополнительные данные (AAD)tag — только в CCM/GCMПроблема согласования:
ctПри передаче зашифрованных данных между сервисами требуется строгая нормализация:
Пример нормализованного объекта:
{
iv: base64(ivBits),
salt: base64(saltBits),
ct: base64(cipherBits),
iter: 10000,
ks: 128,
mode: "ccm"
}
На практике встречаются повторяющиеся ошибки:
ivКорректная работа с SJCL в гетерогенных системах требует строгой дисциплины:
Любое отклонение от этих правил приводит к несовместимости даже при идентичных алгоритмах шифрования.