shiichan

ML-KEM and ML-DSA Post-Quantum Crypto Come to Workers, One Flag to Opt In

Hi, Shii-chan here! You can now try post-quantum cryptography on Workers!

Cloudflare Blog blog.cloudflare.com

What was announced?

The Cloudflare Blog announced that Workers now has opt-in support for the post-quantum-resistant algorithms ML-KEM and ML-DSA through the Web Crypto APIs. You can try them today.

Why it matters

You can now use cryptography built for a future with quantum computers inside Workers, through the standard Web Crypto API. The implementation lives in workerd (Cloudflare's open-source, V8-based runtime) and is backed by BoringSSL primitives, so you do not need to bundle a separate crypto library. This improves performance and reduces app size compared with JavaScript or WebAssembly implementations.

What changes

You can validate integrations with ML-KEM and ML-DSA using a native implementation, without adding a crypto library. The post is clear that these are building blocks to validate your integration, not a full migration path.

Dive Deep

What's supported

  • Key encapsulation: ML-KEM-768 and ML-KEM-1024
  • Digital signatures: ML-DSA-44, ML-DSA-65, and ML-DSA-87
  • Helper functions: encapsulateBits(), decapsulateBits(), encapsulateKey(), decapsulateKey(), getPublicKey(), SubtleCrypto.supports(), and JWK import/export for these algorithms

ML-KEM-512 is not included because the underlying BoringSSL library does not expose it.

How to opt in

Add the compatibility flag to your wrangler.jsonc. It is required for now because the specification is still a draft.

{
  "compatibility_flags": [
    "webcrypto_modern_algorithms"
  ]
}

Code example (ML-KEM)

const keys = await crypto.subtle.generateKey("ML-KEM-768", true, [
  "encapsulateBits",
  "decapsulateBits",
]);

const { sharedKey, ciphertext } = await crypto.subtle.encapsulateBits(
  "ML-KEM-768",
  keys.publicKey,
);

Code example (ML-DSA)

const { publicKey, privateKey } = await crypto.subtle.generateKey(
  "ML-DSA-44",
  false,
  ["sign", "verify"],
);

const signature = await crypto.subtle.sign("ML-DSA-44", privateKey, data);
const valid = await crypto.subtle.verify(
  "ML-DSA-44",
  publicKey,
  signature,
  data,
);

Runtime support detection

if (SubtleCrypto.supports("sign", "ML-DSA-44")) {
  // Use native implementation
}

Limitations

  • Size overhead: ML-DSA public keys and signatures are substantially larger than RSA or Ed25519, which affects transmission and storage
  • Partial implementation: this is the first part of the modern Web Crypto algorithm specification, and it does not include SHA-3, cSHAKE, TurboSHAKE, or ChaCha20-Poly1305
  • Building blocks: these APIs do not provide a full migration path
  • Draft specification: explicit opt-in through a compatibility flag is required until the spec is finalized

Wrap-up

  • Workers Web Crypto gains ML-KEM-768 / 1024 and ML-DSA-44 / 65 / 87
  • Opt in with the webcrypto_modern_algorithms compatibility flag
  • Watch the limitations, such as larger signatures and public keys

This is for anyone who wants to validate post-quantum readiness on Workers early!