Web Crypto

crypto provides cryptographically secure random values and version 4 UUIDs. crypto.subtle provides low-level cryptographic operations: hashing, encryption, signatures, key generation, key import and export, key derivation, and key wrapping.

  • crypto.getRandomValues(array) fills an integer typed array with random bytes and returns the same array. Requests larger than 65,536 bytes throw a DOMException named QuotaExceededError.
  • crypto.randomUUID() returns a lowercase version 4 UUID.
  • crypto.subtle.digest(algorithm, data) hashes data.
  • crypto.subtle.generateKey, importKey, and exportKey manage keys.
  • crypto.subtle.encrypt, decrypt, sign, verify, deriveKey, deriveBits, wrapKey, and unwrapKey perform cryptographic operations.
  • A CryptoKey exposes type, extractable, algorithm, and usages. Non-extractable keys cannot be exported or wrapped.

All algorithms defined by the W3C Web Crypto API Level 2 are available.

Every crypto.subtle method returns a promise. getRandomValues and randomUUID are synchronous. Errors reject the returned promise with a DOMException or TypeError. Check error.name for the specific DOMException name.

Usage#

Generate random values and a UUID:

const bytes = crypto.getRandomValues(new Uint8Array(16));
const id = crypto.randomUUID();

Hash a string:

const encoder = new TextEncoder();
const data = encoder.encode("hello");
const digest = await crypto.subtle.digest("SHA-256", data);

Encrypt and decrypt with AES-GCM:

const key = await crypto.subtle.generateKey(
  { name: "AES-GCM", length: 256 },
  true,
  ["encrypt", "decrypt"],
);

const iv = crypto.getRandomValues(new Uint8Array(12));
const plaintext = new TextEncoder().encode("secret");
const ciphertext = await crypto.subtle.encrypt(
  { name: "AES-GCM", iv },
  key,
  plaintext,
);
const decrypted = await crypto.subtle.decrypt(
  { name: "AES-GCM", iv },
  key,
  ciphertext,
);

Sign and verify with HMAC:

const key = await crypto.subtle.generateKey(
  { name: "HMAC", hash: "SHA-256" },
  true,
  ["sign", "verify"],
);

const data = new TextEncoder().encode("message");
const signature = await crypto.subtle.sign("HMAC", key, data);
const valid = await crypto.subtle.verify("HMAC", key, signature, data);

Import a raw AES key and export it as JWK:

const key = await crypto.subtle.importKey(
  "raw",
  rawKeyBytes,
  { name: "AES-GCM" },
  true,
  ["encrypt", "decrypt"],
);

const jwk = await crypto.subtle.exportKey("jwk", key);

Differences from the standard#

CryptoKey objects are not structured-cloneable. Cloning a key, or an object containing one, throws DataCloneError.

To keep runs responsive, crypto operations are subject to per-run limits so that a single expensive operation cannot make a run hang or take an unbounded amount of time. Exceeding a limit rejects with OperationError.

Documentation#