Утечка данных через побочные каналы в JS

Побочные каналы в криптографических реализациях на JavaScript представляют особую проблему из-за особенностей выполнения кода в среде браузера и интерпретируемой природы языка. Даже при корректной математической реализации алгоритмов утечки информации могут происходить через время выполнения, особенности работы памяти, кэш процессора, поведение сборщика мусора и различия в ветвлениях исполнения кода.

В отличие от низкоуровневых языков, где разработчик может напрямую контролировать работу с памятью и процессорными инструкциями, JavaScript абстрагирует большую часть системных деталей. Это создаёт иллюзию безопасности, однако именно эта абстракция формирует новые векторы атак.

Ключевые источники утечек:

  • время выполнения операций
  • различия в доступе к памяти
  • оптимизации JIT-компилятора
  • особенности работы строк и массивов
  • поведение garbage collector
  • кэширование CPU

Даже при использовании криптографически стойких алгоритмов, таких как AES или SHA, реализация на уровне языка может раскрывать информацию о секретных данных.

Timing-атаки в контексте JavaScript

Наиболее изученный класс побочных каналов — атаки по времени выполнения. В JavaScript они особенно критичны, поскольку интерпретатор и JIT-компиляция создают нестабильную модель исполнения.

Типичный пример уязвимости:

function compare(a, b) {
    if (a.length !== b.length) return false;
    for (let i = 0; i < a.length; i++) {
        if (a[i] !== b[i]) return false;
    }
    return true;
}

Такое сравнение строк или массивов позволяет атакующему измерять время выхода из функции и постепенно восстанавливать секретные данные.

Ключевая проблема — ранний выход из цикла. Различия в количестве итераций становятся измеримым сигналом.

SJCL и модель угроз побочных каналов

Stanford Javascript Crypto Library (SJCL) изначально проектировалась с учётом ограничений JavaScript-среды. Основной упор сделан на минимизацию утечек через:

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

Внутренняя архитектура SJCL старается придерживаться принципа constant-time execution, однако полностью гарантировать отсутствие побочных каналов в JavaScript невозможно.

Константное время и его ограничения

Идея константного времени заключается в том, что операция должна выполняться одинаково долго независимо от входных данных. В SJCL это применяется, например, в сравнении блоков данных и криптографических преобразованиях.

Однако в JavaScript существуют фундаментальные препятствия:

  • JIT-компилятор может оптимизировать код по-разному в зависимости от входных данных
  • движки браузеров (V8, SpiderMonkey, JavaScriptCore) по-разному интерпретируют одинаковый код
  • кэш процессора влияет на время доступа к памяти
  • строки и массивы могут храниться в разных представлениях

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

Утечки через кэш и структуру памяти

Современные атаки часто используют не только время выполнения, но и особенности работы процессорного кэша. В JavaScript это проявляется через:

  • доступ к индексам массивов
  • работу с объектами и их hidden classes
  • различия между packed и holey arrays в V8

SJCL минимизирует подобные эффекты за счёт работы с фиксированными структурами данных, например 32-битными словами, однако полностью устранить влияние движка невозможно.

Побочные каналы через строки

Строки в JavaScript являются неизменяемыми, но их внутренняя реализация может отличаться:

  • one-byte strings
  • two-byte strings (UTF-16)
  • переходные представления при конкатенации

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

SJCL избегает работы со строками в критических операциях, предпочитая битовые массивы.

Утечки через JIT-оптимизацию

Современные JavaScript-движки используют JIT-компиляцию, которая может приводить к непредсказуемым различиям в производительности:

  • инлайнинг функций
  • деоптимизация при изменении типов
  • переход между baseline и optimized code paths

В криптографическом контексте это критично, поскольку атакующий может измерять микроскопические различия во времени выполнения.

SJCL старается использовать стабильные паттерны кода, которые не провоцируют деоптимизацию.

Проблема ветвлений и секрет-зависимого кода

Любое ветвление, зависящее от секретных данных, потенциально раскрывает информацию:

if (secretBit === 1) {
    result ^= mask;
}

Даже если логика кажется безобидной, различие в пути исполнения может быть измерено.

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

result ^= mask & -secretBit;

Такая форма устраняет явное ветвление, но не гарантирует полное отсутствие утечек на уровне процессора.

Работа с памятью и garbage collector

Garbage collector в JavaScript является ещё одним источником побочных каналов:

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

При криптографических операциях это может создавать измеримые задержки, зависящие от структуры данных.

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

Практики снижения утечек в SJCL

Основные подходы, используемые в библиотеке:

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

Особое внимание уделяется операциям сравнения, где используется XOR-аккумуляция вместо поэлементного выхода.

Ограничения модели безопасности JavaScript

Несмотря на все меры, JavaScript остаётся средой с принципиально ограниченной возможностью защиты от побочных каналов. Основные причины:

  • отсутствие контроля над процессорным уровнем
  • вариативность движков браузеров
  • оптимизации исполнения, не учитывающие криптографические требования
  • влияние многопоточности и event loop

SJCL можно рассматривать как инженерный компромисс между безопасностью и возможностью выполнения в браузере, но не как строго защищённую от всех побочных каналов реализацию.

Атаки через измерение времени в браузере

Современные атаки могут использовать высокоточные таймеры:

  • performance.now()
  • SharedArrayBuffer-based timers
  • requestAnimationFrame-based измерения

Даже наносекундные различия могут быть агрегированы статистически и использованы для восстановления секретов при многократных измерениях.

Итоговая модель угроз

При анализе криптографии в JavaScript необходимо учитывать, что утечки происходят не только на уровне алгоритма, но и на уровне исполнения:

  • микроразличия времени
  • кэш процессора
  • особенности JIT
  • поведение памяти
  • структура объектов

SJCL снижает поверхность атаки, но не устраняет фундаментальные ограничения среды выполнения.