Node.js v26.9.0 documentation
- Node.js v26.9.0
- Table of contents
- Crypto
- Determining if crypto support is unavailable
- Asymmetric key types
- Class:
Certificate - Class:
Cipheriv - Class:
Decipheriv - Class:
DiffieHellmandiffieHellman.computeSecret(otherPublicKey[, inputEncoding][, outputEncoding])diffieHellman.generateKeys([encoding])diffieHellman.getGenerator([encoding])diffieHellman.getPrime([encoding])diffieHellman.getPrivateKey([encoding])diffieHellman.getPublicKey([encoding])diffieHellman.setPrivateKey(privateKey[, encoding])diffieHellman.setPublicKey(publicKey[, encoding])diffieHellman.verifyError
- Class:
DiffieHellmanGroup - Class:
ECDH- Static method:
ECDH.convertKey(key, curve[, inputEncoding[, outputEncoding[, format]]]) ecdh.computeSecret(otherPublicKey[, inputEncoding][, outputEncoding])ecdh.generateKeys([encoding[, format]])ecdh.getPrivateKey([encoding])ecdh.getPublicKey([encoding][, format])ecdh.setPrivateKey(privateKey[, encoding])ecdh.setPublicKey(publicKey[, encoding])
- Static method:
- Class:
Hash - Class:
Hmac - Class:
KeyObject - Class:
Mac - Class:
Sign - Class:
Verify - Class:
X509Certificatenew X509Certificate(buffer)x509.cax509.checkEmail(email[, options])x509.checkHost(name[, options])x509.checkIP(ip)x509.checkIssued(otherCert)x509.checkPrivateKey(privateKey)x509.fingerprintx509.fingerprint256x509.fingerprint512x509.infoAccessx509.issuerx509.issuerCertificatex509.keyUsagex509.publicKeyx509.rawx509.serialNumberx509.subjectx509.subjectAltNamex509.toJSON()x509.toLegacyObject()x509.toString()x509.validFromx509.validFromDatex509.validTox509.validToDatex509.signatureAlgorithmx509.signatureAlgorithmOidx509.verify(publicKey)
node:cryptomodule methods and propertiescrypto.argon2(algorithm, parameters, callback)crypto.argon2Sync(algorithm, parameters)crypto.checkPrime(candidate[, options], callback)crypto.checkPrimeSync(candidate[, options])crypto.constantscrypto.createCipheriv(algorithm, key, iv[, options])crypto.createDecipheriv(algorithm, key, iv[, options])crypto.createDiffieHellman(prime[, primeEncoding][, generator][, generatorEncoding])crypto.createDiffieHellman(primeLength[, generator])crypto.createDiffieHellmanGroup(name)crypto.createECDH(curveName)crypto.createHash(algorithm[, options])crypto.createHmac(algorithm, key[, options])crypto.createMac(algorithm, key[, options])crypto.createPrivateKey(key)crypto.createPublicKey(key)crypto.createSecretKey(key[, encoding])crypto.createSign(algorithm[, options])crypto.createVerify(algorithm[, options])crypto.decapsulate(key, ciphertext[, callback])crypto.diffieHellman(options[, callback])crypto.encapsulate(key[, callback])crypto.fipscrypto.generateKey(type, options, callback)crypto.generateKeyPair(type, options, callback)crypto.generateKeyPairSync(type, options)crypto.generateKeySync(type, options)crypto.generatePrime(size[, options], callback)crypto.generatePrimeSync(size[, options])crypto.getCipherInfo(nameOrNid[, options])crypto.getCiphers()crypto.getCurves()crypto.getDiffieHellman(groupName)crypto.getFips()crypto.getHashes()crypto.getMacs()crypto.getRandomValues(typedArray)crypto.hash(algorithm, data[, options])crypto.hkdf(digest, ikm, salt, info, keylen, callback)crypto.hkdfSync(digest, ikm, salt, info, keylen)crypto.pbkdf2(password, salt, iterations, keylen, digest, callback)crypto.pbkdf2Sync(password, salt, iterations, keylen, digest)crypto.privateDecrypt(privateKey, buffer)crypto.privateEncrypt(privateKey, buffer)crypto.publicDecrypt(key, buffer)crypto.publicEncrypt(key, buffer)crypto.randomBytes(size[, callback])crypto.randomFill(buffer[, offset][, size], callback)crypto.randomFillSync(buffer[, offset][, size])crypto.randomInt([min, ]max[, callback])crypto.randomUUID([options])crypto.randomUUIDv7([options])crypto.scrypt(password, salt, keylen[, options], callback)crypto.scryptSync(password, salt, keylen[, options])crypto.secureHeapUsed()crypto.setEngine(engine[, flags])crypto.setFips(bool)crypto.sign(algorithm, data, key[, callback])crypto.subtlecrypto.timingSafeEqual(a, b)crypto.verify(algorithm, data, key, signature[, callback])crypto.webcrypto
- Notes
- Crypto constants
- Crypto
- Index
- About this documentation
- Usage and example
- Assertion testing
- Asynchronous context tracking
- Async hooks
- Benchmark runner
- Buffer
- C++ addons
- C/C++ addons with Node-API
- C++ embedder API
- Child processes
- Cluster
- Command-line options
- Console
- Crypto
- Debugger
- Deprecated APIs
- Diagnostics Channel
- DNS
- Domain
- Environment Variables
- Errors
- Events
- File system
- FFI
- Globals
- HTTP
- HTTP/2
- HTTPS
- Inspector
- Internationalization
- Iterable Streams API
- Modules: CommonJS modules
- Modules: ECMAScript modules
- Modules:
node:moduleAPI - Modules: Packages
- Modules: TypeScript
- Net
- OS
- Path
- Performance hooks
- Permissions
- Process
- Punycode
- Query strings
- Readline
- REPL
- Report
- Single executable applications
- SQLite
- Stream
- String decoder
- Test runner
- Timers
- TLS/SSL
- Trace events
- TTY
- UDP/datagram
- URL
- Utilities
- V8
- Virtual File System
- VM
- WASI
- Web Crypto API
- Web Streams API
- Worker threads
- Zlib
- Other versions
- Options
Crypto#
Stability: 2 - Stable
The node:crypto module provides cryptographic functionality that includes a
set of wrappers for OpenSSL's hash, message authentication code (MAC), cipher,
decipher, sign, verify, and key encapsulation mechanism (KEM) functions.
const { createHmac } = await import('node:crypto'); const secret = 'abcdefg'; const hash = createHmac('sha256', secret) .update('I love cupcakes') .digest('hex'); console.log(hash); // Prints: // c0fa1bc00531bd78ef38c628449c5102aeabd49b5dc3a2a516ea6ea959d6658econst { createHmac } = require('node:crypto'); const secret = 'abcdefg'; const hash = createHmac('sha256', secret) .update('I love cupcakes') .digest('hex'); console.log(hash); // Prints: // c0fa1bc00531bd78ef38c628449c5102aeabd49b5dc3a2a516ea6ea959d6658e
Determining if crypto support is unavailable#
It is possible for Node.js to be built without including support for the
node:crypto module. In such cases, attempting to import from crypto or
calling require('node:crypto') will result in an error being thrown.
When using CommonJS, the error thrown can be caught using try/catch:
let crypto;
try {
crypto = require('node:crypto');
} catch (err) {
console.error('crypto support is disabled!');
}
When using the lexical ESM import keyword, the error can only be
caught if a handler for process.on('uncaughtException') is registered
before any attempt to load the module is made (using, for instance,
a preload module).
When using ESM, if there is a chance that the code may be run on a build
of Node.js where crypto support is not enabled, consider using the
import() function instead of the lexical import keyword:
let crypto;
try {
crypto = await import('node:crypto');
} catch (err) {
console.error('crypto support is disabled!');
}
Asymmetric key types#
The following lists group the asymmetric key types recognized by the
KeyObject API by the complete set of formats supported for importing and
exporting each type.
Formats: 'pem', 'der'
'dh'(Diffie-Hellman) — OID1.2.840.113549.1.3.1'dsa'— OID1.2.840.10040.4.1'rsa-pss'— OID1.2.840.113549.1.1.10
Formats: 'pem', 'der', 'jwk'
'rsa'— OID1.2.840.113549.1.1.1
Formats: 'pem', 'der', 'jwk', 'raw-public', 'raw-private'
'ec'(Elliptic curve) — OID1.2.840.10045.2.1'ed25519'— OID1.3.101.112'ed448'— OID1.3.101.113'slh-dsa-sha2-128f'1 — OID2.16.840.1.101.3.4.3.21'slh-dsa-sha2-128s'1 — OID2.16.840.1.101.3.4.3.20'slh-dsa-sha2-192f'1 — OID2.16.840.1.101.3.4.3.23'slh-dsa-sha2-192s'1 — OID2.16.840.1.101.3.4.3.22'slh-dsa-sha2-256f'1 — OID2.16.840.1.101.3.4.3.25'slh-dsa-sha2-256s'1 — OID2.16.840.1.101.3.4.3.24'slh-dsa-shake-128f'1 — OID2.16.840.1.101.3.4.3.27'slh-dsa-shake-128s'1 — OID2.16.840.1.101.3.4.3.26'slh-dsa-shake-192f'1 — OID2.16.840.1.101.3.4.3.29'slh-dsa-shake-192s'1 — OID2.16.840.1.101.3.4.3.28'slh-dsa-shake-256f'1 — OID2.16.840.1.101.3.4.3.31'slh-dsa-shake-256s'1 — OID2.16.840.1.101.3.4.3.30'x25519'— OID1.3.101.110'x448'— OID1.3.101.111
Formats: 'pem', 'der', 'jwk', 'raw-public', 'raw-seed'
Key formats#
Asymmetric keys can be represented in several formats. The recommended
approach is to import key material into a KeyObject once and reuse it
for all subsequent operations, as this avoids repeated parsing and delivers
the best performance.
When a KeyObject is not practical - for example, when key material
arrives in a protocol message and is used only once - most cryptographic
functions also accept a PEM string or an object specifying the format
and key material directly. See crypto.createPublicKey(),
crypto.createPrivateKey(), and keyObject.export() for the full
options accepted by each format.
KeyObject#
A KeyObject is the in-memory representation of a parsed key. It is
created by crypto.createPublicKey(), crypto.createPrivateKey(),
crypto.createSecretKey(), or key generation functions such as
crypto.generateKeyPair(). The first cryptographic operation with a given
KeyObject may be slower than subsequent ones because OpenSSL lazily
initializes internal caches on first use.
PEM and DER#
PEM and DER are the traditional encoding formats for asymmetric keys based on ASN.1 structures.
- PEM is a text encoding that wraps Base64-encoded DER data between
header and footer lines (e.g.
-----BEGIN PUBLIC KEY-----). PEM strings can be passed directly to most cryptographic operations. - DER is the binary encoding of the same ASN.1 structures. When providing
DER input, the
type(typically'spki'or'pkcs8') must be specified explicitly.
JSON Web Key (JWK)#
JSON Web Key (JWK) is a JSON-based key representation defined in RFC 7517. JWK encodes each key component as an individual Base64url-encoded value inside a JSON object. For RSA keys, JWK avoids ASN.1 parsing overhead and is the fastest serialized import format.
Raw key formats#
Stability: 1.1 - Active development
The 'raw-public', 'raw-private', and 'raw-seed' key formats allow
importing and exporting raw key material without any encoding wrapper.
See keyObject.export(), crypto.createPublicKey(), and
crypto.createPrivateKey() for usage details.
'raw-public' is generally the fastest way to import a public key.
'raw-private' and 'raw-seed' are not always faster than other formats
because they only contain the private scalar or seed - importing them requires
deriving the public key component (e.g. elliptic curve point multiplication or
seed expansion), which can be expensive. Other formats include both private
and public components, avoiding that computation.
Choosing a key format#
Always prefer a KeyObject - create one from whatever format you
have and reuse it. The guidance below applies only when choosing between
serialization formats, either for importing into a KeyObject or for
passing key material inline when a KeyObject is not practical.
Importing keys#
When creating a KeyObject for repeated use, the import cost is paid once,
so choosing a faster format reduces startup latency.
The import cost breaks down into two parts: parsing overhead (decoding the serialization wrapper) and key computation (any mathematical work needed to reconstruct the full key, such as deriving a public key from a private scalar or expanding a seed). Which part dominates depends on the key type. For example:
- Public keys -
'raw-public'is the fastest serialized format because the raw format skips all ASN.1 and Base64 decoding. - EC private keys -
'raw-private'is faster than PEM or DER because it avoids ASN.1 parsing. However, for larger curves (e.g. P-384, P-521) the required derivation of the public point from the private scalar becomes expensive, reducing the advantage. - RSA keys -
'jwk'is the fastest serialized format. JWK represents RSA key components as individual Base64url-encoded integers, avoiding the overhead of ASN.1 parsing entirely.
Inline key material in operations#
When a KeyObject cannot be reused (e.g. the key arrives as raw bytes in
a protocol message and is used only once), most cryptographic functions also
accept a PEM string or an object specifying the format and key
material directly. In this case the total cost is the sum of key import and
the cryptographic computation itself.
For operations where the cryptographic computation dominates - such as
signing with RSA or ECDH key agreement with P-384 or P-521 - the
serialization format has negligible impact on overall throughput, so choose
whichever format is most convenient. For lightweight operations like Ed25519
signing or verification, the import cost is a larger fraction of the total,
so a faster format like 'raw-public' or 'raw-private' can meaningfully
improve throughput.
Even if the same key material is used only a few times, it is worth importing it
into a KeyObject rather than passing the raw or PEM representation
repeatedly.
Examples#
Example: Reusing a KeyObject across sign and verify operations:
import { promisify } from 'node:util';
const { generateKeyPair, sign, verify } = await import('node:crypto');
const { publicKey, privateKey } = await promisify(generateKeyPair)('ed25519');
// A KeyObject holds the parsed key in memory and can be reused
// across multiple operations without re-parsing.
const data = new TextEncoder().encode('message to sign');
const signature = sign(null, data, privateKey);
verify(null, data, publicKey, signature);
Example: Importing keys of various formats into KeyObjects:
import { promisify } from 'node:util';
const {
createPrivateKey, createPublicKey, generateKeyPair,
} = await import('node:crypto');
const generated = await promisify(generateKeyPair)('ed25519');
// PEM
const privatePem = generated.privateKey.export({ format: 'pem', type: 'pkcs8' });
const publicPem = generated.publicKey.export({ format: 'pem', type: 'spki' });
createPrivateKey(privatePem);
createPublicKey(publicPem);
// DER - requires explicit type
const privateDer = generated.privateKey.export({ format: 'der', type: 'pkcs8' });
const publicDer = generated.publicKey.export({ format: 'der', type: 'spki' });
createPrivateKey({ key: privateDer, format: 'der', type: 'pkcs8' });
createPublicKey({ key: publicDer, format: 'der', type: 'spki' });
// JWK
const privateJwk = generated.privateKey.export({ format: 'jwk' });
const publicJwk = generated.publicKey.export({ format: 'jwk' });
createPrivateKey({ key: privateJwk, format: 'jwk' });
createPublicKey({ key: publicJwk, format: 'jwk' });
// Raw
const rawPriv = generated.privateKey.export({ format: 'raw-private' });
const rawPub = generated.publicKey.export({ format: 'raw-public' });
createPrivateKey({ key: rawPriv, format: 'raw-private', asymmetricKeyType: 'ed25519' });
createPublicKey({ key: rawPub, format: 'raw-public', asymmetricKeyType: 'ed25519' });
Example: Passing key material directly to crypto.sign() and
crypto.verify() without creating a KeyObject first:
import { promisify } from 'node:util';
const { generateKeyPair, sign, verify } = await import('node:crypto');
const generated = await promisify(generateKeyPair)('ed25519');
const data = new TextEncoder().encode('message to sign');
// PEM strings
const privatePem = generated.privateKey.export({ format: 'pem', type: 'pkcs8' });
const publicPem = generated.publicKey.export({ format: 'pem', type: 'spki' });
const sig1 = sign(null, data, privatePem);
verify(null, data, publicPem, sig1);
// JWK objects
const privateJwk = generated.privateKey.export({ format: 'jwk' });
const publicJwk = generated.publicKey.export({ format: 'jwk' });
const sig2 = sign(null, data, { key: privateJwk, format: 'jwk' });
verify(null, data, { key: publicJwk, format: 'jwk' }, sig2);
// Raw key bytes
const rawPriv = generated.privateKey.export({ format: 'raw-private' });
const rawPub = generated.publicKey.export({ format: 'raw-public' });
const sig3 = sign(null, data, {
key: rawPriv, format: 'raw-private', asymmetricKeyType: 'ed25519',
});
verify(null, data, {
key: rawPub, format: 'raw-public', asymmetricKeyType: 'ed25519',
}, sig3);
Example: For EC keys, the namedCurve option is required when importing
raw keys:
import { promisify } from 'node:util';
const {
createPrivateKey, createPublicKey, generateKeyPair, sign, verify,
} = await import('node:crypto');
const generated = await promisify(generateKeyPair)('ec', {
namedCurve: 'P-256',
});
// Export the raw EC public key (uncompressed by default).
const rawPublicKey = generated.publicKey.export({ format: 'raw-public' });
// The following is equivalent.
const rawPublicKeyUncompressed = generated.publicKey.export({
format: 'raw-public',
type: 'uncompressed',
});
// Export compressed point format.
const rawPublicKeyCompressed = generated.publicKey.export({
format: 'raw-public',
type: 'compressed',
});
// Export the raw EC private key.
const rawPrivateKey = generated.privateKey.export({ format: 'raw-private' });
// Import the raw EC keys.
// Both compressed and uncompressed point formats are accepted.
const publicKey = createPublicKey({
key: rawPublicKey,
format: 'raw-public',
asymmetricKeyType: 'ec',
namedCurve: 'P-256',
});
const privateKey = createPrivateKey({
key: rawPrivateKey,
format: 'raw-private',
asymmetricKeyType: 'ec',
namedCurve: 'P-256',
});
const data = new TextEncoder().encode('message to sign');
const signature = sign('sha256', data, privateKey);
verify('sha256', data, publicKey, signature);
Example: Exporting raw seeds and importing them:
import { promisify } from 'node:util';
const {
createPrivateKey, decapsulate, encapsulate, generateKeyPair,
} = await import('node:crypto');
const generated = await promisify(generateKeyPair)('ml-kem-768');
// Export the raw seed (64 bytes for ML-KEM).
const seed = generated.privateKey.export({ format: 'raw-seed' });
// Import the raw seed.
const privateKey = createPrivateKey({
key: seed,
format: 'raw-seed',
asymmetricKeyType: 'ml-kem-768',
});
const { ciphertext } = encapsulate(generated.publicKey);
decapsulate(privateKey, ciphertext);
Class: Certificate#
SPKAC is a Certificate Signing Request mechanism originally implemented by
Netscape and was specified formally as part of HTML5's keygen element.
<keygen> is deprecated since HTML 5.2 and new projects
should not use this element anymore.
The node:crypto module provides the Certificate class for working with SPKAC
data. The most common usage is handling output generated by the HTML5
<keygen> element. Node.js uses OpenSSL's SPKAC implementation internally.
Static method: Certificate.exportChallenge(spkac[, encoding])#
spkac<string>|<ArrayBuffer>|<Buffer>|<TypedArray>|<DataView>encoding<string>The encoding of thespkacstring.- Returns:
<Buffer>The challenge component of thespkacdata structure, which includes a public key and a challenge.
const { Certificate } = await import('node:crypto'); const spkac = getSpkacSomehow(); const challenge = Certificate.exportChallenge(spkac); console.log(challenge.toString('utf8')); // Prints: the challenge as a UTF8 stringconst { Certificate } = require('node:crypto'); const spkac = getSpkacSomehow(); const challenge = Certificate.exportChallenge(spkac); console.log(challenge.toString('utf8')); // Prints: the challenge as a UTF8 string
Static method: Certificate.exportPublicKey(spkac[, encoding])#
spkac<string>|<ArrayBuffer>|<Buffer>|<TypedArray>|<DataView>encoding<string>The encoding of thespkacstring.- Returns:
<Buffer>The public key component of thespkacdata structure, which includes a public key and a challenge.
const { Certificate } = await import('node:crypto');
const spkac = getSpkacSomehow();
const publicKey = Certificate.exportPublicKey(spkac);
console.log(publicKey)