API reference

Web Crypto

16/18Coverage3/18Strict (zero caveats)

crypto.subtle is Node's own Web Crypto implementation (lib/internal/crypto/webcrypto.js) ported to TypeScript and written over the node:crypto module: the algorithm is normalized at run time, every failure rejects the returned promise with Node's error, and crypto.subtle is an ordinary value. node:crypto's natives come from the backend picked with -crypto (OpenSSL libcrypto by default; Apple CommonCrypto on macOS covers the symmetric algorithms only). getRandomValues and randomUUID need only a CSPRNG and no external library.

Exact Works, with caveats Not supported

crypto.getRandomValues(view)

Works, with caveats
getRandomValues<T extends TypedArray>(view: T): T

Fills an integer TypedArray's (or whole ArrayBuffer's) bytes in place from the in-house CSPRNG — arc4random_buf on macOS/BSD, getrandom() on Linux — and returns the same view. The spec's 65,536-byte quota is enforced (an oversize view throws QuotaExceededError), and a float TypedArray is a compile-time rejection matching the spec's TypeMismatchError. The legacy plain number[] form still works, writing one random byte value (0–255) per element.

Parameters
viewTypedArray | ArrayBuffer
The buffer to fill in place.
Returns

TypedArray — The same view, now filled.

const bytes = new Uint8Array(16)
crypto.getRandomValues(bytes)
See it in a full example →
⚠ Differences from standard
  • A whole ArrayBuffer is accepted as a deliberate extension (real JS throws TypeMismatchError — only integer TypedArrays are spec-legal).

crypto.randomUUID()

Exact
randomUUID(): string

Returns a standard RFC 4122 version-4 UUID string. The version nibble (4) and variant nibble (one of 8/9/a/b) are fixed by the spec's bit layout; the rest is CSPRNG-random.

Returns

string — A 36-character v4 UUID.

const id1: string = crypto.randomUUID()
const id2: string = crypto.randomUUID()
See it in a full example →

crypto.subtle.digest(algo, data)

supported
digest(algo: string | { name: string }, data: TypedArray | ArrayBuffer): Promise<ArrayBuffer>

Hashes any BufferSource with SHA-1, SHA-256, SHA-384 or SHA-512, returning a Promise<ArrayBuffer>; an unknown algorithm rejects with NotSupportedError.

Parameters
algostring | { name: string }
Hash name literal.
dataTypedArray | ArrayBuffer
Bytes to hash.
Returns

Promise<ArrayBuffer> — The digest bytes.

const sha256 = new Uint8Array(await crypto.subtle.digest("SHA-256", data))
See it in a full example →

crypto.subtle.encrypt / .decrypt

Works, with caveats
encrypt(algo, key: CryptoKey, data): Promise<ArrayBuffer>; decrypt(algo, key: CryptoKey, data): Promise<ArrayBuffer>

AES-CTR (counter, length), AES-CBC, AES-GCM (iv, additionalData, tagLength) and RSA-OAEP (label), each returning a Promise<ArrayBuffer>; a failed decryption rejects with OperationError.

Parameters
algo{ name: string, ... }
Algorithm literal with its parameters (iv, label, …).
keyCryptoKey
The key to use.
dataTypedArray | ArrayBuffer
Plaintext or ciphertext.
Returns

Promise<ArrayBuffer> — Ciphertext or plaintext bytes.

const ct = await crypto.subtle.encrypt({ name: "AES-GCM", iv: iv }, aesKey, secret)
const pt = await crypto.subtle.decrypt({ name: "AES-GCM", iv: iv }, aesKey, ct)
See it in a full example →
⚠ Differences from standard
  • On -crypto=commoncrypto the asymmetric algorithms (RSA, EC, Ed25519, X25519) fail: they run over node:crypto's KeyObject, which that backend does not provide.

crypto.subtle.sign / .verify

Works, with caveats
sign(algo, key: CryptoKey, data): Promise<ArrayBuffer>; verify(algo, key: CryptoKey, sig, data): Promise<boolean>

