跳转到内容
搜索文档

Web Crypto

最后更新 查看 MarkdownAgent 设置

背景

Web Crypto API 提供一组用于常见加密任务的底层函数。Workers 运行时实现了此 API 的完整接口,但在支持的算法方面与大多数浏览器实现的算法存在差异。

使用 Web Crypto API 执行加密操作比纯 JavaScript 执行要快得多。如果您想执行 CPU 密集型的加密操作,应考虑使用 Web Crypto API。

Web Crypto API 通过 SubtleCrypto 接口实现,可通过全局 crypto.subtle 绑定(binding)访问。计算摘要(也称为哈希)的简单示例如下:

const myText = new TextEncoder().encode('Hello world!');

const myDigest = await crypto.subtle.digest(
  {
    name: 'SHA-256',
  },
  myText // The data you want to hash as an ArrayBuffer
);

console.log(new Uint8Array(myDigest));

一些常见用途包括签名请求


构造函数

  • crypto.DigestStream(algorithm) DigestStream

    • crypto API 的非标准扩展,支持从流式数据生成哈希摘要。DigestStream 本身是一个 WritableStream,不会保留写入其中的数据。相反,当数据流结束时,它会自动生成哈希摘要。

参数

用法

export default {
  async fetch(req) {
    // Fetch from origin
    const res = await fetch(req);

    // We need to read the body twice so we `tee` it (get two instances)
    const [bodyOne, bodyTwo] = res.body.tee();
    // Make a new response so we can set the headers (responses from `fetch` are immutable)
    const newRes = new Response(bodyOne, res);
    // Create a SHA-256 digest stream and pipe the body into it
    const digestStream = new crypto.DigestStream("SHA-256");
    bodyTwo.pipeTo(digestStream);
    // Get the final result
    const digest = await digestStream.digest;
    // Turn it into a hex string
    const hexString = [...new Uint8Array(digest)]
      .map(b => b.toString(16).padStart(2, '0'))
      .join('')
    // Set a header with the SHA-256 hash and return the response
    newRes.headers.set("x-content-digest", `SHA-256=${hexString}`);
    return newRes;
  }
}
export default {
  async fetch(req): Promise<Response> {
    // Fetch from origin
    const res = await fetch(req);

    // We need to read the body twice so we `tee` it (get two instances)
    const [bodyOne, bodyTwo] = res.body.tee();
    // Make a new response so we can set the headers (responses from `fetch` are immutable)
    const newRes = new Response(bodyOne, res);
    // Create a SHA-256 digest stream and pipe the body into it
    const digestStream = new crypto.DigestStream("SHA-256");
    bodyTwo.pipeTo(digestStream);
    // Get the final result
    const digest = await digestStream.digest;
    // Turn it into a hex string
    const hexString = [...new Uint8Array(digest)]
      .map(b => b.toString(16).padStart(2, '0'))
      .join('')
    // Set a header with the SHA-256 hash and return the response
    newRes.headers.set("x-content-digest", `SHA-256=${hexString}`);
    return newRes;
  }
} satisfies ExportedHandler;

方法

  • crypto.randomUUID() : string

    • 生成 RFC 4122 定义的新随机(版本 4)UUID。
  • crypto.getRandomValues(bufferArrayBufferView) : ArrayBufferView

    • 用加密安全的随机值填充传入的 ArrayBufferView,并返回 buffer

参数

  • bufferArrayBufferView

    • 必须是 Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | BigInt64Array | BigUint64Array。

SubtleCrypto Methods

这些方法均通过 crypto.subtle 访问,MDN 上也有详细文档。

encrypt

  • encrypt(algorithm, key, data) : Promise<ArrayBuffer>

    • 返回一个 Promise,该 Promise 解析为与给定明文、算法和密钥对应的加密数据。

参数

  • algorithmobject

  • keyCryptoKey

  • dataBufferSource

decrypt

  • decrypt(algorithm, key, data) : Promise<ArrayBuffer>

    • 返回一个 Promise,该 Promise 解析为与给定密文、算法和密钥对应的明文数据。

参数

  • algorithmobject

  • keyCryptoKey

  • dataBufferSource

sign

  • sign(algorithm, key, data) : Promise<ArrayBuffer>

    • 返回一个 Promise,该 Promise 解析为与给定文本、算法和密钥对应的签名。

参数

  • algorithmstring | object

  • keyCryptoKey

  • dataArrayBuffer

verify

  • verify(algorithm, key, signature, data) : Promise<boolean>

    • 返回一个 Promise,该 Promise 解析为布尔值,指示给定签名是否与同样给定的文本、算法和密钥匹配。

参数

  • algorithmstring | object

  • keyCryptoKey

  • signatureArrayBuffer

  • dataArrayBuffer

