WebCrypto

A zero-dependency W3C Web Cryptography API (Crypto / SubtleCrypto / CryptoKey) built directly on Node's native node:crypto. It is the toolkit's injectable crypto engine, presented in the standard WebCrypto shape, so operators, and every higher structure (X.509, CMS, OCSP), reach for one familiar surface.

Unlike the browser's built-in crypto.subtle, this engine is **PQC-first without being PQC-only**: the FIPS 204 ML-DSA and FIPS 205 SLH-DSA signature suites sit alongside the full classical set PKI still runs on -- RSASSA-PKCS1-v1_5, RSA-PSS, RSA-OAEP, ECDSA, ECDH, Ed25519 / Ed448, AES-GCM / CBC / KW, HMAC, HKDF, PBKDF2, the SHA family (including legacy SHA-1 for old certificates and signatures), and the SHAKE128 / SHAKE256 extendable-output functions as message digests. FIPS 203 ML-KEM key generation, encoding, certificate/PKCS#8 import, and encapsulation/decapsulation (encapsulateBits / decapsulateBits over Node's crypto.encapsulate/decapsulate) are all available. Because it is OpenSSL-backed, every key and signature it emits is interoperable with OpenSSL, NSS, and other PKI implementations.

pki.webcrypto.CryptoKey

since 0.1.0 stable
new pki.webcrypto.CryptoKey(type, extractable, algorithm, usages, handle)

Opaque handle to key material, matching the W3C CryptoKey shape: { type, extractable, algorithm, usages }. The underlying node:crypto KeyObject is non-enumerable and never serialized -- extract material only through subtle.exportKey, and only when the key was created extractable. Instances are produced by subtle.generateKey / subtle.importKey; the constructor is rarely called directly.

Example

async function example() {
  var kp = await pki.webcrypto.subtle.generateKey({ name: "Ed25519" }, true, ["sign", "verify"]);
  kp.publicKey.type;       // "public"
  kp.publicKey.algorithm;  // { name: "Ed25519" }
}
example();

References

pki.webcrypto.subtle

since 0.1.0 stable
await pki.webcrypto.subtle.exportKey(format, key)

Export a CryptoKey to spki (public), pkcs8 (private), jwk (either), or raw (symmetric, or an uncompressed EC / OKP public point). Throws unless the key was created extractable.

raw is defined for public and secret keys only; asking for it on a private key throws webcrypto/not-supported instead of answering with the public half. This matters through wrapKey, which forwards the caller's format here: wrapping a private key as raw would otherwise escrow the public key, and unwrapping it returns a handle announcing usages: ["sign"] that cannot sign, with the private key gone. Use pkcs8 or jwk to serialize a private key.

A private jwk round-trips as a private key for every algorithm, ML-DSA, ML-KEM and SLH-DSA included: those are kty: "AKP" and carry the private half in priv in place of the d an EC or OKP key uses.

Example

async function example() {
  var keyPair = await pki.webcrypto.subtle.generateKey({ name: "Ed25519" }, true, ["sign", "verify"]);
  var spki = await pki.webcrypto.subtle.exportKey("spki", keyPair.publicKey);
}
example();

References

pki.webcrypto

since 0.1.0 stable
pki.webcrypto.getRandomValues(typedArray) / pki.webcrypto.subtle

A ready Crypto instance (the shape of globalThis.crypto) exposing getRandomValues, randomUUID, and subtle. Construct additional instances with new pki.webcrypto.Crypto().

Example

var iv = pki.webcrypto.getRandomValues(new Uint8Array(12));

References