HMAC, RSASSA-PKCS1-v1_5, RSA-PSS (saltLength), ECDSA over P-256/P-384/P-521 (IEEE P1363 r‖s signatures) and Ed25519. sign returns Promise<ArrayBuffer>, verify returns Promise<boolean>.

Parameters
algostring | { name: string, ... }
Algorithm literal (hash/saltLength as needed).
keyCryptoKey
Signing or verifying key.
dataTypedArray | ArrayBuffer
Message bytes (verify also takes the signature).
Returns

Promise<ArrayBuffer> | Promise<boolean> — Signature bytes, or a verification result.

const sig = new Uint8Array(await crypto.subtle.sign("HMAC", hmacKey, msg))
console.log(await crypto.subtle.verify("HMAC", hmacKey, sig, msg)) // true
See it in a full example →
⚠ Differences from standard
  • On -crypto=commoncrypto the asymmetric algorithms (RSA, EC, Ed25519, X25519) fail: they run over node:crypto's KeyObject, which that backend does not provide.

crypto.subtle.generateKey

Works, with caveats
generateKey(algo, extractable: boolean, usages: string[]): Promise<CryptoKey | CryptoKeyPair>

AES-CTR/CBC/GCM/KW, HMAC, RSASSA-PKCS1-v1_5/RSA-PSS/RSA-OAEP with any publicExponent, ECDSA/ECDH, Ed25519 and X25519, returning a Promise<CryptoKey> or Promise<CryptoKeyPair>; usages are checked and split across a pair as Node splits them.

Parameters
algo{ name: string, ... }
Algorithm literal with its key parameters.
extractableboolean
Whether the key may be exported.
usagesstring[]
Permitted operations.
Returns

Promise<CryptoKey | CryptoKeyPair> — The generated key or key pair.

