Модуль node:crypto является фундаментальным компонентом
криптографической инфраструктуры Node.js. Он предоставляет
низкоуровневый доступ к OpenSSL и используется как основа для
большинства криптографических операций в экосистеме JavaScript, включая
подпись токенов, шифрование данных и проверку целостности.
Несмотря на то, что высокоуровневые библиотеки вроде
jose абстрагируют сложность криптографии, понимание
ограничений и особенностей node:crypto критично для
корректной и безопасной работы с JWT, JWS, JWE и JWK.
Базовая модель
node:crypto
Модуль предоставляет функциональность через обёртку над OpenSSL, что
означает зависимость от:
- версии OpenSSL, встроенной в Node.js
- конфигурации сборки Node.js
- политики безопасности (FIPS mode, если включён)
Основные категории возможностей:
Хеширование
- SHA-1 (устаревший)
- SHA-256 / SHA-512
- MD5 (небезопасен, но доступен)
HMAC
- HMAC-SHA256 и другие вариации
Шифрование
- AES (CBC, GCM, CTR)
- RSA (PKCS#1 v1.5, OAEP)
- ECDSA / ECDH
Генерация ключей
- симметричные ключи
- асимметричные пары
Ключевая проблема:
абстракция OpenSSL
Node.js не реализует криптографию самостоятельно. Это приводит к
нескольким важным ограничениям:
Зависимость от версии
OpenSSL
Разные версии Node.js используют разные версии OpenSSL, что влияет
на:
- доступность алгоритмов
- поведение padding-режимов
- поддержку новых стандартов (например, Ed25519)
Некоторые алгоритмы могут:
- быть отключены по умолчанию
- требовать legacy provider
- полностью отсутствовать в старых версиях Node.js
Непредсказуемость алгоритмов
Один и тот же код может вести себя по-разному:
- в Node.js 16 (OpenSSL 1.1.1)
- в Node.js 20+ (OpenSSL 3.x)
Особенно это критично для:
- RSA-PSS
- EdDSA
- ECDSA с нестандартными кривыми
Ограничения безопасности
node:crypto
1. Устаревшие
алгоритмы доступны по умолчанию
Node.js исторически поддерживает алгоритмы, которые считаются
небезопасными:
- MD5
- SHA-1 (для подписи)
- RSA с PKCS#1 v1.5 padding
Это создаёт риск:
- случайного использования слабых схем
- совместимости в ущерб безопасности
2. Отсутствие
строгой политики безопасных дефолтов
node:crypto не запрещает небезопасные операции.
Например:
createSign('RSA-SHA1')
возможно, хотя SHA-1 давно считается компрометированным.
3. Ошибки использования ключей
Типичные проблемы:
- использование симметричного ключа там, где нужен асимметричный
- неправильная длина ключа AES
- повторное использование IV в GCM
Node.js не валидирует криптографическую корректность на уровне
архитектуры.
Особенности
работы с асимметричной криптографией
RSA
Поддерживаются:
- PKCS#1 v1.5 (устаревший)
- OAEP (рекомендуемый)
Проблемы:
- несовместимость padding между библиотеками
- различия в реализации OpenSSL
ECDSA
Используется для цифровых подписей, но имеет особенности:
- требовательность к кривым (P-256, P-384, P-521)
- чувствительность к формату DER/JOSE
Ed25519
Поддержка появилась относительно недавно и зависит от версии
Node.js.
Ограничения:
- не везде доступен в legacy режимах
- несовместимость с некоторыми реализациями OpenSSL
Симметричное шифрование
AES-GCM как стандарт
Рекомендуемый режим:
- обеспечивает конфиденциальность и целостность
- требует уникального IV
Критические ошибки:
- повторное использование nonce полностью ломает безопасность
- неправильная обработка auth tag
CBC и его риски
AES-CBC:
- требует отдельного HMAC для целостности
- уязвим к padding oracle атакам при неправильной реализации
Взаимодействие с библиотекой
jose
Библиотека jose строится поверх криптографических
возможностей Node.js, но не зависит от crypto напрямую в
логике протоколов — она использует его как backend.
Основные задачи
node:crypto в jose:
- генерация подписей (JWS)
- шифрование (JWE)
- работа с ключами (JWK import/export)
- проверка JWT
Ограничения
при использовании jose через node:crypto
1. Несовпадение алгоритмов
Некоторые алгоритмы JOSE:
могут работать по-разному в зависимости от OpenSSL.
2. Проблемы с импортом ключей
Форматы:
Node.js требует точного соответствия формата, иначе:
- ошибки парсинга
- некорректные подписи
3. Различие между
WebCrypto и node:crypto
В современных версиях Node.js есть WebCrypto API, и он
отличается:
| node:crypto |
WebCrypto |
| синхронный API |
асинхронный |
| OpenSSL backend |
браузерный стандарт |
| больше алгоритмов |
более строгая спецификация |
jose может переключаться между ними, что влияет на
поведение.
Производительность и
системные ограничения
Синхронность операций
node:crypto в основном синхронный:
- блокирует event loop при тяжёлых операциях
- может снижать throughput сервера
Особенно заметно при:
- массовой генерации JWT
- RSA-операциях
Ограничения OpenSSL
- размер ключей RSA влияет на скорость экспоненциально
- ECDSA быстрее, но чувствителен к параметрам кривой
Безопасные практики работы
Использование современных
алгоритмов
Рекомендуемые:
- ES256 / ES384 / ES512
- RS256 (с OAEP для шифрования)
- EdDSA (Ed25519)
Запрет устаревших схем
Следует избегать:
- SHA-1
- MD5
- RSA-PKCS1 v1.5 для новых систем
Контроль ключей
Критично:
- хранить ключи вне кода
- использовать HSM или KMS при возможности
- ограничивать доступ к приватным ключам
Типичные ошибки
разработчиков
1. Неправильный выбор
алгоритма
Часто выбирается:
- RS256 «по привычке»
- вместо более современных схем
2. Игнорирование nonce/IV
Особенно в AES-GCM:
- повтор IV = компрометация данных
3. Смешивание библиотек
Использование:
crypto + сторонние реализации JOSE
приводит к:
- несовместимым токенам
- ошибкам подписи
Влияние версии Node.js
Поведение криптографии меняется между версиями:
- Node.js 14: старый OpenSSL, больше legacy алгоритмов
- Node.js 18: переходный режим
- Node.js 20+: OpenSSL 3, строгие ограничения
Это влияет на:
- доступность алгоритмов
- дефолтные политики безопасности
- совместимость JWT
Итоговая картина ограничений
node:crypto можно рассматривать как мощный, но
низкоуровневый инструмент, в котором:
- безопасность зависит от разработчика
- совместимость зависит от OpenSSL
- поведение зависит от версии Node.js
Библиотеки вроде jose закрывают часть этих проблем, но
не устраняют фундаментальные ограничения криптографической платформы
Node.js.