Node.js provides an implementation of the standard Web Crypto API.
Use require('crypto').webcrypto
to access this module.
const { subtle } = require('crypto').webcrypto;
(async function() {
const key = await subtle.generateKey({
name: 'HMAC',
hash: 'SHA-256',
length: 256
}, true, ['sign', 'verify']);
const enc = new TextEncoder();
const message = enc.encode('I love cupcakes');
const digest = await subtle.sign({
name: 'HMAC'
}, key, message);
})();
The <SubtleCrypto> class can be used to generate symmetric (secret) keys or asymmetric key pairs (public key and private key).
const { subtle } = require('crypto').webcrypto;
async function generateAesKey(length = 256) {
const key = await subtle.generateKey({
name: 'AES-CBC',
length
}, true, ['encrypt', 'decrypt']);
return key;
}
const { subtle } = require('crypto').webcrypto;
async function generateEcKey(namedCurve = 'P-521') {
const {
publicKey,
privateKey
} = await subtle.generateKey({
name: 'ECDSA',
namedCurve,
}, true, ['sign', 'verify']);
return { publicKey, privateKey };
}
const { subtle } = require('crypto').webcrypto;
async function generateEd25519Key() {
return subtle.generateKey({
name: 'NODE-ED25519',
namedCurve: 'NODE-ED25519',
}, true, ['sign', 'verify']);
}
async function generateX25519Key() {
return subtle.generateKey({
name: 'ECDH',
namedCurve: 'NODE-X25519',
}, true, ['deriveKey']);
}
const { subtle } = require('crypto').webcrypto;
async function generateHmacKey(hash = 'SHA-256') {
const key = await subtle.generateKey({
name: 'HMAC',
hash
}, true, ['sign', 'verify']);
return key;
}
const { subtle } = require('crypto').webcrypto;
const publicExponent = new Uint8Array([1, 0, 1]);
async function generateRsaKey(modulusLength = 2048, hash = 'SHA-256') {
const {
publicKey,
privateKey
} = await subtle.generateKey({
name: 'RSASSA-PKCS1-v1_5',
modulusLength,
publicExponent,
hash,
}, true, ['sign', 'verify']);
return { publicKey, privateKey };
}
const { subtle, getRandomValues } = require('crypto').webcrypto;
async function aesEncrypt(plaintext) {
const ec = new TextEncoder();
const key = await generateAesKey();
const iv = getRandomValues(new Uint8Array(16));
const ciphertext = await subtle.encrypt({
name: 'AES-CBC',
iv,
}, key, ec.encode(plaintext));
return {
key,
iv,
ciphertext
};
}
async function aesDecrypt(ciphertext, key, iv) {
const dec = new TextDecoder();
const plaintext = await subtle.decrypt({
name: 'AES-CBC',
iv,
}, key, ciphertext);
return dec.decode(plaintext);
}
const { subtle } = require('crypto').webcrypto;
async function generateAndExportHmacKey(format = 'jwk', hash = 'SHA-512') {
const key = await subtle.generateKey({
name: 'HMAC',
hash
}, true, ['sign', 'verify']);
return subtle.exportKey(format, key);
}
async function importHmacKey(keyData, format = 'jwk', hash = 'SHA-512') {
const key = await subtle.importKey(format, keyData, {
name: 'HMAC',
hash
}, true, ['sign', 'verify']);
return key;
}
const { subtle } = require('crypto').webcrypto;
async function generateAndWrapHmacKey(format = 'jwk', hash = 'SHA-512') {
const [
key,
wrappingKey,
] = await Promise.all([
subtle.generateKey({
name: 'HMAC', hash
}, true, ['sign', 'verify']),
subtle.generateKey({
name: 'AES-KW',
length: 256
}, true, ['wrapKey', 'unwrapKey']),
]);
const wrappedKey = await subtle.wrapKey(format, key, wrappingKey, 'AES-KW');
return wrappedKey;
}
async function unwrapHmacKey(
wrappedKey,
wrappingKey,
format = 'jwk',
hash = 'SHA-512') {
const key = await subtle.unwrapKey(
format,
wrappedKey,
unwrappingKey,
'AES-KW',
{ name: 'HMAC', hash },
true,
['sign', 'verify']);
return key;
}
const { subtle } = require('crypto').webcrypto;
async function sign(key, data) {
const ec = new TextEncoder();
const signature =
await subtle.sign('RSASSA-PKCS1-v1_5', key, ec.encode(data));
return signature;
}
async function verify(key, signature, data) {
const ec = new TextEncoder();
const verified =
await subtle.verify(
'RSASSA-PKCS1-v1_5',
key,
signature,
ec.encode(data));
return verified;
}
const { subtle } = require('crypto').webcrypto;
async function pbkdf2(pass, salt, iterations = 1000, length = 256) {
const ec = new TextEncoder();
const key = await subtle.importKey(
'raw',
ec.encode(pass),
'PBKDF2',
false,
['deriveBits']);
const bits = await subtle.deriveBits({
name: 'PBKDF2',
hash: 'SHA-512',
salt: ec.encode(salt),
iterations
}, key, length);
return bits;
}
async function pbkdf2Key(pass, salt, iterations = 1000, length = 256) {
const ec = new TextEncoder();
const keyMaterial = await subtle.importKey(
'raw',
ec.encode(pass),
'PBKDF2',
false,
['deriveKey']);
const key = await subtle.deriveKey({
name: 'PBKDF2',
hash: 'SHA-512',
salt: ec.encode(salt),
iterations
}, keyMaterial, {
name: 'AES-GCM',
length: 256
}, true, ['encrypt', 'decrypt']);
return key;
}
const { subtle } = require('crypto').webcrypto;
async function digest(data, algorithm = 'SHA-512') {
const ec = new TextEncoder();
const digest = await subtle.digest(algorithm, ec.encode(data));
return digest;
}
The table details the algorithms supported by the Node.js Web Crypto API implementation and the APIs supported for each:
Algorithm | generateKey | exportKey | importKey | encrypt | decrypt | wrapKey | unwrapKey | deriveBits | deriveKey | sign | verify | digest |
---|---|---|---|---|---|---|---|---|---|---|---|---|
'RSASSA-PKCS1-v1_5' | ✔ | ✔ | ✔ | ✔ | ✔ | |||||||
'RSA-PSS' | ✔ | ✔ | ✔ | ✔ | ✔ | |||||||
'RSA-OAEP' | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | |||||
'ECDSA' | ✔ | ✔ | ✔ | ✔ | ✔ | |||||||
'ECDH' | ✔ | ✔ | ✔ | ✔ | ✔ | |||||||
'AES-CTR' | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | |||||
'AES-CBC' | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | |||||
'AES-GCM' | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | |||||
'AES-KW' | ✔ | ✔ | ✔ | ✔ | ✔ | |||||||
'HMAC' | ✔ | ✔ | ✔ | ✔ | ✔ | |||||||
'HKDF' | ✔ | ✔ | ✔ | ✔ | ||||||||
'PBKDF2' | ✔ | ✔ | ✔ | ✔ | ||||||||
'SHA-1' | ✔ | |||||||||||
'SHA-256' | ✔ | |||||||||||
'SHA-384' | ✔ | |||||||||||
'SHA-512' | ✔ | |||||||||||
'NODE-DSA' 1 | ✔ | ✔ | ✔ | ✔ | ✔ | |||||||
'NODE-DH' 1 | ✔ | ✔ | ✔ | ✔ | ✔ | |||||||
'NODE-ED25519' 1 | ✔ | ✔ | ✔ | ✔ | ✔ | |||||||
'NODE-ED448' 1 | ✔ | ✔ | ✔ | ✔ | ✔ |
Crypto
类#Calling require('crypto').webcrypto
returns an instance of the Crypto
class.
Crypto
is a singleton that provides access to the remainder of the crypto API.
crypto.subtle
#Provides access to the SubtleCrypto
API.
crypto.getRandomValues(typedArray)
#typedArray
<Buffer> | <TypedArray>Generates cryptographically strong random values. The given typedArray
is
filled with random values, and a reference to typedArray
is returned.
The given typedArray
must be an integer-based instance of <TypedArray>,
i.e. Float32Array
and Float64Array
are not accepted.
An error will be thrown if the given typedArray
is larger than 65,536 bytes.
crypto.randomUUID()
#Generates a random RFC 4122 version 4 UUID. The UUID is generated using a cryptographic pseudorandom number generator.
CryptoKey
类#cryptoKey.algorithm
#An object detailing the algorithm for which the key can be used along with additional algorithm-specific parameters.
Read-only.
cryptoKey.extractable
#When true
, the <CryptoKey> can be extracted using either
subtleCrypto.exportKey()
or subtleCrypto.wrapKey()
.
Read-only.
cryptoKey.type
#'secret'
, 'private'
, or 'public'
.A string identifying whether the key is a symmetric ('secret'
) or
asymmetric ('private'
or 'public'
) key.
cryptoKey.usages
#An array of strings identifying the operations for which the key may be used.
The possible usages are:
'encrypt'
- The key may be used to encrypt data.'decrypt'
- The key may be used to decrypt data.'sign'
- The key may be used to generate digital signatures.'verify'
- The key may be used to verify digital signatures.'deriveKey'
- The key may be used to derive a new key.'deriveBits'
- The key may be used to derive bits.'wrapKey'
- The key may be used to wrap another key.'unwrapKey'
- The key may be used to unwrap another key.Valid key usages depend on the key algorithm (identified by
cryptokey.algorithm.name
).
Key Type | 'encrypt' | 'decrypt' | 'sign' | 'verify' | 'deriveKey' | 'deriveBits' | 'wrapKey' | 'unwrapKey' |
---|---|---|---|---|---|---|---|---|
'AES-CBC' | ✔ | ✔ | ✔ | ✔ | ||||
'AES-CTR' | ✔ | ✔ | ✔ | ✔ | ||||
'AES-GCM' | ✔ | ✔ | ✔ | ✔ | ||||
'AES-KW' | ✔ | ✔ | ||||||
'ECDH' | ✔ | ✔ | ||||||
'ECDSA' | ✔ | ✔ | ||||||
'HDKF' | ✔ | ✔ | ||||||
'HMAC' | ✔ | ✔ | ||||||
'PBKDF2' | ✔ | ✔ | ||||||
'RSA-OAEP' | ✔ | ✔ | ✔ | ✔ | ||||
'RSA-PSS' | ✔ | ✔ | ||||||
'RSASSA-PKCS1-v1_5' | ✔ | ✔ | ||||||
'NODE-DSA' 1 | ✔ | ✔ | ||||||
'NODE-DH' 1 | ✔ | ✔ | ||||||
'NODE-SCRYPT' 1 | ✔ | ✔ | ||||||
'NODE-ED25519' 1 | ✔ | ✔ | ||||||
'NODE-ED448' 1 | ✔ | ✔ |
CryptoKeyPair
类#The CryptoKeyPair
is a simple dictionary object with publicKey
and
privateKey
properties, representing an asymmetric key pair.
cryptoKeyPair.privateKey
#type
will be 'private'
.cryptoKeyPair.publicKey
#type
will be 'public'
.SubtleCrypto
类#subtle.decrypt(algorithm, key, data)
#algorithm
: <RsaOaepParams> | <AesCtrParams> | <AesCbcParams> | <AesGcmParams>key
: <CryptoKey>data
: <ArrayBuffer> | <TypedArray> | <DataView> | <Buffer>Using the method and parameters specified in algorithm
and the keying
material provided by key
, subtle.decrypt()
attempts to decipher the
provided data
. If successful, the returned promise will be resolved with
an <ArrayBuffer> containing the plaintext result.
The algorithms currently supported include:
'RSA-OAEP'
'AES-CTR'
'AES-CBC'
'AES-GCM
'subtle.deriveBits(algorithm, baseKey, length)
#algorithm
: <EcdhKeyDeriveParams> | <HkdfParams> | <Pbkdf2Params> | <NodeDhDeriveBitsParams> | <NodeScryptParams>baseKey
: <CryptoKey>length
: <number>Using the method and parameters specified in algorithm
and the keying
material provided by baseKey
, subtle.deriveBits()
attempts to generate
length
bits. The Node.js implementation requires that length
is a
multiple of 8
. If successful, the returned promise will be resolved with
an <ArrayBuffer> containing the generated data.
The algorithms currently supported include:
subtle.deriveKey(algorithm, baseKey, derivedKeyAlgorithm, extractable, keyUsages)
#algorithm
: <EcdhKeyDeriveParams> | <HkdfParams> | <Pbkdf2Params> | <NodeDhDeriveBitsParams> | <NodeScryptParams>baseKey
: <CryptoKey>derivedKeyAlgorithm
: <HmacKeyGenParams> | <AesKeyGenParams>extractable
: <boolean>keyUsages
: <string[]> See Key usages.Using the method and parameters specified in algorithm
, and the keying
material provided by baseKey
, subtle.deriveKey()
attempts to generate
a new <CryptoKey> based on the method and parameters in derivedKeyAlgorithm
.
Calling subtle.deriveKey()
is equivalent to calling subtle.deriveBits()
to
generate raw keying material, then passing the result into the
subtle.importKey()
method using the deriveKeyAlgorithm
, extractable
, and
keyUsages
parameters as input.
The algorithms currently supported include:
subtle.digest(algorithm, data)
#algorithm
: <string> | <Object>data
: <ArrayBuffer> | <TypedArray> | <DataView> | <Buffer>Using the method identified by algorithm
, subtle.digest()
attempts to
generate a digest of data
. If successful, the returned promise is resolved
with an <ArrayBuffer> containing the computed digest.
If algorithm
is provided as a <string>, it must be one of:
'SHA-1'
'SHA-256'
'SHA-384'
'SHA-512'
If algorithm
is provided as an <Object>, it must have a name
property
whose value is one of the above.
subtle.encrypt(algorithm, key, data)
#algorithm
: <RsaOaepParams> | <AesCtrParams> | <AesCbcParams> | <AesGcmParams>key
: <CryptoKey>Using the method and parameters specified by algorithm
and the keying
material provided by key
, subtle.encrypt()
attempts to encipher data
.
If successful, the returned promise is resolved with an <ArrayBuffer>
containing the encrypted result.
The algorithms currently supported include:
'RSA-OAEP'
'AES-CTR'
'AES-CBC'
'AES-GCM
'subtle.exportKey(format, key)
#format
: <string> Must be one of 'raw'
, 'pkcs8'
, 'spki'
, 'jwk'
, or
'node.keyObject'
.key
: <CryptoKey>format
is
'node.keyObject'
, a <KeyObject>.Exports the given key into the specified format, if supported.
If the <CryptoKey> is not extractable, the returned promise will reject.
When format
is either 'pkcs8'
or 'spki'
and the export is successful,
the returned promise will be resolved with an <ArrayBuffer> containing the
exported key data.
When format
is 'jwk'
and the export is successful, the returned promise
will be resolved with a JavaScript object conforming to the JSON Web Key
specification.
The special 'node.keyObject'
value for format
is a Node.js-specific
extension that allows converting a <CryptoKey> into a Node.js <KeyObject>.
Key Type | 'spki' | 'pkcs8' | 'jwk' | 'raw' |
---|---|---|---|---|
'AES-CBC' | ✔ | ✔ | ||
'AES-CTR' | ✔ | ✔ | ||
'AES-GCM' | ✔ | ✔ | ||
'AES-KW' | ✔ | ✔ | ||
'ECDH' | ✔ | ✔ | ✔ | ✔ |
'ECDSA' | ✔ | ✔ | ✔ | ✔ |
'HDKF' | ||||
'HMAC' | ✔ | ✔ | ||
'PBKDF2' | ||||
'RSA-OAEP' | ✔ | ✔ | ✔ | |
'RSA-PSS' | ✔ | ✔ | ✔ | |
'RSASSA-PKCS1-v1_5' | ✔ | ✔ | ✔ | |
'NODE-DSA' 1 | ✔ | ✔ | ||
'NODE-DH' 1 | ✔ | ✔ | ||
'NODE-SCRYPT' 1 | ||||
'NODE-ED25519' 1 | ✔ | ✔ | ✔ | ✔ |
'NODE-ED448' 1 | ✔ | ✔ | ✔ | ✔ |
subtle.generateKey(algorithm, extractable, keyUsages)
#algorithm
: <RsaHashedKeyGenParams> | <EcKeyGenParams> | <HmacKeyGenParams> | <AesKeyGenParams> | <NodeDsaKeyGenParams> | <NodeDhKeyGenParams> | <NodeEdKeyGenParams>extractable
: <boolean>keyUsages
: <string[]> See Key usages.Using the method and parameters provided in algorithm
, subtle.generateKey()
attempts to generate new keying material. Depending the method used, the method
may generate either a single <CryptoKey> or a <CryptoKeyPair>.
The <CryptoKeyPair> (public and private key) generating algorithms supported include:
'RSASSA-PKCS1-v1_5'
'RSA-PSS'
'RSA-OAEP'
'ECDSA'
'ECDH'
'NODE-DSA'
1'NODE-DH'
1'NODE-ED25519'
1'NODE-ED448'
1The <CryptoKey> (secret key) generating algorithms supported include:
'HMAC'
'AES-CTR'
'AES-CBC'
'AES-GCM'
'AES-KW'
subtle.importKey(format, keyData, algorithm, extractable, keyUsages)
#format
: <string> Must be one of 'raw'
, 'pkcs8'
, 'spki'
, 'jwk'
, or
'node.keyObject'
.keyData
: <ArrayBuffer> | <TypedArray> | <DataView> | <Buffer> | <KeyObject>algorithm
: <RsaHashedImportParams> | <EcKeyImportParams> | <HmacImportParams> | <AesImportParams> | <Pbkdf2ImportParams> | <NodeDsaImportParams> | <NodeDhImportParams> | <NodeScryptImportParams> | <NodeEdKeyImportParams>extractable
: <boolean>keyUsages
: <string[]> See Key usages.The subtle.importKey()
method attempts to interpret the provided keyData
as the given format
to create a <CryptoKey> instance using the provided
algorithm
, extractable
, and keyUsages
arguments. If the import is
successful, the returned promise will be resolved with the created <CryptoKey>.
The special 'node.keyObject'
value for format
is a Node.js-specific
extension that allows converting a Node.js <KeyObject> into a