Совместимость с серверными реализациями

Серверные среды исполнения JavaScript исторически развивались вокруг собственных криптографических примитивов, и лишь позднее начали приближаться к спецификации Web Crypto API. Несмотря на общую идею унификации, поведение SubtleCrypto и набор доступных алгоритмов в браузере и на сервере часто различаются не только по реализации, но и по архитектурным ограничениям платформ.

В браузере Web Crypto API опирается на встроенные системные библиотеки операционной системы или изолированные реализации, контролируемые браузерным движком. На сервере JavaScript работает в окружении, где криптография почти всегда реализована через нативные биндинги.

В случае Node.js основой выступает OpenSSL, что определяет:

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

Deno использует аналогичный подход, но стремится к более строгому соответствию стандарту Web Crypto API. Bun, в свою очередь, реализует собственный слой поверх системных библиотек, оптимизируя производительность и частично расширяя API.

Node.js и реализация Web Crypto API

В Node.js доступ к Web Crypto API предоставляется через модуль crypto.webcrypto. Его архитектура представляет собой адаптацию браузерного стандарта поверх OpenSSL.

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

  • объект crypto.subtle соответствует спецификации W3C
  • поддерживаются Promise-основанные методы
  • часть алгоритмов зависит от версии OpenSSL
  • различается поведение в Node 16, 18, 20 и более новых версиях

Поддержка алгоритмов

Поддержка алгоритмов в Node.js не полностью совпадает с браузером:

  • AES-CBC, AES-GCM — поддерживаются стабильно
  • RSA-OAEP, RSA-PSS — поддерживаются, но с различиями в параметрах
  • ECDSA — зависит от кривых, доступных OpenSSL
  • HKDF и PBKDF2 — реализованы полностью
  • Ed25519 и Ed448 — появились относительно поздно и требуют новых версий Node

Отдельной особенностью является наличие legacy-алгоритмов, которые существуют в Node.js, но отсутствуют в Web Crypto API браузеров.

Deno как наиболее строгая реализация стандарта

Deno стремится к максимальному соответствию спецификации Web Crypto API. Его реализация:

  • полностью асинхронная
  • соответствует структуре браузерного SubtleCrypto
  • минимизирует отклонения в сигнатурах методов

Однако даже в Deno присутствуют системные ограничения:

  • криптографические операции зависят от версии Rust-библиотек
  • некоторые алгоритмы доступны только при компиляции с определёнными флагами
  • производительность может отличаться от Node.js из-за различий в FFI-слое

Deno чаще используется как эталон поведения Web Crypto API в серверной среде, но не всегда совпадает с реальными браузерами по деталям реализации.

Bun и оптимизированная криптография

Bun реализует Web Crypto API с приоритетом на скорость. В отличие от Node.js и Deno, он активно использует собственные оптимизированные реализации и системные вызовы.

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

  • высокая скорость операций AES и SHA
  • частичная замена OpenSSL-слоя
  • более агрессивное кэширование ключевых операций
  • возможные расхождения с W3C-спецификацией в edge cases

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

Различия в генерации ключей

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

RSA

В браузере параметры RSA строго ограничены:

  • длины ключей фиксированы (2048, 3072, 4096)
  • публичные экспоненты обычно 65537

В Node.js допускаются более гибкие параметры, включая нестандартные экспоненты, что может привести к несовместимости при переносе ключей между окружениями.

ECDSA и ECDH

Различия проявляются в поддержке кривых:

  • P-256, P-384, P-521 — универсально поддерживаются
  • secp256k1 — часто поддерживается в Node.js, но отсутствует в браузерах
  • X25519 / Ed25519 — поддержка зависит от версии runtime

Форматы экспорта и импорта ключей

Web Crypto API стандартизирует форматы:

  • spki для публичных ключей
  • pkcs8 для приватных ключей
  • jwk как JSON-представление

Серверные реализации могут расширять эти форматы:

  • Node.js поддерживает дополнительные PEM-конверсии через crypto
  • Deno строго следует ArrayBuffer-ориентированным структурам
  • Bun допускает упрощённые преобразования между форматами

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

Случайные числа и криптографическая стойкость

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

  • Node.js — crypto.randomBytes
  • Deno — системный CSPRNG
  • Bun — оптимизированный системный источник

Несмотря на единый принцип, различия возникают в:

  • блокировке потоков при генерации больших объёмов данных
  • скорости генерации
  • поведении в контейнеризированных средах

Особенно критично это при высоконагруженных системах, где Web Crypto API используется для генерации токенов.

Совместимость алгоритмов хэширования

Алгоритмы SHA семейства демонстрируют наибольшую совместимость:

  • SHA-1 — поддерживается везде, но считается устаревшим
  • SHA-256 / SHA-384 / SHA-512 — полностью совместимы
  • SHA-3 — поддержка варьируется и часто отсутствует в стандартном Web Crypto API

Node.js может предоставлять расширенные варианты через OpenSSL, которые не существуют в браузере.

Проблемы переносимости между средами

Основные несовместимости возникают не на уровне алгоритмов, а на уровне API:

1. Различие в типах данных

  • браузер: ArrayBuffer, TypedArray
  • Node.js: допускает Buffer как расширение

Это приводит к ошибкам при переносе кода без адаптации типов.

2. Поведение ошибок

  • браузеры используют DOMException
  • Node.js часто использует стандартные Error с кодами OpenSSL

3. Поддержка streaming-операций

Web Crypto API не поддерживает потоковую обработку, но серверные обёртки могут её эмулировать, что создаёт расхождения в производительности и логике.

Edge-среды и ограниченные реализации

Cloudflare Workers, Vercel Edge Runtime и аналогичные среды реализуют Web Crypto API с ограничениями:

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

Такие среды ближе к браузерной модели, чем к Node.js, что упрощает перенос фронтенд-кода, но ограничивает криптографическую гибкость.

Стратегии обеспечения совместимости

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

  • использование только подмножества алгоритмов Web Crypto API, совместимого с браузерами
  • отказ от Node.js-specific расширений (crypto legacy API)
  • фиксация форматов ключей в JWK
  • явное управление типами данных (ArrayBuffer как основной формат)
  • избегание нестандартных параметров криптографических функций

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

Границы унификации

Полная унификация Web Crypto API между браузером и сервером остаётся недостижимой из-за фундаментальных различий архитектур:

  • браузеры ориентированы на безопасность и изоляцию
  • серверные среды ориентированы на производительность и контроль
  • спецификация Web Crypto API описывает поведение, но не реализацию

Это приводит к тому, что совместимость существует на уровне интерфейсов, но не гарантируется на уровне бинарной эквивалентности результатов в каждом edge case.