Sign inConnect your agent
infochanged

Workers - Web Crypto adds ML-KEM and ML-DSA support

Announced
Tags
Workers
Severity
info, set by reef/rss-rule-v1
Source
https://developers.cloudflare.com/changelog/post/2026-09-28-webcrypto-modern-algorithms/

<p>The Workers Web Crypto API now supports ML-KEM-768, ML-KEM-1024, ML-DSA-44, ML-DSA-65, and ML-DSA-87. ML-KEM establishes shared secrets, while ML-DSA signs and verifies data.</p> <p>The opt-in API also adds key encapsulation and decapsulation methods, <code>getPublicKey()</code>, <code>SubtleCrypto.supports()</code>, and JSON Web Keys (JWKs) with the <code>AKP</code> key type.</p> <p>Turn on the <code>webcrypto_modern_algorithms</code> compatibility flag to use these features:</p> <div data-nb-tabs data-nb-sync-key="wranglerConfig" class><div class="relative flex border-b border-border" role="tablist" data-nb-tabs-list><span class="bg-primary pointer-events-none absolute -bottom-px h-0.5 rounded-t-sm transition-[left,width] duration-200 ease-out" data-nb-tabs-indicator aria-hidden="true"></span></div><div class="mt-3"><div role="tabpanel" data-nb-tabs-content data-nb-tab-label="wrangler.jsonc" class><figure class="nb-code-figure" data-nb-lang="jsonc"><pre class="astro-code astro-code-themes github-light github-dark nb-shiki-c6xiwz" tabindex="0" data-language="jsonc" data-nb-lang="jsonc"><code><span class="line"><span class="nb-shiki-140thh">{</span></span> <span class="line"><span class="nb-shiki-dzsirb"> "$schema"</span><span class="nb-shiki-140thh">: </span><span class="nb-shiki-mdbnqw">"./node_modules/wrangler/config-schema.json"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-dzsirb"> "compatibility_flags"</span><span class="nb-shiki-140thh">: [</span></span> <span class="line"><span class="nb-shiki-mdbnqw"> "webcrypto_modern_algorithms"</span></span> <span class="line"><span class="nb-shiki-140thh"> ]</span></span> <span class="line"><span class="nb-shiki-140thh">}</span></span></code></pre></figure></div><div role="tabpanel" data-nb-tabs-content data-nb-tab-label="wrangler.toml" class><figure class="nb-code-figure" data-nb-lang="toml"><pre class="astro-code astro-code-themes github-light github-dark nb-shiki-c6xiwz" tabindex="0" data-language="toml" data-nb-lang="toml"><code><span class="line"><span class="nb-shiki-140thh">compatibility_flags = [</span><span class="nb-shiki-mdbnqw">"webcrypto_modern_algorithms"</span><span class="nb-shiki-140thh">]</span></span></code></pre></figure></div></div></div><script type="module" src="https://developers.cloudflare.com/home/runner/work/cloudflare-docs/cloudflare-docs/src/components/ui/tabs/Tabs.astro?astro&type=script&index=0&lang.ts"></script> <p>This example uses ML-KEM-768 to establish the same shared secret on both sides:</p> <div><div data-nb-tabs data-nb-sync-key="workersExamples" class><div class="relative flex border-b border-border" role="tablist" data-nb-tabs-list><span class="bg-primary pointer-events-none absolute -bottom-px h-0.5 rounded-t-sm transition-[left,width] duration-200 ease-out" data-nb-tabs-indicator aria-hidden="true"></span></div><div class="mt-3"><div role="tabpanel" data-nb-tabs-content data-nb-tab-label="JavaScript" class><figure class="nb-code-figure nb-code-figure-titled" data-nb-lang="js"><figcaption class="nb-code-title"><span class="nb-code-title-name">src/index.js</span><span class="nb-code-title-lang">js</span></figcaption><pre class="astro-code astro-code-themes github-light github-dark nb-shiki-c6xiwz" tabindex="0" data-language="js" data-nb-lang="js"><code><span class="line"><span class="nb-shiki-1itgoe">const</span><span class="nb-shiki-dzsirb"> keyPair</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> crypto.subtle.</span><span class="nb-shiki-1t8gfj">generateKey</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"ML-KEM-768"</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-dzsirb">false</span><span class="nb-shiki-140thh">, [</span></span> <span class="line"><span class="nb-shiki-mdbnqw"> "encapsulateBits"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-mdbnqw"> "decapsulateBits"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh">]);</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe">if</span><span class="nb-shiki-140thh"> (</span><span class="nb-shiki-1itgoe">!</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"publicKey"</span><span class="nb-shiki-1itgoe"> in</span><span class="nb-shiki-140thh"> keyPair)) {</span></span> <span class="line"><span class="nb-shiki-1itgoe"> throw</span><span class="nb-shiki-1itgoe"> new</span><span class="nb-shiki-1t8gfj"> Error</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"Expected an ML-KEM key pair"</span><span class="nb-shiki-140thh">);</span></span> <span class="line"><span class="nb-shiki-140thh">}</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe">const</span><span class="nb-shiki-140thh"> { </span><span class="nb-shiki-dzsirb">sharedKey</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-dzsirb">ciphertext</span><span class="nb-shiki-140thh"> } </span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> crypto.subtle.</span><span class="nb-shiki-1t8gfj">encapsulateBits</span><span class="nb-shiki-140thh">(</span></span> <span class="line"><span class="nb-shiki-mdbnqw"> "ML-KEM-768"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh"> keyPair.publicKey,</span></span> <span class="line"><span class="nb-shiki-140thh">);</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe">const</span><span class="nb-shiki-dzsirb"> recoveredSharedKey</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> crypto.subtle.</span><span class="nb-shiki-1t8gfj">decapsulateBits</span><span class="nb-shiki-140thh">(</span></span> <span class="line"><span class="nb-shiki-mdbnqw"> "ML-KEM-768"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh"> keyPair.privateKey,</span></span> <span class="line"><span class="nb-shiki-140thh"> ciphertext,</span></span> <span class="line"><span class="nb-shiki-140thh">);</span></span></code></pre></figure></div><div role="tabpanel" data-nb-tabs-content data-nb-tab-label="TypeScript" class><figure class="nb-code-figure nb-code-figure-titled" data-nb-lang="ts"><figcaption class="nb-code-title"><span class="nb-code-title-name">src/index.ts</span><span class="nb-code-title-lang">ts</span></figcaption><pre class="astro-code astro-code-themes github-light github-dark nb-shiki-c6xiwz" tabindex="0" data-language="ts" data-nb-lang="ts"><code><span class="line"><span class="nb-shiki-1itgoe">const</span><span class="nb-shiki-dzsirb"> keyPair</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> crypto.subtle.</span><span class="nb-shiki-1t8gfj">generateKey</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"ML-KEM-768"</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-dzsirb">false</span><span class="nb-shiki-140thh">, [</span></span> <span class="line"><span class="nb-shiki-mdbnqw"> "encapsulateBits"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-mdbnqw"> "decapsulateBits"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh">]);</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe">if</span><span class="nb-shiki-140thh"> (</span><span class="nb-shiki-1itgoe">!</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"publicKey"</span><span class="nb-shiki-1itgoe"> in</span><span class="nb-shiki-140thh"> keyPair)) {</span></span> <span class="line"><span class="nb-shiki-1itgoe"> throw</span><span class="nb-shiki-1itgoe"> new</span><span class="nb-shiki-1t8gfj"> Error</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"Expected an ML-KEM key pair"</span><span class="nb-shiki-140thh">);</span></span> <span class="line"><span class="nb-shiki-140thh">}</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe">const</span><span class="nb-shiki-140thh"> { </span><span class="nb-shiki-dzsirb">sharedKey</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-dzsirb">ciphertext</span><span class="nb-shiki-140thh"> } </span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> crypto.subtle.</span><span class="nb-shiki-1t8gfj">encapsulateBits</span><span class="nb-shiki-140thh">(</span></span> <span class="line"><span class="nb-shiki-mdbnqw"> "ML-KEM-768"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh"> keyPair.publicKey,</span></span> <span class="line"><span class="nb-shiki-140thh">);</span></span> <span class="line"></span> <span class="line"><span class="nb-shiki-1itgoe">const</span><span class="nb-shiki-dzsirb"> recoveredSharedKey</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> await</span><span class="nb-shiki-140thh"> crypto.subtle.</span><span class="nb-shiki-1t8gfj">decapsulateBits</span><span class="nb-shiki-140thh">(</span></span> <span class="line"><span class="nb-shiki-mdbnqw"> "ML-KEM-768"</span><span class="nb-shiki-140thh">,</span></span> <span class="line"><span class="nb-shiki-140thh"> keyPair.privateKey,</span></span> <span class="line"><span class="nb-shiki-140thh"> ciphertext,</span></span> <span class="line"><span class="nb-shiki-140thh">);</span></span></code></pre></figure></div></div></div></div> <p>Workers implements a subset of the evolving <a href="https://wicg.github.io/webcrypto-modern-algos/" target="_blank" rel="noopener">Modern Algorithms in the Web Cryptography API<span class="external-link"> ↗︎</span></a> draft. ML-KEM-512 and the draft's other algorithms are not supported. The API may change as the draft evolves.</p> <p>For current algorithm and operation support, refer to <a href="https://developers.cloudflare.com/workers/runtime-apis/web-crypto/#supported-algorithms">Web Crypto supported algorithms</a>.</p>

The text above is the source's. reef added the severity, the dates it could read from the text, and the endpoints and scopes named in code.