Криптография¶
Стабильность: 2 — Стабильная
Модуль node:crypto предоставляет криптографические возможности, включая обёртки над функциями OpenSSL для хэшей, HMAC, шифрования и расшифрования, подписи и проверки.
1 2 3 4 5 6 7 8 9 | |
1 2 3 4 5 6 7 8 9 | |
Когда поддержка crypto недоступна¶
Node.js может быть собран без модуля node:crypto. Тогда import из crypto или вызов require('node:crypto') приведут к ошибке.
В CommonJS ошибку можно перехватить через try/catch:
1 2 3 4 5 6 | |
При лексическом import в ESM ошибку можно перехватить только если обработчик process.on('uncaughtException') зарегистрирован до любой попытки загрузить модуль (например через preload).
Если код может выполняться в сборке Node.js без crypto, вместо лексического import используйте динамический [import()][import()]:
1 2 3 4 5 6 | |
Типы асимметричных ключей¶
В таблице — типы асимметричных ключей, которые распознаёт API [KeyObject][KeyObject], и поддерживаемые форматы импорта/экспорта.
| Тип ключа | Описание | OID | 'pem' | 'der' | 'jwk' | 'raw-public' | 'raw-private' | 'raw-seed' |
|---|---|---|---|---|---|---|---|---|
'dh' | Diffie-Hellman | 1.2.840.113549.1.3.1 | ✔ | ✔ | ||||
'dsa' | DSA | 1.2.840.10040.4.1 | ✔ | ✔ | ||||
'ec' | Elliptic curve | 1.2.840.10045.2.1 | ✔ | ✔ | ✔ | ✔ | ✔ | |
'ed25519' | Ed25519 | 1.3.101.112 | ✔ | ✔ | ✔ | ✔ | ✔ | |
'ed448' | Ed448 | 1.3.101.113 | ✔ | ✔ | ✔ | ✔ | ✔ | |
'ml-dsa-44'3 | ML-DSA-44 | 2.16.840.1.101.3.4.3.17 | ✔ | ✔ | ✔ | ✔ | ✔ | |
'ml-dsa-65'3 | ML-DSA-65 | 2.16.840.1.101.3.4.3.18 | ✔ | ✔ | ✔ | ✔ | ✔ | |
'ml-dsa-87'3 | ML-DSA-87 | 2.16.840.1.101.3.4.3.19 | ✔ | ✔ | ✔ | ✔ | ✔ | |
'ml-kem-512'3 | ML-KEM-512 | 2.16.840.1.101.3.4.4.1 | ✔ | ✔ | ✔ | ✔ | ||
'ml-kem-768'3 | ML-KEM-768 | 2.16.840.1.101.3.4.4.2 | ✔ | ✔ | ✔ | ✔ | ||
'ml-kem-1024'3 | ML-KEM-1024 | 2.16.840.1.101.3.4.4.3 | ✔ | ✔ | ✔ | ✔ | ||
'rsa-pss' | RSA PSS | 1.2.840.113549.1.1.10 | ✔ | ✔ | ||||
'rsa' | RSA | 1.2.840.113549.1.1.1 | ✔ | ✔ | ✔ | |||
'slh-dsa-sha2-128f'3 | SLH-DSA-SHA2-128f | 2.16.840.1.101.3.4.3.21 | ✔ | ✔ | ✔ | ✔ | ||
'slh-dsa-sha2-128s'3 | SLH-DSA-SHA2-128s | 2.16.840.1.101.3.4.3.20 | ✔ | ✔ | ✔ | ✔ | ||
'slh-dsa-sha2-192f'3 | SLH-DSA-SHA2-192f | 2.16.840.1.101.3.4.3.23 | ✔ | ✔ | ✔ | ✔ | ||
'slh-dsa-sha2-192s'3 | SLH-DSA-SHA2-192s | 2.16.840.1.101.3.4.3.22 | ✔ | ✔ | ✔ | ✔ | ||
'slh-dsa-sha2-256f'3 | SLH-DSA-SHA2-256f | 2.16.840.1.101.3.4.3.25 | ✔ | ✔ | ✔ | ✔ | ||
'slh-dsa-sha2-256s'3 | SLH-DSA-SHA2-256s | 2.16.840.1.101.3.4.3.24 | ✔ | ✔ | ✔ | ✔ | ||
'slh-dsa-shake-128f'3 | SLH-DSA-SHAKE-128f | 2.16.840.1.101.3.4.3.27 | ✔ | ✔ | ✔ | ✔ | ||
'slh-dsa-shake-128s'3 | SLH-DSA-SHAKE-128s | 2.16.840.1.101.3.4.3.26 | ✔ | ✔ | ✔ | ✔ | ||
'slh-dsa-shake-192f'3 | SLH-DSA-SHAKE-192f | 2.16.840.1.101.3.4.3.29 | ✔ | ✔ | ✔ | ✔ | ||
'slh-dsa-shake-192s'3 | SLH-DSA-SHAKE-192s | 2.16.840.1.101.3.4.3.28 | ✔ | ✔ | ✔ | ✔ | ||
'slh-dsa-shake-256f'3 | SLH-DSA-SHAKE-256f | 2.16.840.1.101.3.4.3.31 | ✔ | ✔ | ✔ | ✔ | ||
'slh-dsa-shake-256s'3 | SLH-DSA-SHAKE-256s | 2.16.840.1.101.3.4.3.30 | ✔ | ✔ | ✔ | ✔ | ||
'x25519' | X25519 | 1.3.101.110 | ✔ | ✔ | ✔ | ✔ | ✔ | |
'x448' | X448 | 1.3.101.111 | ✔ | ✔ | ✔ | ✔ | ✔ |
Форматы ключей¶
Асимметричные ключи можно представить в нескольких форматах. Рекомендуется один раз импортировать материал ключа в [KeyObject][KeyObject] и переиспользовать его для всех дальнейших операций — так не повторяется разбор и достигается лучшая производительность.
Если [KeyObject][KeyObject] неудобен (например ключ приходит в сообщении протокола и используется один раз), большинство криптографических функций принимают строку PEM или объект с форматом и материалом ключа. Полный набор опций — в [crypto.createPublicKey()][crypto.createPublicKey()], [crypto.createPrivateKey()][crypto.createPrivateKey()] и [keyObject.export()][keyObject.export()].
KeyObject¶
[KeyObject][KeyObject] — представление разобранного ключа в памяти. Создаётся через [crypto.createPublicKey()][crypto.createPublicKey()], [crypto.createPrivateKey()][crypto.createPrivateKey()], [crypto.createSecretKey()][crypto.createSecretKey()] или функции генерации, например [crypto.generateKeyPair()][crypto.generateKeyPair()]. Первая криптографическая операция с данным [KeyObject][KeyObject] может быть медленнее последующих: OpenSSL лениво инициализирует внутренние кэши при первом использовании.
PEM и DER¶
PEM и DER — традиционные кодировки асимметричных ключей на базе структур ASN.1.
- PEM — текстовая кодировка: DER в Base64 между строками заголовка и подвала (например
-----BEGIN PUBLIC KEY-----). Строки PEM можно передавать напрямую во многие операции. - DER — двоичная кодировка тех же структур ASN.1. Для входа DER нужно явно указать
type(обычно'spki'или'pkcs8').
JSON Web Key (JWK)¶
JSON Web Key (JWK) — представление ключа в JSON по RFC 7517. Компоненты кодируются в Base64url внутри объекта. Для RSA JWK снижает накладные расходы разбора ASN.1 и часто даёт самый быстрый импорт из сериализованных форматов.
«Сырые» форматы ключей¶
Стабильность: 1.1 — Активная разработка
Форматы 'raw-public', 'raw-private' и 'raw-seed' позволяют импортировать и экспортировать сырой материал ключа без обёртки. Подробности — [keyObject.export()][keyObject.export()], [crypto.createPublicKey()][crypto.createPublicKey()], [crypto.createPrivateKey()][crypto.createPrivateKey()].
'raw-public' обычно самый быстрый способ импорта открытого ключа. 'raw-private' и 'raw-seed' не всегда быстрее других форматов: в них только скаляр/seed закрытого ключа — для использования часто нужно вычислить открытую часть (умножение на кривой, развёртывание seed), что дорого. В других форматах уже есть обе части ключа.
Выбор формата ключа¶
По возможности используйте [KeyObject][KeyObject] — создайте из любого доступного формата и переиспользуйте. Ниже — про выбор формата сериализации при импорте в [KeyObject][KeyObject] или при передаче материала inline, когда [KeyObject][KeyObject] не подходит.
Импорт ключей¶
Если [KeyObject][KeyObject] создаётся для многократного использования, стоимость импорта платится один раз, и более быстрый формат снижает задержку старта.
Импорт состоит из разбора обёртки и вычислений по ключу (восстановление полного ключа: открытый ключ из закрытого скаляра, развёртывание seed и т. д.). Что доминирует, зависит от типа ключа. Например:
- Открытые ключи —
'raw-public'обычно быстрее всех сериализованных форматов: нет разбора ASN.1 и Base64. - Закрытые EC —
'raw-private'быстрее PEM/DER (меньше ASN.1). На больших кривых (P-384, P-521) вычисление открытой точки дорого, выигрыш меньше. - RSA —
'jwk'часто самый быстрый сериализованный формат: компоненты как целые в Base64url без ASN.1.
Материал ключа inline в операциях¶
Если [KeyObject][KeyObject] нельзя переиспользовать (ключ пришёл как сырые байты в сообщении и используется один раз), функции обычно принимают PEM или объект с форматом и материалом. Полная стоимость — импорт плюс сама криптооперация.
Если доминирует тяжёлая операция (подпись RSA, ECDH на P-384/P-521), формат сериализации почти не влияет на пропускную способность — выбирайте удобный. Для лёгких операций (Ed25519) импорт заметнее, и быстрые 'raw-public' / 'raw-private' дают выигрыш.
Даже при нескольких использованиях одного материала лучше импортировать в [KeyObject][KeyObject], чем снова передавать сырой или PEM.
Примеры¶
Переиспользование [KeyObject][KeyObject] для подписи и проверки:
1 2 3 4 5 6 7 8 9 10 | |
Пример: импорт ключей разных форматов в [KeyObject][KeyObject]:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | |
Пример: передача материала ключа напрямую в [crypto.sign()][crypto.sign()] и [crypto.verify()][crypto.verify()] без предварительного [KeyObject][KeyObject]:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
Пример: для ключей EC при импорте сырых ключей нужна опция namedCurve:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | |
Пример: экспорт и импорт сырых seed:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
Class: Certificate¶
SPKAC — механизм запроса на подпись сертификата, изначально в Netscape и формально вошедший в элемент HTML5 keygen.
<keygen> устарел с HTML 5.2; в новых проектах элемент не используют.
Модуль node:crypto предоставляет класс Certificate для работы с данными SPKAC. Чаще всего это вывод элемента <keygen>. Внутри Node.js использует реализацию SPKAC в OpenSSL.
Static method: Certificate.exportChallenge(spkac[, encoding])¶
Добавлено в: v9.0.0
История
| Версия | Изменения |
|---|---|
| v15.0.0 | Аргументом spkac может быть ArrayBuffer. Ограничен размер аргумента spkac максимум до 2**31–1 байта. |
spkac| | | | encodingкодировка строки spkac- Возвращает:
компонент challenge структуры spkac(открытый ключ и challenge)
1 2 3 4 5 | |
1 2 3 4 5 | |
Static method: Certificate.exportPublicKey(spkac[, encoding])¶
Добавлено в: v9.0.0
История
| Версия | Изменения |
|---|---|
| v15.0.0 | Аргументом spkac может быть ArrayBuffer. Ограничен размер аргумента spkac максимум до 2**31–1 байта. |
spkac| | | | encodingкодировка строки spkac- Возвращает:
компонент открытого ключа структуры spkac(открытый ключ и challenge)
1 2 3 4 5 | |
1 2 3 4 5 | |
Static method: Certificate.verifySpkac(spkac[, encoding])¶
Добавлено в: v9.0.0
История
| Версия | Изменения |
|---|---|
| v15.0.0 | Аргументом spkac может быть ArrayBuffer. Добавлена кодировка. Ограничен размер аргумента spkac максимум до 2**31–1 байта. |
spkac| | | | encodingкодировка строки spkac- Возвращает:
true, если структураspkacдопустима, иначеfalse
1 2 3 4 5 6 | |
1 2 3 4 5 6 | |
Legacy API¶
Stability: 0 - Deprecated
As a legacy interface, it is possible to create new instances of the crypto.Certificate class as illustrated in the examples below.
new crypto.Certificate()¶
Instances of the Certificate class can be created using the new keyword or by calling crypto.Certificate() as a function:
1 2 3 4 | |
1 2 3 4 | |
certificate.exportChallenge(spkac[, encoding])¶
spkac| | | | encodingThe encoding of the spkacstring.- Returns:
The challenge component of the spkacdata structure, which includes a public key and a challenge.
1 2 3 4 5 6 | |
1 2 3 4 5 6 | |
certificate.exportPublicKey(spkac[, encoding])¶
spkac| | | | encodingThe encoding of the spkacstring.- Returns:
The public key component of the spkacdata structure, which includes a public key and a challenge.
1 2 3 4 5 6 | |
1 2 3 4 5 6 | |
certificate.verifySpkac(spkac[, encoding])¶
spkac| | | | encodingThe encoding of the spkacstring.- Returns:
trueif the givenspkacdata structure is valid,falseotherwise.
1 2 3 4 5 6 7 | |
1 2 3 4 5 6 7 | |
Class: Cipheriv¶
Экземпляры Cipheriv используются для шифрования данных. Два варианта использования:
- как поток
Transform: в пишущую сторону подаётся открытый текст, со стороны чтения — шифротекст; - через [
cipher.update()][cipher.update()] и [cipher.final()][cipher.final()].
[crypto.createCipheriv()][crypto.createCipheriv()] создаёт экземпляры Cipheriv; конструктор new не используют.
Пример: Cipheriv как поток:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | |
Пример: Cipheriv и pipeline:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | |
Пример: методы [cipher.update()][cipher.update()] и [cipher.final()][cipher.final()]:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
cipher.final([outputEncoding])¶
outputEncodingThe encoding of the return value. - Returns:
| Any remaining enciphered contents. If outputEncodingis specified, a string is returned. If anoutputEncodingis not provided, a [Buffer][Buffer] is returned.
Once the cipher.final() method has been called, the Cipheriv object can no longer be used to encrypt data. Attempts to call cipher.final() more than once will result in an error being thrown.
cipher.getAuthTag()¶
- Возвращает:
В режимах с аутентификацией ( GCM,CCM,OCB,chacha20-poly1305) методcipher.getAuthTag()возвращает [Buffer][Buffer] с тегом аутентификации, вычисленным по данным.
cipher.getAuthTag() вызывают только после завершения шифрования через [cipher.final()][cipher.final()].
Если при создании cipher была задана опция authTagLength, вернётся ровно столько байт.