digest

  • digest(algorithm, data) : Promise<ArrayBuffer>

    • 返回一个 Promise,该 Promise 解析为根据给定算法和文本生成的摘要。

参数

  • algorithmstring | object

  • dataArrayBuffer

generateKey

  • generateKey(algorithm, extractable, keyUsages) : Promise<CryptoKey> | Promise<CryptoKeyPair>

    • 返回一个 Promise,该 Promise 解析为新生成的 CryptoKey(对称算法)或 CryptoKeyPair(包含两个新生成密钥的非对称算法)。例如,生成新的 AES-GCM 密钥:
    let keyPair = await crypto.subtle.generateKey(
      {
        name: 'AES-GCM',
        length: 256,
      },
      true,
      ['encrypt', 'decrypt']
    );

参数

deriveKey

  • deriveKey(algorithm, baseKey, derivedKeyAlgorithm, extractable, keyUsages) : Promise<CryptoKey>

    • 返回一个 Promise,该 Promise 解析为根据给定基础密钥和特定算法新生成的 CryptoKey

参数

deriveBits

  • deriveBits(algorithm, baseKey, length) : Promise<ArrayBuffer>

    • 返回一个 Promise,该 Promise 解析为根据给定基础密钥和特定算法新生成的伪随机位缓冲区。它返回一个 Promise,该 Promise 解析为包含派生位的 ArrayBuffer。此方法与 deriveKey() 非常相似,不同之处在于 deriveKey() 返回 CryptoKey 对象而非 ArrayBuffer。本质上,deriveKey()deriveBits() 后跟 importKey() 组成。

参数

  • algorithmobject

  • baseKeyCryptoKey

  • lengthint

    • 要派生的位串长度。

importKey

  • importKey(format, keyData, algorithm, extractable, keyUsages) : Promise<CryptoKey>

    • 将密钥从某种外部可移植格式转换为可用于 Web Crypto API 的 CryptoKey

参数

exportKey

  • exportKey(formatstring, keyCryptoKey) : Promise<ArrayBuffer>

    • 如果 CryptoKeyextractable 的,则将其转换为可移植格式。

参数

wrapKey

  • wrapKey(format, key, wrappingKey, wrapAlgo) : Promise<ArrayBuffer>

    • CryptoKey 转换为可移植格式,然后用另一个密钥加密它。这使 CryptoKey 适合在不受信任的环境中存储或传输。

参数

unwrapKey

  • unwrapKey(format, key, unwrappingKey, unwrapAlgo,
    unwrappedKeyAlgo, extractable, keyUsages)
    : Promise<CryptoKey>

    • 将被 wrapKey() 包装的密钥转换回 CryptoKey

参数

timingSafeEqual

  • timingSafeEqual(a, b) : bool

    • 以防时序攻击的方式比较两个缓冲区。这是对 Web Crypto API 的非标准扩展。

参数

  • aArrayBuffer | TypedArray

  • bArrayBuffer | TypedArray

支持的算法

Workers 实现了 WebCrypto 标准 的所有操作,如下表所示。

勾选标记 (✓) 表示此功能据信已按规范完全支持。
叉号 (✘) 表示此功能是规范的一部分但未实现。
如果功能仅部分实现操作,则列出详细信息。

Algorithm sign()
verify()
encrypt()
decrypt()
digest() deriveBits()
deriveKey()
generateKey() wrapKey()
unwrapKey()
exportKey() importKey()
RSASSA PKCS1 v1.5
RSA PSS
RSA OAEP
ECDSA
ECDH
Ed255191
X255191
NODE ED255192
AES CTR
AES CBC
AES GCM
AES KW
HMAC
SHA 1
SHA 256
SHA 384
SHA 512
MD53
HKDF
PBKDF2

Footnotes:

  1. Secure Curves API 中指定的算法。

  2. 除 Secure Curves 版本外,还支持旧版非标准 EdDSA(Ed25519 曲线)。由于此算法是非标准的,使用时请注意以下事项:

    • 使用 NODE-ED25519 作为算法和 namedCurve 参数。
    • 与 NodeJS 不同,Cloudflare 不支持私钥的原始导入。
    • 算法实现可能会随时间变化。虽然 Cloudflare 目前无法保证,但 Cloudflare 将努力保持向后兼容以及与 NodeJS 行为的兼容性。任何重要的兼容性说明将在发布说明中传达,并通过此开发者文档提供。
  3. MD5 不是 WebCrypto 标准的一部分,但在 Cloudflare Workers 中受支持,用于与需要 MD5 的旧版系统交互。MD5 被认为是弱算法。不要依赖 MD5 来保证安全。


相关资源

这篇文档对您有帮助吗?