Сравнение производительности режимов AES

В Stanford JavaScript Crypto Library (SJCL) реализация AES построена вокруг базового блочного шифра с размером блока 128 бит и поддержкой ключей 128/192/256 бит. Сам AES в библиотеке представлен как низкоуровневый примитив, поверх которого реализуются различные режимы работы: CBC, CFB, OFB, CTR, CCM, GCM и исторически OCB2.

Ключевая особенность архитектуры SJCL заключается в том, что все режимы реализованы на чистом JavaScript без использования нативных криптографических расширений браузера. Это делает производительность полностью зависимой от движка JavaScript (V8, SpiderMonkey, JavaScriptCore), а также от структуры самого алгоритма — количества последовательных зависимостей, возможности распараллеливания и числа операций над 32-битными словами.

AES в SJCL оперирует 32-битными словами, что важно для производительности: JavaScript эффективно работает с побитовыми операциями именно в этом диапазоне, но любые дополнительные преобразования (массивы, буферы, копирования состояния) становятся критическими для итоговой скорости.


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

Сравнение режимов AES в SJCL некорректно сводить только к количеству операций XOR или вызовов S-box. Реальная стоимость определяется несколькими факторами:

  • количество последовательных зависимостей между блоками
  • возможность потоковой обработки данных
  • наличие или отсутствие аутентификации
  • объем служебных операций (padding, MAC)
  • количество копирований буферов
  • накладные расходы на инициализацию состояния

Особенно важно различие между потоковыми и блочными режимами. Потоковые режимы позволяют обрабатывать блоки независимо, что лучше ложится на JIT-оптимизации. Блочные режимы с цепочками зависимостей ограничивают параллелизм внутри интерпретатора.


CTR как эталон производительности

CTR (Counter Mode) в SJCL обычно демонстрирует наивысшую производительность среди всех режимов AES.

CTR преобразует блочный шифр в потоковый за счёт генерации последовательности блоков-ключей, зависящих только от счётчика:

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

Ключевой фактор скорости CTR — отсутствие цепочки состояний. Это позволяет JavaScript-движкам агрессивно оптимизировать цикл шифрования, минимизируя проверки и обращения к памяти.

Основное ограничение CTR связано не с AES, а с операциями увеличения счётчика и управлением буферами.


CBC и влияние цепочки зависимостей

CBC (Cipher Block Chaining) значительно медленнее CTR из-за строгой последовательной зависимости.

Каждый блок:

  • XOR-ится с предыдущим зашифрованным блоком
  • затем проходит через AES

Это создаёт критическую цепочку:

  • невозможность параллельной обработки
  • ухудшение предсказуемости для JIT
  • рост стоимости pipeline stalls внутри интерпретатора

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

CBC часто демонстрирует стабильную, но более низкую пропускную способность по сравнению с CTR при увеличении объема данных.


CFB и OFB: промежуточный класс производительности

CFB (Cipher Feedback) и OFB (Output Feedback) занимают промежуточное положение между CTR и CBC.

CFB:

  • зависит от предыдущего шифротекста
  • сохраняет последовательный характер обработки
  • требует дополнительного XOR на каждом шаге

OFB:

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

На практике OFB часто оказывается ближе к CTR по скорости, но уступает из-за более сложной схемы обновления состояния и дополнительных операций с буферами.

CFB, в свою очередь, ближе к CBC по производительности, поскольку сохраняет цепочку зависимостей.


CCM, GCM и стоимость аутентификации

Режимы с аутентификацией данных существенно увеличивают вычислительную стоимость.

CCM

CCM объединяет CTR-шифрование и CBC-MAC:

  • шифрование выполняется в CTR
  • затем отдельно вычисляется MAC через CBC

Основной источник замедления:

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

В SJCL это особенно заметно на больших сообщениях, где MAC становится сравним по стоимости с самим шифрованием.

GCM

GCM использует GHASH на основе полиномиальной арифметики в поле GF(2^128).

Основные факторы нагрузки:

  • умножения в конечном поле
  • накопление состояния хэша
  • обработка блоков аутентификации параллельно с CTR

Хотя GCM теоретически хорошо параллелизуется, в чистом JavaScript реализация GHASH становится узким местом из-за отсутствия аппаратных инструкций carry-less multiplication.

OCB2

OCB2 исторически считается более быстрым AEAD-режимом, поскольку объединяет шифрование и аутентификацию в один проход.

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


Причины различий в производительности

Разница между режимами AES в SJCL определяется не самим AES, а структурой надстройки:

  • CTR: минимальные зависимости, высокая эффективность JIT
  • CBC/CFB: строгая последовательность блоков
  • OFB: потоковая модель с умеренными накладными расходами
  • CCM/GCM: дополнительные криптографические операции поверх AES

Важным фактором является также работа с памятью:

  • частые аллокации временных массивов резко снижают скорость
  • JS-движки оптимизируют предсказуемые циклы
  • доступ к массивам 32-битных слов быстрее, чем к байтовым структурам

Влияние особенностей JavaScript-движков

Производительность SJCL напрямую зависит от оптимизаций конкретного JS-движка:

  • V8 (Chrome, Node.js) эффективно оптимизирует CTR-подобные циклы
  • SpiderMonkey (Firefox) чувствителен к типизации массивов
  • JavaScriptCore (Safari) быстрее на коротких сообщениях, но хуже масштабируется

Дополнительное влияние оказывают:

  • переходы между “hot” и “cold” кодом JIT
  • деоптимизация функций при изменении типов входных данных
  • выравнивание данных в памяти

Особенно критично использование “плоских” структур данных (ArrayBuffer / Uint32Array), поскольку SJCL исторически опирается на массивы чисел, что увеличивает стоимость преобразований.


Масштабирование производительности с размером данных

При малых объёмах данных накладные расходы инициализации режима часто доминируют над самим AES.

При увеличении объёма:

  • CTR демонстрирует линейную масштабируемость с высоким коэффициентом пропускной способности
  • CBC и CFB растут линейно, но с меньшим наклоном
  • CCM и GCM имеют заметный дополнительный overhead, связанный с MAC

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


Общая картина относительной скорости режимов

В типичной JS-реализации SJCL порядок производительности обычно выстраивается следующим образом:

  • CTR — максимальная скорость
  • OFB — близко к CTR, но с небольшим overhead
  • CBC — средний уровень с последовательными зависимостями
  • CFB — сопоставим с CBC или немного медленнее
  • CCM — существенно медленнее из-за двойной обработки
  • GCM — зависит от эффективности GHASH, часто медленнее CTR
  • OCB2 — потенциально быстрый, но зависит от реализации и контекста использования