Подключение в Node.js

Stanford JavaScript Crypto Library изначально проектировалась как браузерная криптографическая библиотека, поэтому при использовании в Node.js возникает ряд особенностей, связанных с отсутствием DOM-окружения и различиями в источниках случайности. Подключение сводится к установке пакета и адаптации окружения.

npm install sjcl

После установки библиотека подключается стандартным способом:

const sjcl = require('sjcl');

В проектах с ES Modules используется импорт:

import sjcl from 'sjcl';

В зависимости от конфигурации сборщика (Node.js ESM, TypeScript, bundler) может потребоваться дополнительная настройка интеропа между CommonJS и ES Modules.


Особенности окружения Node.js

SJCL ожидает наличие браузерных глобальных объектов, прежде всего:

  • window
  • document (в некоторых сценариях)
  • navigator
  • crypto (Web Crypto API или fallback)

В Node.js часть этих объектов отсутствует, что требует частичной эмуляции окружения.

Базовое приведение окружения

Для большинства сценариев достаточно минимального shim’а:

global.window = global;
global.navigator = { userAgent: 'node.js' };

Однако ключевая проблема связана не с DOM, а с генерацией случайных чисел.


Источник энтропии и криптографическая стойкость

SJCL имеет собственный механизм генерации случайных чисел через sjcl.random. В браузере он использует события мыши и системные источники. В Node.js этого нет, поэтому требуется подключение криптографически стойкого генератора из стандартного модуля crypto.

const crypto = require('crypto');

Добавление энтропии:

sjcl.random.addEntropy(
  crypto.randomBytes(32).toString('hex'),
  256,
  'crypto'
);

Параметр 256 указывает на количество бит энтропии, которое добавляется в пул.


Проверка готовности генератора случайных чисел

SJCL не сразу переходит в режим криптографической готовности. Перед использованием функций шифрования, зависящих от RNG, проверяется состояние:

if (!sjcl.random.isReady()) {
  sjcl.random.startCollectors();
}

В Node.js startCollectors() не имеет эффекта, поэтому основная стратегия — ручное добавление энтропии из crypto.


Использование Web Crypto API в Node.js

В современных версиях Node.js доступен crypto.webcrypto, который можно использовать для улучшенной совместимости.

const { webcrypto } = require('crypto');

global.crypto = webcrypto;

Это приближает окружение к браузерному и позволяет SJCL работать более предсказуемо в режимах, завязанных на стандарт WebCrypto.


Шифрование и расшифрование в Node.js

После подготовки окружения SJCL используется без изменений API.

AES-шифрование строки

const plaintext = "секретное сообщение";
const password = "ключ";

const encrypted = sjcl.encrypt(password, plaintext);
console.log(encrypted);

Дешифрование

const decrypted = sjcl.decrypt(password, encrypted);
console.log(decrypted);

Результат шифрования представляет собой JSON-строку, содержащую параметры алгоритма, соль, IV и ciphertext.


Работа с форматами данных

SJCL использует собственные представления данных:

  • битовые массивы (sjcl.bitArray)
  • JSON-контейнеры шифрования
  • base64 / hex кодирование

Преобразование строки в bitArray

const bits = sjcl.codec.utf8String.toBits("данные");

Обратное преобразование

const str = sjcl.codec.utf8String.fromBits(bits);

Хеширование в Node.js

SJCL поддерживает несколько криптографических хеш-функций, включая SHA-256.

const hash = sjcl.hash.sha256.hash("данные");
const hex = sjcl.codec.hex.fromBits(hash);

console.log(hex);

Хеш-значение возвращается в виде bitArray и обычно кодируется в hex или base64.


Генерация ключей и PBKDF2

Для производных ключей используется PBKDF2:

const key = sjcl.misc.pbkdf2("пароль", "соль", 1000, 256);

Параметры:

  • пароль
  • соль
  • количество итераций
  • длина ключа в битах

Результат — битовый массив, пригодный для AES.


Типичные проблемы при использовании в Node.js

Отсутствие энтропии

При запуске в headless-среде SJCL может блокироваться из-за недостатка энтропии. Решение — явное добавление источника через crypto.randomBytes.

Несовместимость с bundler’ами

При использовании Webpack или Vite возможны конфликты из-за ожидания глобальных объектов браузера. Обычно требуется настройка:

  • resolve.fallback
  • DefinePlugin для global
  • полифил crypto

Производительность

SJCL написана на чистом JavaScript без использования нативных биндингов. В Node.js это приводит к:

  • более медленному AES по сравнению с crypto
  • высокой нагрузке при PBKDF2 с большими итерациями

Сравнение с нативным crypto Node.js

В Node.js уже существует полноценный криптографический модуль:

const crypto = require('crypto');

Он предоставляет:

  • AES-GCM
  • SHA-2/3
  • PBKDF2 (нативный)
  • randomBytes (CSPRNG)

SJCL в Node.js используется преимущественно в случаях:

  • совместимости с браузерным кодом
  • необходимости одинакового крипто-формата между клиентом и сервером
  • работы с существующими SJCL-структурами данных

Интеграция в серверные приложения

При использовании в API-сервисах SJCL обычно включается как слой совместимости:

  • данные шифруются на клиенте SJCL
  • сервер Node.js расшифровывает тем же алгоритмом
  • или наоборот, обеспечивает единый формат payload

Типичная схема обмена:

// сервер принимает SJCL JSON
const decrypted = sjcl.decrypt(serverKey, request.body.data);

Безопасная настройка параметров

Ключевые параметры, влияющие на безопасность:

  • количество итераций PBKDF2 (минимум 10000 для реальных систем)
  • длина ключа (256 бит для AES-256)
  • корректная соль (не фиксированная)
  • использование сильного источника энтропии
const derivedKey = sjcl.misc.pbkdf2(password, salt, 10000, 256);

Особенности сериализации результатов

Результат sjcl.encrypt имеет структуру JSON:

  • iv
  • salt
  • ct (ciphertext)
  • mode
  • ks (key size)
  • iter (iterations)

Эта структура позволяет переносить зашифрованные данные между средами без потери контекста.


Использование в TypeScript-проектах

Типизация SJCL отсутствует по умолчанию, поэтому используется декларация:

declare module "sjcl";

Либо подключаются сторонние d.ts файлы, описывающие bitArray и crypto API.


Архитектурные ограничения

SJCL не предназначена для высоконагруженных серверных криптосистем. В Node.js она используется как:

  • совместимый слой
  • учебная реализация криптографии
  • средство сериализации криптографических структур

Основные ограничения:

  • отсутствие нативного ускорения
  • зависимость от JS-реализации алгоритмов
  • необходимость ручного управления энтропией