В 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. Реальная стоимость определяется несколькими факторами:
Особенно важно различие между потоковыми и блочными режимами. Потоковые режимы позволяют обрабатывать блоки независимо, что лучше ложится на JIT-оптимизации. Блочные режимы с цепочками зависимостей ограничивают параллелизм внутри интерпретатора.
CTR (Counter Mode) в SJCL обычно демонстрирует наивысшую производительность среди всех режимов AES.
CTR преобразует блочный шифр в потоковый за счёт генерации последовательности блоков-ключей, зависящих только от счётчика:
Ключевой фактор скорости CTR — отсутствие цепочки состояний. Это позволяет JavaScript-движкам агрессивно оптимизировать цикл шифрования, минимизируя проверки и обращения к памяти.
Основное ограничение CTR связано не с AES, а с операциями увеличения счётчика и управлением буферами.
CBC (Cipher Block Chaining) значительно медленнее CTR из-за строгой последовательной зависимости.
Каждый блок:
Это создаёт критическую цепочку:
В JS это особенно заметно, поскольку каждый новый блок требует обращения к результату предыдущего, что ограничивает эффективность кеширования CPU и оптимизаций движка.
CBC часто демонстрирует стабильную, но более низкую пропускную способность по сравнению с CTR при увеличении объема данных.
CFB (Cipher Feedback) и OFB (Output Feedback) занимают промежуточное положение между CTR и CBC.
CFB:
OFB:
На практике OFB часто оказывается ближе к CTR по скорости, но уступает из-за более сложной схемы обновления состояния и дополнительных операций с буферами.
CFB, в свою очередь, ближе к CBC по производительности, поскольку сохраняет цепочку зависимостей.
Режимы с аутентификацией данных существенно увеличивают вычислительную стоимость.
CCM объединяет CTR-шифрование и CBC-MAC:
Основной источник замедления:
В SJCL это особенно заметно на больших сообщениях, где MAC становится сравним по стоимости с самим шифрованием.
GCM использует GHASH на основе полиномиальной арифметики в поле GF(2^128).
Основные факторы нагрузки:
Хотя GCM теоретически хорошо параллелизуется, в чистом JavaScript реализация GHASH становится узким местом из-за отсутствия аппаратных инструкций carry-less multiplication.
OCB2 исторически считается более быстрым AEAD-режимом, поскольку объединяет шифрование и аутентификацию в один проход.
Однако в SJCL он ограничен патентными и историческими факторами использования, а также сложностью реализации.
Разница между режимами AES в SJCL определяется не самим AES, а структурой надстройки:
Важным фактором является также работа с памятью:
Производительность SJCL напрямую зависит от оптимизаций конкретного JS-движка:
Дополнительное влияние оказывают:
Особенно критично использование “плоских” структур данных (ArrayBuffer / Uint32Array), поскольку SJCL исторически опирается на массивы чисел, что увеличивает стоимость преобразований.
При малых объёмах данных накладные расходы инициализации режима часто доминируют над самим AES.
При увеличении объёма:
На больших потоках данных различие между режимами становится более выраженным, поскольку стоимость инициализации амортизируется, и остаётся чистая криптографическая нагрузка.
В типичной JS-реализации SJCL порядок производительности обычно выстраивается следующим образом: