Workers 对现代密码算法的支持:在边缘运行时试用后量子 Web Crypto

原文标题: Support for modern cryptographic algorithms in Workers
作者: Thibault Meunier
来源: Cloudflare Blog 原文
原文日期: 2026 年 10 月 1 日

Cloudflare Workers 为 Web Crypto 增加了若干后量子密码算法接口,使开发者可以在 Worker 运行时中试验 ML-KEM 密钥封装和 ML-DSA 数字签名。它们属于仍在演进的 Web Crypto 现代算法草案,因此目前通过兼容性标志显式启用。它们提供的是构造更完整协议所需的密码学原语,并不意味着应用已经完成后量子迁移。

为什么在 Web Crypto 中提供这些原语

在 JavaScript 环境中试验新的后量子算法,过去通常需要自己把协议拼在现有 Web Crypto 接口上,或额外打包 JavaScript、WebAssembly 密码库。这样会把选择、维护实现的责任交给应用和下游库,也会增大应用包体。若运行时直接提供底层原语,采用 Web Crypto 的库便有机会复用运行时能力,而不必为每个环境附带一份实现。

后量子迁移涉及协议、库、服务和部署环境,不能通过打开一个开关一次完成。Workers 此次提供的构件包括:

  • ML-KEM-768、ML-KEM-1024:密钥封装;
  • ML-DSA-44、ML-DSA-65、ML-DSA-87:数字签名;
  • encapsulateBits()、decapsulateBits()、encapsulateKey()、decapsulateKey();
  • getPublicKey() 与 SubtleCrypto.supports();
  • 这些算法的 JWK 导入和导出支持。

初始实现的接口仍是 opt-in,因为它依据的规格还在变化,Cloudflare 希望库作者先实际检验并反馈。

ML-KEM:协商共享密钥材料

ML-KEM 是密钥封装机制。接收方先持有公私钥;发送方使用公开密钥封装出共享密钥材料和密文;持有私钥的一方再解封装密文,得到相同的共享密钥材料。下面的简化示例展示 ML-KEM-768 的基本调用:

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

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

这段代码还没有加密应用数据。ML-KEM 只给通信双方提供共享密钥材料。像混合公钥加密(HPKE)这样的协议还要通过密钥调度,并使用 AES-GCM 之类的认证加密算法,才能构成完整的加密方案。把密钥封装结果误当成“已经加密的消息”是不对的。

ML-DSA:签名并验证字节

ML-DSA 的使用形态接近 Ed25519 或 ECDSA:生成密钥对,对字节签名,再使用公钥验证。下例与原文展示的接口相对应:

const data = new TextEncoder().encode("hello post-quantum");

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,
);

这类代码同样只是原语示范,不是可直接用于生产的协议设计。真正集成时还需要确定消息编码、密钥管理、算法协商和协议层行为。

与常见协议和库集成

后量子算法正逐步进入协议生态:OpenSSH 已支持混合 ML-KEM 与 X25519 的方案;HPKE 相关工作也在推进后量子和混合 KEM;ML-DSA 已有用于 JOSE 的规范工作。要让这些协议在 Workers 上使用相应算法,运行时需要具备底层密码原语。

例如,jose 可以把 ML-DSA 用于签名 JWT。原文示例的核心流程如下:

import * as jose from "jose";

const alg = "ML-DSA-44";
const { publicKey, privateKey } = await jose.generateKeyPair(alg);

const jwt = await new jose.SignJWT({ sub: "alice" })
  .setProtectedHeader({ alg })
  .setIssuedAt()
  .setExpirationTime("5m")
  .sign(privateKey);

await jose.jwtVerify(jwt, publicKey);

库可以把签名操作交给运行时,而不必为所有环境打包自有实现。使用 ML-KEM 的 HPKE 也类似:由库选择运行时可用的 Web Crypto 实现,再组合 KEM、密钥派生函数和 AEAD。下面是原文给出的调用结构:

import * as HPKE from "hpke";

const plaintext = new TextEncoder().encode("Hello World!");

const suite = new HPKE.CipherSuite(
  HPKE.KEM_ML_KEM_768,
  HPKE.KDF_HKDF_SHA256,
  HPKE.AEAD_AES_128_GCM,
);
const recipient = await suite.GenerateKeyPair();
const sealed = await suite.Seal(recipient.publicKey, plaintext);

const opened = await suite.Open(
  recipient.privateKey,
  sealed.encapsulatedSecret,
  sealed.ciphertext,
);

运行时支持原语并不保证每个库都无需改动;库可能需要针对具体运行时做集成适配。原文特别指出,HPKE 库可以根据环境选择实现。

从私钥取得公钥,并检查运行时能力

有些协议需要在加载私钥后发布或推导对应的公钥。新增的 getPublicKey() 可以直接完成此事。签名密钥可请求 verify 用途的公钥:

const publicKey = await crypto.subtle.getPublicKey(privateKey, ["verify"]);

ML-KEM 的用途不同:公钥用于封装,私钥用于解封装,因此取得公钥时应请求 encapsulateBits:

const publicKey = await crypto.subtle.getPublicKey(privateKey, [
  "encapsulateBits",
]);

这些现代算法并非所有 JavaScript 运行时都支持。跨 Workers、Node.js、Deno、浏览器等环境运行的库应在调用前检查能力,而不是假定接口普遍存在:

if (SubtleCrypto.supports("sign", "ML-DSA-44")) {
  const keys = await crypto.subtle.generateKey("ML-DSA-44", false, [
    "sign",
    "verify",
  ]);
}

能力检查也有助于处理“部分实现”:某个运行时可能只实现提案的一部分。

在 Workers 中启用和当前支持范围

使用这些算法需要在 wrangler.jsonc 中加入兼容性标志:

{
  // Opt into modern crypto algorithms
  "compatibility_flags": [
    "webcrypto_modern_algorithms"
  ]
}

文章列出的初始实现包括 ML-KEM-768 和 ML-DSA-44,并说明 ML-KEM-1024、ML-DSA-65、ML-DSA-87 也可用;ML-KEM-512 不受支持,因为 Workers 使用的 BoringSSL 版本没有公开这一变体。该实现选择使用原生密码库已提供的算法,没有为缺少的变体另行加入一套实现。支持清单应以 Cloudflare 开发者文档的当前版本为准。

Workers 运行在基于 V8 的 workerd 上。此次实现把 ML-KEM 和 ML-DSA 接入 workerd 的 Web Crypto 层,由 BoringSSL 原语提供支持;同时加入了现代算法 API 的 Web Platform Tests、兼容性标志相关测试,以及相应的 Workers TypeScript 类型。

这次改动是较大 Web Crypto 现代算法提案中的一部分,聚焦 ML-KEM、ML-DSA、辅助接口和 JWK 支持。SHA-3、cSHAKE、TurboSHAKE、ChaCha20-Poly1305 等其他提案内容不在此次实现范围内,HPKE 也不是这次 Workers 原生 Web Crypto 改动所实现的算法接口。

实验前需要留意的限制

ML-DSA 公钥和签名明显大于 RSA 或 Ed25519 对应数据。运行时集成可以减少应用重复携带密码实现,但不会消除密钥、签名和密文在传输或存储时变大的事实。

这些 API 仍由 webcrypto_modern_algorithms 标志控制,规格还处于草案阶段。现阶段适合验证库和协议集成、反馈接口问题;不能据此认定现有业务协议已自动获得后量子安全,也不能把 ML-KEM 示例单独当作消息加密协议。若要面向实际系统迁移,需要进一步确认所用协议、对端能力、密钥与数据格式、运行时支持情况,以及密钥/签名体积对网络和存储的影响。

作者致谢: 原文感谢 Filip Skokan 的最初贡献与迭代,感谢 Felix Hanau、James Snell、Bas Westerbaan、Peter Wu 参与审阅,并感谢 Daniel Huigens 共同撰写该实现所依据的规范工作。

来源说明: 本文依据 Cloudflare Blog 指定原文整理与中文化。原文说明该接口基于仍在演进的草案并需显式启用;正文未列出单篇转载许可声明。本文保留原始作者和链接。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容