Bitarray — основной внутренний формат данных

Внутри SJCL (Stanford Javascript Crypto Library) все криптографические примитивы опираются на единый базовый формат представления данных — bitArray. Это не просто вспомогательная структура, а центральный контракт, через который проходят ключи, векторы инициализации, хэши, шифротексты и промежуточные состояния алгоритмов.

bitArray в SJCL устроен иначе, чем привычные массивы байтов или TypedArray. Его модель ближе к потоковому представлению битов, чем к классическому блочному буферу.


bitArray — это обычный JavaScript-массив, элементы которого интерпретируются как 32-битные слова:

  • каждый элемент хранит 32 бита данных
  • значения трактуются как unsigned 32-bit integers
  • порядок — big-endian на уровне операций

Пример:

var a = [0x12345678, 0x9abcdef0];

Это не массив чисел в математическом смысле, а последовательность 64 бит информации, разбитая на два слова.


Отсутствие явного поля длины

Ключевая особенность SJCL: bitArray не содержит отдельного поля длины.

Длина вычисляется неявно:

  • основная часть массива — полные 32-битные слова
  • последний элемент может быть частично заполнен
  • дополнительные биты кодируются через служебные механизмы (partial words)

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


Частично заполненные слова (partial words)

Чтобы поддерживать произвольную длину битового потока, SJCL использует механизм “partial word” — последний элемент массива может хранить не 32, а меньше бит.

Это реализуется через специальное кодирование:

  • в старших битах хранится число значимых бит
  • младшие биты содержат полезную нагрузку

Типичная идея:

[ word1, word2, ..., lastWordWithPartialInfo ]

Где последний элемент не полностью заполнен.


Основные операции над bitArray

Вся работа с bitArray осуществляется через набор функций, определённых в sjcl.bitArray.

Конкатенация

Объединение двух битовых массивов:

sjcl.bitArray.concat(a, b);

Логика:

  • слова из b дописываются к a
  • учитывается возможная неполная заполненность последнего слова

Получение длины

sjcl.bitArray.bitLength(a);

Функция вычисляет количество значимых бит во всём массиве.

Важно:

  • учитывается partial word
  • не равняется a.length * 32

Обрезка (clamp)

sjcl.bitArray.clamp(a, len);

Операция ограничивает битовый массив первыми len битами.

Используется при:

  • формировании хэшей фиксированной длины
  • обрезке ключей
  • приведении блоков к нужному размеру

Сдвиги

SJCL реализует битовые сдвиги на уровне массива:

sjcl.bitArray.shiftRight(a, n);
sjcl.bitArray.shiftLeft(a, n);

Особенности:

  • сдвиг выполняется сквозь границы 32-битных слов
  • учитывается перенос между элементами массива
  • partial word корректируется автоматически

XOR-операции

Одна из ключевых операций в криптографии:

sjcl.bitArray.xor(a, b);

Используется в:

  • потоковых шифрах
  • режимах CBC/CFB
  • генерации псевдослучайных последовательностей

Поведение:

  • выполняется побитовое XOR по словам
  • длина результата соответствует минимальной длине входов

Представление байтов и преобразования

bitArray не является байтовым массивом, поэтому SJCL предоставляет конвертеры.

bytes → bitArray

sjcl.codec.bytes.toBits(bytes);

Правила:

  • каждые 4 байта объединяются в 32-битное слово
  • недостающие байты дополняются нулями

bitArray → bytes

sjcl.codec.bytes.fromBits(bits);

Используется при:

  • выводе шифротекста
  • сериализации ключей
  • интеграции с внешними API

Внутренняя модель хранения слов

Каждое 32-битное слово в SJCL фактически обрабатывается как беззнаковое:

  • операции AND/OR/XOR приводятся к unsigned виду
  • сдвиги выполняются через >>> и <<
  • переполнение игнорируется на уровне JS (из-за 32-bit coercion)

Это важно, потому что JavaScript числа — IEEE 754 double, но SJCL искусственно ограничивает их до 32 бит через битовые операции.


Особенности арифметики на битовых массивах

SJCL не использует bitArray как арифметическую структуру, но через него реализуются:

  • сложение в алгоритмах хэшей
  • вращения (rotations)
  • поблочные операции в AES

Пример вращения:

sjcl.bitArray.rotl(x, n);

Используется в:

  • SHA-256
  • SHA-512
  • BLAKE-подобных конструкциях внутри SJCL

Внутренние вспомогательные операции

Помимо базовых операций, bitArray поддерживает низкоуровневые функции:

slice

Извлечение диапазона бит:

sjcl.bitArray.bitSlice(a, start, end);

Позволяет работать с подстроками битового потока.


equal

Сравнение двух массивов:

sjcl.bitArray.equal(a, b);

Используется для:

  • проверки MAC
  • сравнения хэшей
  • проверки ключей

Важно: сравнение реализовано так, чтобы минимизировать утечки по времени (constant-time поведение в пределах возможностей JS).


Роль bitArray в архитектуре SJCL

bitArray является фундаментом всей библиотеки:

  • AES работает на блоках, представленных через bitArray
  • HMAC принимает и возвращает bitArray
  • PBKDF2 использует bitArray как промежуточный формат
  • ECC-операции также используют его для сериализации координат

Фактически SJCL не оперирует “байтами” в классическом смысле — весь стек построен поверх битового потока.


Преобразование произвольных данных в bitArray

Любой вход в SJCL в конечном счёте приводится к bitArray:

  • строки → UTF-8 → bytes → bitArray
  • hex → bytes → bitArray
  • случайные значения → bitArray напрямую

Пример:

sjcl.codec.utf8String.toBits("test");

Особенности производительности

bitArray не оптимизирован под высокоуровневые структуры:

  • частые операции создают новые массивы
  • конкатенация требует копирования
  • нет мутабельных in-place оптимизаций для большинства операций

Это осознанный компромисс:

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

Ограничения модели

Несмотря на универсальность, bitArray имеет ограничения:

  • нет нативной поддержки 64-битных слов
  • отсутствует типизация
  • возможны накладные расходы при больших объёмах данных
  • сложнее интеграция с современными WebCrypto API без конвертации

Типовой жизненный цикл данных в SJCL

  1. входная строка или массив байтов
  2. преобразование в bitArray
  3. криптографические операции (AES, SHA, HMAC)
  4. промежуточные bitArray-структуры
  5. преобразование обратно в байты или строку

bitArray выступает как универсальный “язык общения” между всеми стадиями.


Ключевая идея модели

bitArray — это компромисс между:

  • низкоуровневой битовой точностью
  • удобством JavaScript-структур
  • предсказуемостью криптографических преобразований

Он не пытается быть эффективным контейнером данных. Его задача — гарантировать корректную и однозначную работу битовых операций во всех алгоритмах SJCL.