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