const aesKey = await crypto.subtle.generateKey(
    { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"])
See it in a full example →
⚠ Differences from standard
  • On -crypto=commoncrypto the asymmetric algorithms (RSA, EC, Ed25519, X25519) fail: they run over node:crypto's KeyObject, which that backend does not provide.

crypto.subtle.importKey / .exportKey

Works, with caveats
importKey(format, keyData, algo, extractable, usages): Promise<CryptoKey>; exportKey(format, key): Promise<ArrayBuffer | Map<string,string>>

raw (secret keys; EC points, compressed or not; Ed25519/X25519), pkcs8, spki and jwk for every algorithm, with Node's JWK checks and member order. CryptoKey's type, extractable, algorithm and usages are all readable.

Parameters
format"raw" | "pkcs8" | "spki" | "jwk"
Key encoding.
keyDataTypedArray | Map<string,string> | object
The key material (import only).
usagesstring[]
Permitted operations (import only).
Returns

Promise<CryptoKey | ArrayBuffer | Map<string,string>> — A CryptoKey, or exported bytes / a JWK object.

const hmacKey = await crypto.subtle.importKey("raw", rawKey,
    { name: "HMAC", hash: "SHA-256" }, true, ["sign", "verify"])
const jwk = await crypto.subtle.exportKey("jwk", hmacKey)
See it in a full example →
⚠ Differences from standard
  • On -crypto=commoncrypto the asymmetric algorithms (RSA, EC, Ed25519, X25519) fail: they run over node:crypto's KeyObject, which that backend does not provide.

crypto.subtle.deriveKey / .deriveBits

Works, with caveats
deriveKey(algo, baseKey, derivedAlgo, extractable, usages): Promise<CryptoKey>; deriveBits(algo, baseKey, length): Promise<ArrayBuffer>

PBKDF2 and HKDF (non-extractable base keys, as Node requires), ECDH and X25519. deriveBits returns a Promise<ArrayBuffer>; deriveKey makes any key the target algorithm can make.

Parameters
algo{ name: string, ... }
Derivation algorithm literal (salt, iterations, hash, …).
baseKeyCryptoKey
The imported base key material.
Returns

Promise<CryptoKey | ArrayBuffer> — The derived key or raw bits.

const aes = await crypto.subtle.deriveKey(
    { name: "PBKDF2", salt: salt, iterations: 100000, hash: "SHA-256" },
    base, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"])
See it in a full example →
⚠ Differences from standard
  • On -crypto=commoncrypto the asymmetric algorithms (RSA, EC, Ed25519, X25519) fail: they run over node:crypto's KeyObject, which that backend does not provide.

crypto.subtle.wrapKey / unwrapKey

Works, with caveats
wrapKey(format, key, wrappingKey, wrapAlgorithm): Promise<ArrayBuffer>; unwrapKey(format, wrapped, unwrappingKey, unwrapAlgorithm, keyAlgorithm, extractable, usages): Promise<CryptoKey>

Exports a key in any format and encrypts it with AES-KW, AES-GCM/CBC/CTR or RSA-OAEP, and the reverse.

Returns

Promise<ArrayBuffer> | Promise<CryptoKey> — The wrapped key, or the unwrapped CryptoKey.

const wrapped = await crypto.subtle.wrapKey('raw', aesKey, kek, 'AES-KW')
const back = await crypto.subtle.unwrapKey('raw', wrapped, kek, 'AES-KW', 'AES-GCM', true, ['encrypt'])
⚠ Differences from standard
  • On -crypto=commoncrypto the asymmetric algorithms (RSA, EC, Ed25519, X25519) fail: they run over node:crypto's KeyObject, which that backend does not provide.

crypto.createHash / createHmac / hash / getHashes

Works, with caveats
createHash(algorithm, options?): Hash; createHmac(algorithm, key): Hmac; hash(algorithm, data, outputEncoding?): string

Node's Hash and Hmac objects: .update(data) (chainable, string or bytes), .digest(encoding?) and Hash's .copy(). Every digest the crypto backend has is available, including shake128/shake256 with an outputLength. Validation and errors are Node's: a second digest throws ERR_CRYPTO_HASH_FINALIZED, and an unknown algorithm throws 'Digest method not supported'.

Returns

Hash | Hmac | string — A digest handle, or the one-shot digest.

import crypto from 'crypto'
const accept = crypto.createHash('sha1')
  .update(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')
  .digest('base64')
const sig = crypto.createHmac('sha256', secret).update(msg).digest('hex')
⚠ Differences from standard
  • On -crypto=commoncrypto only md5, sha1, sha224, sha256, sha384 and sha512 exist; SHAKE, SHA-3, SHA-512/t, RIPEMD-160 and BLAKE2 throw 'Digest method not supported'.

crypto.createCipheriv / createDecipheriv / getCiphers

Works, with caveats
createCipheriv(algorithm, key, iv, options?): Cipheriv; createDecipheriv(algorithm, key, iv, options?): Decipheriv

Symmetric encryption with any cipher the backend has. update/final, setAutoPadding, and setAAD, getAuthTag and setAuthTag for AEAD modes such as GCM. A wrong key or IV length, a bad final block, and a failed authentication throw the errors Node throws.

Returns

Cipheriv | Decipheriv — A cipher handle.

const e = crypto.createCipheriv('aes-256-gcm', key, iv)
const ct = Buffer.concat([e.update('hello'), e.final()])
const tag = e.getAuthTag()
⚠ Differences from standard
  • On -crypto=commoncrypto only AES-128/192/256 in CBC, ECB, CTR and GCM exist; other ciphers throw ERR_CRYPTO_UNKNOWN_CIPHER.

crypto.pbkdf2 / scrypt / hkdf (+ Sync)

Works, with caveats
pbkdf2(password, salt, iterations, keylen, digest, callback); scrypt(password, salt, keylen, options?, callback); hkdf(digest, ikm, salt, info, keylen, callback)

Key derivation. The Sync forms return a Buffer (hkdfSync an ArrayBuffer); the callback forms run on the thread pool and call back with (err, key), as Node's do.

Returns

Buffer | ArrayBuffer | void — The derived key, or nothing for the callback form.

const key = crypto.scryptSync('password', 'salt', 32)
⚠ Differences from standard
  • On -crypto=commoncrypto the digests are the six createHash has there.

crypto.randomBytes / randomFill / randomInt / timingSafeEqual / constants

Exact
randomBytes(size, callback?); randomFill(buf, offset?, size?, callback); randomInt(min?, max, callback?); timingSafeEqual(a, b)

CSPRNG bytes and integers. randomBytes and randomFill fill on the thread pool when given a callback; randomInt is Node's rejection-sampling draw. timingSafeEqual compares in constant time and throws Node's RangeError on a length mismatch. constants is Node's table.

Returns

Buffer | number | boolean — Random bytes, a random integer, or the comparison.

const token = crypto.randomBytes(32).toString('hex')
const die = crypto.randomInt(1, 7)

crypto.generateKeyPair / createSign / createVerify / sign / verify

Works, with caveats
generateKeyPair(type, options, callback); generateKeyPairSync(type, options): { publicKey, privateKey }; sign(algorithm, data, key); verify(algorithm, data, key, signature)

Key pairs of every type but dh — rsa, rsa-pss, dsa, ec, ed25519, ed448, x25519, x448 — as KeyObjects, or in any encoding (pem/der/jwk with pkcs1/spki/pkcs8/sec1 and an optional cipher). Signatures over a KeyObject, PEM or { key, passphrase, padding, saltLength, dsaEncoding }: Sign/Verify streams and the one-shot sign/verify (null algorithm for Ed25519). The callback form of generateKeyPair runs on the thread pool.

Returns

{ publicKey, privateKey } | Buffer | boolean — A key pair (KeyObjects or encoded keys), a signature, or the verification.

const { publicKey, privateKey } = crypto.generateKeyPairSync('ed25519')
const sig = crypto.sign(null, Buffer.from('msg'), privateKey)
crypto.verify(null, Buffer.from('msg'), publicKey, sig)  // true
⚠ Differences from standard
  • dh key pairs are not generated.
  • On -crypto=commoncrypto: RSA keys of 1024 bits or more with exponent 65537, EC keys on P-256/P-384/P-521, ed25519 and x25519 only; encodings other than SPKI/PKCS#8 PEM and the padding/saltLength/dsaEncoding sign options fail.

KeyObject / createPrivateKey / createPublicKey / createSecretKey

Works, with caveats
createPrivateKey(key); createPublicKey(key); createSecretKey(key[, encoding]); keyObject.export(options); keyObject.equals(other)

Keys from PEM, DER (pkcs1/spki/pkcs8/sec1, encrypted PKCS#8 with a passphrase) or JWK (RSA, EC, OKP), and export back to each. type, asymmetricKeyType, asymmetricKeyDetails, symmetricKeySize and equals answer as in Node, with Node's error codes, OpenSSL's ERR_OSSL_* ones included.

Returns

KeyObject — A SecretKeyObject, PublicKeyObject or PrivateKeyObject.

const key = crypto.createPrivateKey(pem)
const jwk = key.export({ format: 'jwk' })
crypto.createPublicKey(key).asymmetricKeyType  // 'ec'
⚠ Differences from standard
  • A secp256k1 JWK cannot be imported (P-256/P-384/P-521 can; export covers all four).
  • On -crypto=commoncrypto, creating or exporting an asymmetric key fails.

createECDH / diffieHellman / publicEncrypt / privateDecrypt / getCurves

Works, with caveats
createECDH(curve): ECDH; ECDH.convertKey(key, curve[, inEnc, outEnc, format]); diffieHellman({ privateKey, publicKey }): Buffer; publicEncrypt(key, buffer): Buffer; privateDecrypt(key, buffer): Buffer

ECDH key agreement on every built-in curve, with compressed, uncompressed or hybrid points; diffieHellman over EC, X25519 and X448 KeyObjects; RSA encryption with OAEP (oaepHash, oaepLabel), PKCS#1 or no padding, and the private-encrypt/public-decrypt pair. getCurves lists the curves.

Returns

ECDH | Buffer | string[] — The ECDH object, a shared secret or ciphertext, or the curve names.

const alice = crypto.createECDH('prime256v1'), bob = crypto.createECDH('prime256v1')
const a = alice.generateKeys(), b = bob.generateKeys()
alice.computeSecret(b).equals(bob.computeSecret(a))  // true
⚠ Differences from standard
  • On -crypto=commoncrypto each of these fails.