Web 加密 第 2 级

W3C 第一份公开工作草案

本文档的更多详细信息
本版本:
https://www.w3.org/TR/2025/WD-webcrypto-2-20250422/
最新发布版本:
https://www.w3.org/TR/webcrypto-2/
最新编辑草案:
https://w3c.github.io/webcrypto/
历史:
https://www.w3.org/standards/history/webcrypto-2/
提交历史
编辑:
Proton AG
前任编辑:
Mark Watson - 直到
Ryan Sleevi - 直到
反馈:
GitHub w3c/webcrypto拉取请求新议题未解决议题

摘要

本规范描述了一种 JavaScript API,用于在 Web 应用中执行基本的 加密操作,例如散列、 签名生成与验证,以及加密与解密。 此外,它还描述了一种 API,用于让应用生成和/或 管理执行这些操作所必需的密钥材料。 此 API 的用途包括用户或服务认证、文档 或代码签名,以及通信的机密性和 完整性。

本文档状态

本节描述的是本文档在其发布时的 状态。当前 W3C 出版物列表以及本技术报告的最新修订版可在 W3C 标准和草案 索引中找到,网址为 https://www.w3.org/TR/。

本文档由 Web 应用安全 工作组 作为 第一份公开工作草案发布,使用的是 推荐标准轨道

作为第一份公开工作草案发布并不 表示得到 W3C 及其成员的认可。

这是一份草案文档,随时可能被其他 文档更新、替换或废弃。除作为进行中的工作外,不宜以其他方式引用本文档。

本文档由一个根据 W3C 专利 政策 运作的工作组制作。 W3C 维护着一个 与该工作组交付物 有关的任何专利披露的公开列表; 该页面还包括 披露专利的说明。实际 知晓某项专利,并且该个人认为该专利包含 必要权利要求 的个人,必须按照 W3C 专利政策第 6 节 披露相关信息。

本文档受 2023年11月3日 W3C 流程文档管辖。

1. 简介

本节是非规范性的。

Web Cryptography API 定义了一个低级接口,用于与由用户代理管理或暴露的加密 密钥材料进行交互。该 API 本身不关心密钥存储的 底层实现,但提供了一组通用接口, 使富 Web 应用能够执行签名生成与 验证、散列与验证、加密与解密等操作,而无需 访问原始密钥材料。

加密转换通过 SubtleCrypto 接口暴露,该接口定义了一组方法, 用于执行常见的加密操作。除了签名 生成与验证、散列与验证,以及加密与解密等操作外, 该 API 还提供了用于密钥生成、密钥派生以及密钥导入和导出的接口。

2. 用例

本节是非规范性的。

2.1 多因素认证

Web 应用可能希望用基于证明用户拥有 某些秘密密钥材料访问权的认证方法,扩展或替换现有的基于用户名/密码的 认证方案。与其使用传输层认证, 例如 TLS 客户端证书,Web 应用可能更倾向于在应用自身内部进行认证所提供的 更丰富的用户体验。

使用 Web Cryptography API,应用可以定位合适的客户端密钥,这些密钥 可能此前已通过用户代理生成,或由 Web 应用通过带外方式预先配置。然后它可以执行加密操作,例如先解密一个 认证质询,再对认证响应进行签名。

通过基于底层传输的属性派生一个密钥,将认证绑定到客户端正在其上进行认证的 TLS 会话,可以进一步增强这种交换。

如果用户还没有与其账户关联的密钥,Web 应用 可以指示用户代理生成一个新密钥,或者重新使用 用户选择的现有密钥。

2.2 受保护的文档交换

Web 应用可能希望限制包含敏感或 个人信息的文档的查看者,即使这些文档已经通过安全方式接收,例如通过 TLS。

使用 Web Cryptography API,应用可以通过使用秘密密钥加密文档, 然后用与 授权查看者关联的公钥包装该密钥来实现这一点。当用户代理导航到这样的 Web 应用时, 该应用会发送文档的加密形式。随后用户代理被 指示使用用户的私钥解包加密密钥,并从那里 解密并显示文档。

2.3 云存储

Web 应用可能希望允许用户在上传之前,保护存储于远程服务提供者处的数据和 文档的机密性。

使用 Web Cryptography API,应用可以让用户选择一个私有或 秘密密钥,可选地从所选密钥派生一个加密密钥,加密 文档,然后使用现有 API 将加密数据上传到服务提供者。

此用例类似于 受保护的文档 交换用例,只是文档的查看者仅限于用户本人。

2.4 文档签名

Web 应用可能希望接受文档上的电子签名,以替代 需要物理签名。

使用 Web Cryptography API,应用可以指示用户选择一个密钥, 该密钥可能已通过带外方式预先配置,或专门为该 Web 应用生成。使用此密钥,应用可以对某些 数据执行签名操作,以证明用户接受该文档。

2.5 数据完整性保护

Web 应用可能希望在本地缓存数据,同时确保这些数据不能在 离线攻击中被修改。

使用 Web Cryptography API,应用可以使用包含在 应用中的公钥来验证数据缓存的内容。此前,当数据被添加到 缓存时,它会由服务器用相应的私钥进行签名。通过 在从缓存恢复数据时验证签名,客户端可确保 缓存的数据未被篡改。

2.6 安全消息传递

Web 应用可能希望使用诸如 off-the-record (OTR) messaging 之类的方案来采用消息层安全性,即使这些消息已经通过安全方式接收, 例如通过 TLS。

Web Cryptography API 允许执行密钥 协商,从而支持 OTR 以及类似的消息签名方案。双方可以协商共享的加密密钥和 消息认证码(MAC)密钥,以允许对消息进行加密和解密, 并防止篡改。

2.7 JavaScript Object Signing and Encryption (JOSE)

Web 应用可能希望与 IETF JavaScript Object Signing and Encryption (JOSE) Working Group 定义的结构和消息格式进行交互。

使用 Web Cryptography API,应用可以读取并导入以 JSON 密钥格式(JWK)编码的密钥,验证使用数字 签名或 MAC(JWS)进行了完整性保护的消息,或者解密已加密的消息(JWE)。

3. 一致性

除标记为非规范性的章节外,本 规范中的所有编写指南、图表、示例和注释均为非规范性的。本规范中的其他所有内容均为规范性的。

本文档中的关键词 MUSTREQUIREDSHALL 应按照 BCP 14 [RFC2119] [RFC8174] 中所述进行解释,但仅当它们以全大写形式出现时才如此,如此处所示。

本规范定义了以下一致性类别:

一致的用户代理

如果用户代理满足本规范中适用于实现的所有 一致的用户代理 MUST 级、 REQUIRED 级和 SHALL 级 标准,则该用户代理被认为是 一致的用户代理。本规范使用“conforming user agent”和“user agent”这两个术语来指代此 产品类别。

以算法或具体步骤表述的一致性要求可以以任何 方式实现,只要最终结果等效即可。(特别是,本 规范中定义的算法旨在易于遵循,而不是旨在高性能。)

使用 ECMAScript 来实现本规范中定义的 API 的用户代理 MUST 以与 Web IDL 规范中定义的 ECMAScript 绑定一致的方式实现它们 [WebIDL], 因为本规范使用该规范及其术语。

除非另有说明,字符串比较均以 区分大小写的方式进行。本规范中以等宽字体书写的字符串字面量, 例如 “this”,不包括外围引号。

3.1 可扩展性

强烈不鼓励对本规范进行厂商特定的专有扩展。 作者不得使用此类扩展,因为这样做会降低互操作性并分裂 用户群,使只有特定用户代理的用户才能访问相关 内容。

如果需要厂商特定扩展,则成员应以 厂商特定字符串作为前缀,以防止与本规范未来版本发生冲突。 扩展的定义必须保证扩展的使用既不与规范中定义的功能相矛盾,也不会导致其 不一致。

当需要对本规范进行厂商中立的扩展时,可以相应地更新本 规范,或者编写一个覆盖本规范中要求的 扩展规范。当某个将本 规范应用于其活动的人决定承认此类扩展规范的要求时,它就成为本规范一致性要求目的下的 适用规范。 由 W3C Web Cryptography Working Group 定义的适用规范列在 下表中。

规范 参考
建议读者查阅本规范的勘误,以获取对上表的更新。

4. 范围

本节是非规范性的。

4.1 抽象层级

本规范试图聚焦于各种平台特定或标准化加密 API 之间的 通用功能和特性,并避免仅特定于一两个实现的特性和 功能。因此,该 API 允许以一种避免 开发者需要关心底层密钥存储实现的抽象层级进行 密钥生成、管理和交换。该 API 专门围绕 CryptoKey 对象,作为 底层原始加密密钥材料的抽象。其背后的意图是允许一个 足够通用的 API,使一致的用户代理能够暴露 由用户代理直接存储和管理的密钥,这些密钥可能使用某些操作系统提供的每用户密钥存储等隔离 存储 API 进行存储或管理,或者存储在 安全元件等密钥存储设备中,同时允许富 Web 应用 操纵这些密钥,并且不要求 Web 应用了解 底层密钥存储的性质。

4.2 加密算法

由于底层加密实现会因一致的用户 代理而异,并且可能受制于本地策略,包括但不限于 政府或行业监管、安全最佳实践、知识产权 问题,以及受限的运行环境等考虑,本规范不规定 MUST 实现的一组强制算法。 相反,它定义了一组通用绑定,这些绑定可以以 与算法无关的方式使用;一个通用框架,用于发现用户代理或密钥 句柄是否支持底层算法;以及一组关于 各个算法在被实现时的行为的一致性要求。

4.3 范围之外

此 API 虽然允许应用生成、检索和操纵密钥 材料,但并不专门处理在特定类型的 密钥存储中(例如安全元件或智能卡)配置密钥的问题。这是因为此类配置 操作通常负担着厂商特定细节,使得定义一个 与厂商无关的接口成为一个不适宜且无界的任务。此外,此 API 不 处理或解决加密模块的发现问题,因为这些概念 依赖于底层用户代理,并且不是可在 常见操作系统、加密库和实现之间移植的概念。

5. 概念

本节是非规范性的。

5.1 底层 加密实现

本规范假定但不要求,一致的用户代理不会 并且将不会在用户代理自身内部直接实现加密操作。 从历史上看,许多用户代理已将加密操作(例如 TLS 中使用的那些操作)委托给作为底层 操作系统一部分提供的现有 API,或委托给独立于用户 代理进行管理的第三方模块。

CryptoKey 对象表示 JavaScript 执行环境与这些底层库之间的桥梁, 这是通过使用名为 [[handle]] 的 内部槽来实现的。该句柄表示一种实现特定的不透明类型,它可能无法在 JavaScript 类型中表示,也绝不会暴露给脚本作者。通过这种方式, CryptoKey 对象相对于 JavaScript 执行环境,在概念上等同于 [[handle]] 相对于底层 加密 实现。

这些 API 传统上围绕加密提供者的概念构建,加密提供者是 一组算法的特定实现的抽象。操作系统 或库可能带有默认提供者,并且通常允许用户添加 额外的提供者、重新配置已启用算法的集合,或者以其他方式自定义 加密服务的提供方式。

虽然假定大多数用户代理将与完全以软件实现的加密 提供者交互,但本 规范并不要求如此。因此,某些实现的能力可能受限于 底层硬件的能力,并且根据用户如何 配置底层加密库,这对 用户代理而言可能完全是不透明的。

5.2 密钥存储

本规范并未为 CryptoKey 对象显式提供任何新的存储机制。相反,通过为 序列化和反序列化步骤 定义 CryptoKey 对象,任何支持 存储可序列化对象的现有或未来 Web 存储 机制,都可用于存储 CryptoKey 对象。

在实践中,预计大多数作者会使用 Indexed Database API [INDEXEDDB],它允许对 键/值对进行关联式存储,其中键是对应用有意义的某个字符串标识符, 值是一个 CryptoKey 对象。这允许 存储和检索密钥材料,而不会将该密钥材料暴露给 应用或 JavaScript 环境。此外,这允许作者 拥有充分的灵活性,将任何额外元数据与 CryptoKey 本身一起存储。

6. 安全性考虑

本节是非规范性的。

6.1 面向实现者的安全性 考虑

由于没有提供显式的存储机制,本规范假定 CryptoKey 对象限定于当前执行 环境以及该环境可用的任何存储机制(例如 Indexed Database API)。应用作者依赖这一点来保障其 应用的安全性;拥有同一 CryptoKey 对象的两个源,对底层 密钥具有完全访问权, 因此,来自这些应用的消息无法区分,发送给 这些应用的消息也可以被完全恢复。实现者应确保不会在两个源之间共享 CryptoKey 对象, 除非 作者已明确选择共享(例如通过使用 postMessage)

本规范中规定的一些算法会执行计算 密集型工作,例如生成非常大的素数,或通过 对特定操作进行重复迭代。因此,恶意应用可能会试图 滥用此 API,并试图使实现执行大量工作, 从而拒绝其他正在执行的应用访问或服务。 实现应采取措施来缓解这些风险,例如限制实现 并发执行的操作数量、对已知可能会破坏执行环境的 操作要求用户同意,或者为诸如密钥大小或迭代次数等属性定义 设备特定的限制。

6.2 面向作者的安全性考虑

本规范包含了多种加密操作的描述,其中一些 在使用不当时具有已知弱点。应用开发者必须 谨慎,并查阅适当且最新的加密文献,以理解并 缓解此类问题。一般而言,强烈 不鼓励应用开发者发明新的加密协议;与所有应用一样,本 规范的用户最好使用现有协议,而 本规范提供了实现这些协议所需的构建块。

为了使用本规范中定义的 API 提供任何有意义的 加密保证,作者必须熟悉 Web 应用面临的现有威胁,以及所采用的底层安全模型。从概念上讲, 脚本注入等问题等同于其他操作 环境中的远程代码执行,允许注入恶意脚本可能导致 密钥或数据被外泄。脚本注入可能来自其他应用, 对此可通过审慎使用内容安全策略来缓解;也可能来自恶意 网络中间人,对此可通过使用传输层安全性来缓解。

本规范没有定义任何用于存储 加密密钥的具体机制。默认情况下,除非作者采取具体措施来持久化 密钥,例如通过使用 Indexed Database API,否则使用此 API 创建的密钥仅在当前页面的生命周期内有效(例如 直到发生导航事件)。希望在不同页面 或多个浏览会话之间使用同一密钥的作者,必须采用现有的 Web 存储技术。作者 应了解这些技术的安全性假设,例如 同源安全模型;也就是说,共享相同方案、主机 和端口的任何应用都可以访问同一存储分区,即使路径等 其他信息可能不同。作者可以通过 跨源共享(例如 postMessage)显式选择放宽这种安全性。

作者应注意,本规范没有对 实现如何存储底层加密密钥材料提出规范性要求。唯一的 要求是密钥材料不得暴露给脚本,除非通过使用 exportKeywrapKey 操作。特别是, 它并不 保证底层加密密钥材料不会被持久化到 磁盘上(可能未加密),也不保证拥有与用户代理相同权限运行的用户或其他 应用无法访问这些材料。任何有权访问设备存储的应用或用户 都可能恢复密钥材料,即使 脚本可能被禁止访问。

本规范没有对实现如何在所有对密钥 材料的引用消失后处理这些材料提出规范性要求。也就是说,一致的用户代理不 要求对密钥材料进行清零,并且即使对 CryptoKey 的所有引用都已消失,它仍可能在设备存储或 设备内存中可访问。

应用可以通过使用结构化克隆算法以及 postMessage 等 API,跨安全边界(例如源)共享 CryptoKey 对象。虽然对底层加密密钥 材料的访问可能会基于 extractable 属性受到限制,但一旦密钥与目标源共享,源源就无法 之后限制或撤销对该密钥的访问。因此,作者必须小心确保 其信任目标源会采取与源源相同的缓解恶意脚本的措施。 此外,如果源源发生脚本注入,攻击者可能会将密钥发布到 攻击者控制的源。每当 用户代理访问攻击者的源时,用户代理可能会被指示使用该密钥执行 加密操作,例如解密现有消息 或创建新的欺诈性消息。

作者应注意,用户可以随时选择清除 与某个源关联的存储,从而可能销毁密钥。旨在 提供长期存储(例如服务器端存储)的应用,应考虑使用 密钥托管等技术,以防止此类数据变得不可访问。作者不应假定 密钥会无限期可用。

6.3 面向 用户的安全性考虑

使用本规范中定义的 API 的应用的用户应注意, 无论采用何种加密技术,这些应用都将完全访问所有交换的消息。 也就是说,对于加密消息,使用这些 API 的应用 也将完全访问解密后的消息。

7. 隐私性考虑

本节是非规范性的。

指纹识别
通过暴露反映底层平台能力的额外 API,本 规范可能允许恶意应用确定或区分不同的 用户代理或设备。
超级 Cookie
本规范没有提供任何手段,使恶意应用能够创建 比现有 Web 存储技术寿命更长的标识符。但是,在引入此 API 的未来修订版或额外加密能力时, 必须谨慎, 例如由硬件支持的能力(例如:智能卡或可信平台模块)。 考虑到此类存储的设计目标是防止任意两个用户拥有相同的 底层密钥数据,此类 API 可能真正存在被用作违背用户意愿的永久 标识符的风险。
randomUUID 用作用户 ID
randomUUID 可用于生成用户 ID,但不会直接赋予任何生成全局 标识符的能力。

8. 依赖项

本规范依赖底层规范。

DOM

一致的用户代理 MUST 至少支持 本规范所依赖的 DOM 中定义的功能子集; 特别是,它 MUST 支持 PromiseDOMException。 [DOM]

HTML

一致的用户代理 MUST 至少支持 本规范所依赖的 HTML 中定义的功能子集; 特别是,它 MUST 支持 ArrayBufferView typedef 和可序列化对象。 [HTML]

Web IDL

一致的用户代理 MUST 是 本规范中 IDL 片段的一致实现,如 Web IDL 规范中所述。[WebIDL]

9. 术语

术语 ArrayBufferArrayBufferView可序列化 对象 由 HTML 规范定义 [HTML]。

术语 DOMStringBufferSource 定义于 [WEBIDL]。

术语 字节序列 定义于 [Infra]。

字节序列位长度 是其长度 乘以 8。

包含位序列的字节序列 b 是 通过如下方式获得的 字节序列:首先向 b 追加零个或多个 值为零的位,使所得位序列的长度最小且为 8 的 整数倍, 然后将该字符串中每个连续的 8 位序列视为一个字节。

当本规范要求将非负 整数 i 转换为长度为 n 的字节序列,其中 n * 8 大于 i 以 2 为底的对数时,用户代理必须 先计算 i 的二进制表示,最高有效位在前, 在其前面添加足够的零位,以形成长度为 n * 8 的位序列, 然后返回通过将该位序列中每个连续的 8 位序列视为一个字节而形成的字节 序列

区分大小写 的方式比较两个字符串,意味着逐个码点精确比较它们。

ASCII 不区分大小写的方式 比较两个字符串,意味着逐个码点精确比较它们,但 范围 U+0041 .. U+005A 中的码点(即 LATIN CAPITAL LETTER A 到 LATIN CAPITAL LETTER Z)和 范围 U+0061 .. U+007A 中的相应码点 (即 LATIN SMALL LETTER A 到 LATIN SMALL LETTER Z)也被视为匹配。

当本规范要求终止 算法时,用户代理必须在完成其 当前所在步骤后终止该算法。这里所指的算法是规范定义的一组处理步骤, 而不是可能正处于处理过程中的底层加密算法。

当本规范要求解析 ASN.1 结构时,用户代理必须执行以下步骤:

  1. data 为要解析的字节序列。

  2. structure 为要解析的 ASN.1 结构。

  3. exactData 为一个可选布尔值。如果未提供, 则将其初始化为 true

  4. 根据 [X690] 的区分编码规则解析 data, 使用 structure 作为要解码的 ASN.1 结构。

  5. 如果指定了 exactData,且在解析阶段没有 消耗 data 的所有字节,则 抛出一个 DataError

  6. 返回解析后的 ASN.1 结构。

当本规范要求解析 subjectPublicKeyInfo时,用户代理必须 解析 ASN.1 结构,其中 data 设置为要解析的字节序列,structure 为 [RFC5280] 中规定的 subjectPublicKeyInfo 的 ASN.1 结构, 并且 exactData 设置为 true

当本规范要求解析 PrivateKeyInfo时,用户代理必须解析 ASN.1 结构,其中 data 设置为 要解析的字节序列, structure 为 [RFC5208] 中规定的 PrivateKeyInfo 的 ASN.1 结构, 并且 exactData 设置为 true

当本规范要求解析 JWK时,用户 代理必须运行以下步骤:

  1. data 为要解析的字节序列。

  2. json 为按照 UTF-8 解释 data 所得到的 Unicode 字符串。

  3. json 转换为 UTF-16。

  4. result 为在新全局对象上下文中执行 JSON.parse 内部函数所得的对象字面量, 其中 text 参数设置为包含 json 的 JavaScript String。

  5. key 为将 result 转换为 JsonWebKey 的 IDL 字典类型所得的结果。

  6. 如果 keykty 字段未定义, 则抛出一个 DataError

  7. 返回 key

当本规范要求计算两个序列 ab用途 交集时,结果应为一个 序列,其中包含同时出现在 ab 中的每个已识别密钥用途值, 其顺序按照已识别密钥用途值列表中的顺序; 如果序列中存在某个元素与该值进行区分大小写字符串 匹配,则称该值出现在该序列中。

当本规范要求计算 usages 用途列表的规范化值时,结果应为 usages 与包含所有已识别密钥用途值的 序列的用途交集

当本规范提及与 object 的内部槽 [[slot]] 关联的缓存的 ECMAScript 对象时, 用户代理必须运行以下步骤:

  1. 如果 object 的 [[slot_cached]] 内部槽未定义:
    object 的 [[slot_cached]] 内部槽设置为 对 object 的 [[slot]] 内部槽的内容执行 [WebIDL] 中定义的到 ECMAScript 对象的类型转换所得的结果。
  2. 返回 object 的 [[slot_cached]] 内部槽的内容。

10. Crypto 接口

Crypto 接口表示一个 面向通用加密功能的接口,包括一个 以真正随机值为种子的、加密强度高的伪随机数生成器。

WebIDLpartial interface mixin WindowOrWorkerGlobalScope {
  [SameObject] readonly attribute Crypto crypto;
};

[Exposed=(Window,Worker)]
interface Crypto {
  [SecureContext] readonly attribute SubtleCrypto subtle;
  ArrayBufferView getRandomValues(ArrayBufferView array);
  [SecureContext] DOMString randomUUID();
};
实现应使用成熟的加密伪随机数生成器来生成加密强度高的随机值, 这些生成器应以高质量熵作为种子, 例如来自操作系统熵源(如 “/dev/urandom”)的熵。本 规范没有规定加密强度高的随机值中所含信息论熵的下限, 但实现应尽最大努力提供 尽可能多的熵。
此接口定义了一个同步方法,用于获取加密强度高的随机 值。虽然某些设备和实现可能支持真正随机的加密 数字生成器,或提供在熵不足时会阻塞的接口, 但在实现 getRandomValues 时,不鼓励实现使用这些来源,这既是出于性能考虑,也是为了避免耗尽系统熵。 相反,这些来源应用作加密伪随机数 生成器的种子,而该生成器随后可以高效地返回合适的值。

10.1 方法和参数

10.1.1 getRandomValues 方法

getRandomValues 方法会生成加密强度高的随机值。它必须按如下方式行事:

  1. 如果 array 不是 Int8ArrayUint8ArrayUint8ClampedArrayInt16ArrayUint16ArrayInt32ArrayUint32ArrayBigInt64ArrayBigUint64Array, 则抛出一个 TypeMismatchError终止算法

  2. byteLengtharray字节长度

  3. 如果 byteLength 大于 65536,则抛出一个 QuotaExceededError终止算法

  4. bytes 为一个长度为 byteLength字节序列

  5. 用加密安全的随机字节填充 bytes

  6. bytes 写入 array

  7. 返回 array

不要使用 getRandomValues 方法生成密钥。请改用 generateKey 方法。

10.1.2 randomUUID 方法

randomUUID 方法会生成一个新的第 4 版 UUID, 并返回其命名空间特定 字符串表示, 如 [RFC4122] 的 第 3 节所述。 要生成随机 UUID

  1. bytes 为长度为 16 的字节序列
  2. 用加密安全的随机字节填充 bytes
  3. 将表示 UUID 版本bytes[6] 的最高 4 位设置为 0100
  4. 将表示 UUID 变体bytes[8] 的最高 2 位设置为 10
  5. 返回以下内容的字符串拼接 «

    1. bytes[0] 的十六进制 表示bytes[1] 的十六进制表示bytes[2] 的十六进制表示bytes[3] 的十六进制表示
    2. "-",
    3. bytes[4] 的十六进制 表示bytes[5] 的十六进制表示
    4. "-",
    5. bytes[6] 的十六进制 表示bytes[7] 的十六进制表示
    6. "-",
    7. bytes[8] 的十六进制 表示bytes[9] 的十六进制表示
    8. "-",
    9. bytes[10] 的十六进制 表示bytes[11] 的十六进制表示bytes[12] 的十六进制表示bytes[13] 的十六进制表示bytes[14] 的 十六进制 表示bytes[15] 的十六进制表示

    »。

对于生成随机 UUID算法中描述的步骤, 字节 value十六进制表示是通过使用 ASCII 小写十六进制 数字以十六进制表示 value 所创建的 两字符字符串,并在左侧填充 "0",以达到两个 ASCII 小写十六进制 数字

10.2 属性

10.2.1 subtle 属性

subtle 属性提供 SubtleCrypto 接口的一个实例, 该接口提供 低级加密原语和算法。

11. Algorithm 字典

Algorithm 对象是一个字典对象 [WEBIDL], 用于指定某个算法以及完全 指定所需操作所需的任何额外参数。

WebIDLtypedef (object or DOMString) AlgorithmIdentifier;

typedef AlgorithmIdentifier HashAlgorithmIdentifier;

dictionary Algorithm {
  required DOMString name;
};

11.1 Algorithm 字典成员

name
要使用的已注册算法的名称。

12. KeyAlgorithm 字典

KeyAlgorithm 字典表示有关给定 CryptoKey 对象内容的信息。

WebIDLdictionary KeyAlgorithm {
  required DOMString name;
};

12.1 描述

本节是非规范性的。

提供 KeyAlgorithm 字典,是为了帮助 记录 CryptoKey 的固定公共属性如何反映回应用。实际的字典类型从不会暴露 给应用。

12.2 KeyAlgorithm 字典 成员

name
用于生成 CryptoKey 的算法名称

13. CryptoKey 接口

CryptoKey 对象表示对由用户代理管理的密钥材料的一个不透明引用。

WebIDLenum KeyType { "public", "private", "secret" };

enum KeyUsage { "encrypt", "decrypt", "sign", "verify", "deriveKey", "deriveBits", "wrapKey", "unwrapKey" };

[SecureContext,Exposed=(Window,Worker),Serializable]
interface CryptoKey {
  readonly attribute KeyType type;
  readonly attribute boolean extractable;
  readonly attribute object algorithm;
  readonly attribute object usages;
};

13.1 描述

本节是非规范性的。

本规范为用户代理管理的许多不同种类的密钥 材料提供统一接口。这可以包括由 用户代理生成的密钥、由用户代理从其他密钥派生的密钥、通过用户操作或使用此 API 导入到用户代理的密钥、预先配置在用户代理可访问的软件或硬件中的密钥, 或以其他方式提供给用户代理的密钥。 术语“密钥”广义地指任何密钥材料,包括用于加密 操作的实际密钥,以及在密钥派生或交换操作中获得的秘密值。

CryptoKey 对象不需要直接与底层密钥 存储机制交互,而可以只是用户代理用来理解 在需要时(例如执行加密操作时)如何获取密钥材料的一个引用。

13.2 Key 接口数据类型

KeyType
密钥的类型。已识别的 密钥类型值 为 "public"、"private" 和 "secret"。 不透明密钥材料,包括用于对称算法的密钥材料,由 secret 表示,而作为由 公钥/私钥密钥对组成的非对称算法一部分使用的密钥,将是 publicprivate
KeyUsage
可以使用密钥执行的一种操作类型。 已识别的密钥用途值encryptdecryptsignverifyderiveKeyderiveBitswrapKeyunwrapKey

13.3 CryptoKey 内部槽

每个 CryptoKey 对象都有一组内部槽,用于 存储有关密钥的信息。这些槽不会作为本规范的一部分暴露; 它们表示实现用于实现本规范的内部状态。 这里复用了 [ECMA-262] 中使用的记号约定;内部 槽以包含在双重方括号 [[ ]] 中的名称标识。

所有 CryptoKey 对象都具有名为 [[type]][[extractable]][[algorithm]][[algorithm_cached]][[usages]][[usages_cached]] 以及 [[handle]] 的内部槽。

[[algorithm]] 内部 槽的内容应为 KeyAlgorithm,或从其派生。 [[usages]] 内部 槽的内容应为 Sequence<KeyUsage> 类型。

[[handle]] 槽是 一种不透明类型, 包含底层加密实现用来表示逻辑密钥的任何数据。 不同的加密实现可能使用不同类型,从 表示为整数的不透明标识符,到指针类型,或 提供标识信息的结构。这些句柄绝不会暴露给应用。

13.4 CryptoKey 接口成员

type
反映 [[type]] 内部 槽, 该槽包含底层密钥的类型。
extractable
反映 [[extractable]] 内部 槽,该槽指示原始密钥材料是否可以由 应用导出。
algorithm
返回与 [[algorithm]] 内部槽关联的 缓存的 ECMAScript 对象
usages
返回与 [[usages]] 内部槽关联的 缓存的 ECMAScript 对象, 该内部槽指示哪些加密操作允许与此密钥一起使用。

13.5 序列化和 反序列化步骤

CryptoKey 对象是可序列化对象。给定 valueserialized, 其序列化 步骤为:

  1. serialized.[[Type]] 设置为 value[[type]] 内部槽。
  2. serialized.[[Extractable]] 设置为 value[[extractable]] 内部槽。
  3. serialized.[[Algorithm]] 设置为 value[[algorithm]] 内部槽的 子序列化
  4. serialized.[[Usages]] 设置为 value[[usages]] 内部槽的 子序列化
  5. serialized.[[Handle]] 设置为 value[[handle]] 内部槽。

给定 serializedvalue,其反序列化 步骤为:

  1. value[[type]] 内部 槽初始化为 serialized.[[Type]]。
  2. value[[extractable]] 内部槽 初始化为 serialized.[[Extractable]]。
  3. value[[algorithm]] 内部槽 初始化为 serialized.[[Algorithm]] 的子反序列化
  4. value[[usages]] 内部槽初始化为 serialized.[[Usages]] 的子反序列化
  5. value[[handle]] 内部槽初始化为 serialized.[[Handle]]。
在反序列化已序列化的 CryptoKey 对象时, 重要的是该 对象不得被反序列化为不同类型。这由 反序列化 步骤的定义以规范方式要求,但它值得特别注意,因为 此类反序列化可能会暴露密钥材料的内容,而在某些 情况下(例如 [[extractable]] 内部槽为 false 时)不应 向应用暴露这些内容。

14. SubtleCrypto 接口

SubtleCrypto 接口提供了一组 用于处理低级加密原语和算法的方法。

WebIDLenum KeyFormat { "raw", "spki", "pkcs8", "jwk" };

[SecureContext,Exposed=(Window,Worker)]
interface SubtleCrypto {
  Promise<ArrayBuffer> encrypt(
    AlgorithmIdentifier algorithm,
    CryptoKey key,
    BufferSource data
  );
  Promise<ArrayBuffer> decrypt(
    AlgorithmIdentifier algorithm,
    CryptoKey key,
    BufferSource data
  );
  Promise<ArrayBuffer> sign(
    AlgorithmIdentifier algorithm,
    CryptoKey key,
    BufferSource data
  );
  Promise<boolean> verify(
    AlgorithmIdentifier algorithm,
    CryptoKey key,
    BufferSource signature,
    BufferSource data
  );
  Promise<ArrayBuffer> digest(
    AlgorithmIdentifier algorithm,
    BufferSource data
  );

  Promise<(CryptoKey or CryptoKeyPair)> generateKey(
    AlgorithmIdentifier algorithm,
    boolean extractable,
    sequence<KeyUsage> keyUsages
  );
  Promise<CryptoKey> deriveKey(
    AlgorithmIdentifier algorithm,
    CryptoKey baseKey,
    AlgorithmIdentifier derivedKeyType,
    boolean extractable,
    sequence<KeyUsage> keyUsages
  );
  Promise<ArrayBuffer> deriveBits(
    AlgorithmIdentifier algorithm,
    CryptoKey baseKey,
    optional unsigned long? length = null
  );

  Promise<CryptoKey> importKey(
    KeyFormat format,
    (BufferSource or JsonWebKey) keyData,
    AlgorithmIdentifier algorithm,
    boolean extractable,
    sequence<KeyUsage> keyUsages
  );
  Promise<(ArrayBuffer or JsonWebKey)> exportKey(
    KeyFormat format,
    CryptoKey key
  );

  Promise<ArrayBuffer> wrapKey(
    KeyFormat format,
    CryptoKey key,
    CryptoKey wrappingKey,
    AlgorithmIdentifier wrapAlgorithm
  );
  Promise<CryptoKey> unwrapKey(
    KeyFormat format,
    BufferSource wrappedKey,
    CryptoKey unwrappingKey,
    AlgorithmIdentifier unwrapAlgorithm,
    AlgorithmIdentifier unwrappedKeyAlgorithm,
    boolean extractable,
    sequence<KeyUsage> keyUsages
  );
};

SubtleCrypto 接口被命名为 “SubtleCrypto”, 是为了反映这样一个事实:为了提供所需的 算法安全保证,许多这类算法都有微妙的使用要求。

例如,直接使用未经认证的加密方案,例如 计数器模式下的 AES,会使潜在攻击者能够通过 操纵输入中的位来操纵输出中的位,从而破坏 消息的完整性。然而,AES-CTR 可以与其他 加密原语(例如消息认证码)组合安全地使用,以确保 受保护消息的完整性,但前提是消息认证 码是在加密消息和 IV 之上构造的。

使用 SubtleCrypto 接口的开发者应了解 与所提供各种算法的设计和实现相关的 安全性问题。提供原始算法,是为了让开发者 在实现各种协议和应用时获得最大的灵活性,其中每一种 协议和应用都可能以独特方式表示组合和安全参数, 因而需要使用原始算法。

14.1 数据类型

KeyFormat
指定密钥的序列化格式。已识别的 密钥格式值为:
raw
未格式化的字节序列。用于秘密密钥。
pkcs8
来自 [RFC5208] 的 PrivateKeyInfo 结构的 DER 编码。
spki
来自 [RFC5280] 的 SubjectPublicKeyInfo 结构的 DER 编码。
jwk
该密钥是一个编码为 JavaScript 对象的 JsonWebKey 字典

14.2 任务源

crypto 任务源
任务源用于 对任务进行排队,以解决或拒绝响应 SubtleCrypto 方法调用而创建的 promise。
本规范没有对 SubtleCrypto 方法调用响应的 顺序提出具体要求, 无论是在多次调用之间,还是在这些调用与来自其他 任务源的任务之间。 此任务源仅用于排队任务, 以便在加密操作完成时解决或拒绝相关 promise, 从而 防止 竞态条件

14.3 方法和参数

所有错误都会通过拒绝返回的 Promise 来异步报告。这包括 Web IDL 类型映射错误。

14.3.1 encrypt 方法

encrypt 方法返回一个新的 Promise 对象,该对象将使用 指定的 AlgorithmIdentifier 和 所提供的 CryptoKey 来加密数据。它必须按 如下方式行事:

  1. algorithmkey 分别为传递给 encrypt() 方法的 algorithmkey 参数。

  2. data获取传递给 encrypt() 方法的 data 参数所持有字节的副本所得的结果。

  3. normalizedAlgorithm规范化 算法所得的结果,其中 alg 设置为 algorithmop 设置为 "encrypt"。

  4. 如果发生错误,则返回一个以 normalizedAlgorithm 拒绝的 Promise。

  5. realm相关 realm,其属于 this

  6. promise 为一个新的 Promise。

  7. 返回 promise,并并行 执行剩余步骤。

  8. 如果以下步骤或引用的过程要求 抛出错误, 则在crypto 任务源排队 一个全局任务, 给定 realm 的全局对象, 以返回的错误拒绝 promise; 然后终止算法

  9. 如果 normalizedAlgorithmname 成员不等于 key[[algorithm]] 内部槽的 name 属性,则 抛出一个 InvalidAccessError

  10. 如果 key[[usages]] 内部槽不包含值为 "encrypt" 的条目,则 抛出一个 InvalidAccessError

  11. ciphertext 为使用 algorithmkey,并以 data 作为 plaintext, 执行由 normalizedAlgorithm 指定的 encrypt 操作所得的结果。

  12. crypto 任务源排队 一个全局任务, 给定 realm 的全局对象,以执行剩余步骤。

  13. result 为在 realm创建一个包含 ciphertextArrayBuffer 所得的结果。

  14. result 解决 promise

14.3.2 decrypt 方法

decrypt 方法返回一个新的 Promise 对象,该对象将使用指定的 AlgorithmIdentifier 和 所提供的 CryptoKey 来解密数据。它必须按 如下方式行事:

  1. algorithmkey 分别为传递给 decrypt() 方法的 algorithmkey 参数。

  2. data获取传递给 decrypt() 方法的 data 参数所持有字节的副本所得的结果。

  3. normalizedAlgorithm规范化 算法所得的结果,其中 alg 设置为 algorithmop 设置为 "decrypt"。

  4. 如果发生错误,则返回一个以 normalizedAlgorithm 拒绝的 Promise。

  5. realm相关 realm,其属于 this

  6. promise 为一个新的 Promise。

  7. 返回 promise,并并行 执行剩余步骤。

  8. 如果以下步骤或引用的过程要求 抛出错误, 则在crypto 任务源排队 一个全局任务, 给定 realm 的全局对象, 以返回的错误拒绝 promise; 然后终止算法

  9. 如果 normalizedAlgorithmname 成员不等于 key[[algorithm]] 内部槽的 name 属性,则 抛出一个 InvalidAccessError

  10. 如果 key[[usages]] 内部槽不包含值为 "decrypt" 的条目,则 抛出一个 InvalidAccessError

  11. plaintext 为使用 keyalgorithm,并以 data 作为 ciphertext, 执行由 normalizedAlgorithm 指定的 decrypt 操作所得的结果。

  12. crypto 任务源排队 一个全局任务, 给定 realm 的全局对象,以执行剩余步骤。

  13. result 为在 realm创建一个包含 plaintextArrayBuffer 所得的结果。

  14. result 解决 promise

14.3.3 sign 方法

sign 方法返回一个 新的 Promise 对象,该对象将使用指定的 AlgorithmIdentifier 和所提供的 CryptoKey 来签名数据。它必须按如下方式行事:

  1. algorithmkey 分别为传递给 sign() 方法的 algorithmkey 参数。

  2. data获取传递给 sign() 方法的 data 参数所持有字节的副本所得的结果。

  3. normalizedAlgorithm规范化 算法所得的结果,其中 alg 设置为 algorithmop 设置为 "sign"。

  4. 如果发生错误,则返回一个以 normalizedAlgorithm 拒绝的 Promise。

  5. realm相关 realm,其属于 this

  6. promise 为一个新的 Promise。

  7. 返回 promise,并并行 执行剩余步骤。

  8. 如果以下步骤或引用的过程要求 抛出错误, 则在crypto 任务源排队 一个全局任务, 给定 realm 的全局对象, 以返回的错误拒绝 promise; 然后终止算法

  9. 如果 normalizedAlgorithmname 成员不等于 key[[algorithm]] 内部槽的 name 属性,则 抛出一个 InvalidAccessError

  10. 如果 key[[usages]] 内部槽不包含值为 "sign" 的条目,则 抛出一个 InvalidAccessError

  11. signature 为使用 keyalgorithm,并以 data 作为 message, 执行由 normalizedAlgorithm 指定的 sign 操作所得的结果。

  12. crypto 任务源排队 一个全局任务, 给定 realm 的全局对象,以执行剩余步骤。

  13. result 为在 realm创建一个包含 signatureArrayBuffer 所得的结果。

  14. result 解决 promise

14.3.4 verify 方法

verify 方法返回 一个新的 Promise 对象,该对象将使用指定的 AlgorithmIdentifier 和所提供的 CryptoKey 来验证数据。它必须按如下方式行事:

  1. algorithmkey 分别为传递给 verify() 方法的 algorithmkey 参数。

  2. signature获取传递给 verify() 方法的 signature 参数所持有字节的副本所得的结果。

  3. data获取传递给 verify() 方法的 data 参数所持有字节的副本所得的结果。

  4. normalizedAlgorithm规范化 算法所得的结果,其中 alg 设置为 algorithmop 设置为 "verify"。

  5. 如果发生错误,则返回一个以 normalizedAlgorithm 拒绝的 Promise。

  6. realm相关 realm,其属于 this

  7. promise 为一个新的 Promise。

  8. 返回 promise,并并行 执行剩余步骤。

  9. 如果以下步骤或引用的过程要求 抛出错误, 则在crypto 任务源排队 一个全局任务, 给定 realm 的全局对象, 以返回的错误拒绝 promise; 然后终止算法

  10. 如果 normalizedAlgorithmname 成员不等于 key[[algorithm]] 内部槽的 name 属性,则 抛出一个 InvalidAccessError

  11. 如果 key[[usages]] 内部槽不包含值为 "verify" 的条目,则 抛出一个 InvalidAccessError

  12. result 为使用 keyalgorithmsignature,并以 data 作为 message, 执行由 normalizedAlgorithm 指定的 verify 操作所得的结果。

  13. crypto 任务源排队 一个全局任务, 给定 realm 的全局对象,以执行剩余步骤。

  14. result 解决 promise

14.3.5 digest 方法

digest 方法返回 一个新的 Promise 对象,该对象将使用指定的 AlgorithmIdentifier 对数据进行摘要计算。 它必须按如下方式行事:

  1. algorithm 为传递给 digest() 方法的 algorithm 参数。

  2. data获取传递给 digest() 方法的 data 参数所持有字节的副本所得的结果。

  3. normalizedAlgorithm规范化 算法所得的结果,其中 alg 设置为 algorithmop 设置为 "digest"。

  4. 如果发生错误,则返回一个以 normalizedAlgorithm 拒绝的 Promise。

  5. realm相关 realm,其属于 this

  6. promise 为一个新的 Promise。

  7. 返回 promise,并并行 执行剩余步骤。

  8. 如果以下步骤或引用的过程要求 抛出错误, 则在crypto 任务源排队 一个全局任务, 给定 realm 的全局对象, 以返回的错误拒绝 promise; 然后终止算法

  9. digest 为使用 algorithm,并以 data 作为 message,执行由 normalizedAlgorithm 指定的 digest 操作所得的结果。

  10. crypto 任务源排队 一个全局任务, 给定 realm 的全局对象,以执行剩余步骤。

  11. result 为在 realm创建一个包含 digestArrayBuffer 所得的结果。

  12. result 解决 promise

14.3.6 generateKey 方法

调用时,generateKey MUST 执行 以下步骤:

  1. algorithmextractableusages 分别为传递给 generateKey() 方法的 algorithmextractablekeyUsages 参数。

  2. normalizedAlgorithm规范化 算法所得的结果,其中 alg 设置为 algorithmop 设置为 "generateKey"。

  3. 如果发生错误,则返回一个以 normalizedAlgorithm 拒绝的 Promise。

  4. realm相关 realm,其属于 this

  5. promise 为一个新的 Promise。

  6. 返回 promise,并并行 执行剩余步骤。

  7. 如果以下步骤或引用的过程要求 抛出错误, 则在crypto 任务源排队 一个全局任务, 给定 realm 的全局对象, 以返回的错误拒绝 promise; 然后终止算法

  8. result 为使用 algorithmextractableusages, 执行由 normalizedAlgorithm 指定的 generate key 操作所得的结果。

  9. 如果 result 是一个 CryptoKey 对象:

    如果 result[[type]] 内部槽为 "secret" 或 "private",并且 usages 为空,则抛出一个 SyntaxError

    如果 result 是一个 CryptoKeyPair 对象:

    如果 resultprivateKey 属性的 [[usages]] 内部 槽为空序列,则 抛出一个 SyntaxError

  10. crypto 任务源排队 一个全局任务, 给定 realm 的全局对象,以执行剩余步骤。

  11. result 为在 realm 中将 result 转换为 ECMAScript Object 所得的结果, 如 [WebIDL] 中所定义。

  12. result 解决 promise

14.3.7 deriveKey 方法

调用时,deriveKey MUST 执行以下步骤:

  1. algorithmbaseKeyderivedKeyTypeextractableusages 分别为传递给 deriveKey() 方法的 algorithmbaseKeyderivedKeyTypeextractablekeyUsages 参数。

  2. normalizedAlgorithm规范化 算法所得的结果,其中 alg 设置为 algorithmop 设置为 "deriveBits"。

  3. 如果发生错误,则返回一个以 normalizedAlgorithm 拒绝的 Promise。

  4. normalizedDerivedKeyAlgorithmImport规范化 算法所得的结果,其中 alg 设置为 derivedKeyTypeop 设置为 "importKey"。

  5. 如果发生错误,则返回一个以 normalizedDerivedKeyAlgorithmImport 拒绝的 Promise。

  6. normalizedDerivedKeyAlgorithmLength规范化 算法所得的结果,其中 alg 设置为 derivedKeyTypeop 设置为 "get key length"。

  7. 如果发生错误,则返回一个以 normalizedDerivedKeyAlgorithmLength 拒绝的 Promise。

  8. realm相关 realm,其属于 this

  9. promise 为一个新的 Promise。

  10. 返回 promise,并并行 执行剩余步骤。

  11. 如果以下步骤或引用的过程要求 抛出错误, 则在crypto 任务源排队 一个全局任务, 给定 realm 的全局对象, 以返回的错误拒绝 promise; 然后终止算法

  12. 如果 normalizedAlgorithmname 成员不等于 baseKey[[algorithm]] 内部槽的 name 属性,则 抛出一个 InvalidAccessError

  13. 如果 baseKey[[usages]] 内部槽 不包含值为 "deriveKey" 的条目, 则抛出一个 InvalidAccessError

  14. length 为使用 derivedKeyType,执行由 normalizedDerivedKeyAlgorithmLength 指定的 get key length 算法所得的结果。

  15. secret 为使用 keyalgorithmlength, 执行由 normalizedAlgorithm 指定的 derive bits 操作所得的结果。

  16. result 为使用 "raw" 作为 formatsecret 作为 keyDataderivedKeyType 作为 algorithm,并使用 extractableusages,执行由 normalizedDerivedKeyAlgorithmImport 指定的 import key 操作所得的结果。

  17. 如果 result[[type]] 内部槽为 "secret" 或 "private",并且 usages 为空,则抛出一个 SyntaxError

  18. result[[extractable]] 内部 槽设置为 extractable

  19. result[[usages]] 内部 槽设置为 usages规范化值

  20. crypto 任务源排队 一个全局任务, 给定 realm 的全局对象,以执行剩余步骤。

  21. result 为在 realm 中将 result 转换为 ECMAScript Object 所得的结果, 如 [WebIDL] 中所定义。

  22. result 解决 promise

14.3.8 deriveBits 方法

调用时,deriveBits MUST 执行以下步骤:

  1. algorithmbaseKeylength 分别为传递给 deriveBits() 方法的 algorithmbaseKeylength 参数。

  2. normalizedAlgorithm规范化 算法所得的结果,其中 alg 设置为 algorithmop 设置为 "deriveBits"。

  3. 如果发生错误,则返回一个以 normalizedAlgorithm 拒绝的 Promise。

  4. realm相关 realm,其属于 this

  5. promise 为一个新的 Promise。

  6. 返回 promise,并并行 执行剩余步骤。

  7. 如果以下步骤或引用的过程要求 抛出错误, 则在crypto 任务源排队 一个全局任务, 给定 realm 的全局对象, 以返回的错误拒绝 promise; 然后终止算法

  8. 如果 normalizedAlgorithmname 成员不等于 baseKey[[algorithm]] 内部 槽的 name 属性,则 抛出一个 InvalidAccessError

  9. 如果 baseKey[[usages]] 内部槽 不包含值为 "deriveBits" 的条目, 则抛出一个 InvalidAccessError

  10. bits 为使用 baseKeyalgorithmlength,执行由 normalizedAlgorithm 指定的 derive bits 操作所得的结果。

  11. crypto 任务源排队 一个全局任务, 给定 realm 的全局对象,以执行剩余步骤。

  12. result 为在 realm创建一个包含 bitsArrayBuffer 所得的结果。

  13. result 解决 promise

14.3.9 importKey 方法

调用时,importKey 方法 MUST 执行 以下步骤:

  1. formatalgorithmextractableusages 分别为传递给 importKey() 方法的 formatalgorithmextractablekeyUsages 参数。

  2. 如果 format 等于字符串 "raw"、 "pkcs8" 或 "spki":
    1. 如果传递给 importKey() 方法的 keyData 参数是 JsonWebKey 字典,则抛出一个 TypeError

    2. keyData获取 传递给 importKey() 方法的 keyData 参数所持有字节的副本所得的结果。

    如果 format 等于字符串 "jwk":
    1. 如果传递给 importKey() 方法的 keyData 参数不是 JsonWebKey 字典,则抛出一个 TypeError

    2. keyData 为传递给 importKey() 方法的 keyData 参数。

  3. normalizedAlgorithm规范化 算法所得的结果,其中 alg 设置为 algorithmop 设置为 "importKey"。

  4. 如果发生错误,则返回一个以 normalizedAlgorithm 拒绝的 Promise。

  5. realm相关 realm,其属于 this

  6. promise 为一个新的 Promise。

  7. 返回 promise,并并行 执行剩余步骤。

  8. 如果以下步骤或引用的过程要求 抛出错误, 则在crypto 任务源排队 一个全局任务, 给定 realm 的全局对象, 以返回的错误拒绝 promise; 然后终止算法

  9. result 为使用 keyDataalgorithmformatextractableusages, 执行由 normalizedAlgorithm 指定的 import key 操作所得的 CryptoKey 对象。

  10. 如果 result[[type]] 内部槽为 "secret" 或 "private",并且 usages 为空,则抛出一个 SyntaxError

  11. result[[extractable]] 内部 槽设置为 extractable

  12. result[[usages]] 内部 槽设置为 usages规范化值

  13. crypto 任务源排队 一个全局任务, 给定 realm 的全局对象,以执行剩余步骤。

  14. result 为在 realm 中将 result 转换为 ECMAScript Object 所得的结果, 如 [WebIDL] 中所定义。

  15. result 解决 promise

为了互操作性,鼓励支持 "raw" 密钥格式。 Web 开发者应查阅测试套件,以获取 关于实现对其他密钥格式支持情况的详细信息。

对于结构化密钥格式 "spki"、"pkcs8" 和 "jwk", 在某个算法的密钥 导入过程中未被显式引用的字段会被忽略。

14.3.10 exportKey 方法

调用时,exportKey 方法 MUST 执行 以下步骤:

  1. formatkey 分别为传递给 exportKey() 方法的 formatkey 参数。

  2. realm相关 realm,其属于 this

  3. promise 为一个新的 Promise。

  4. 返回 promise,并并行 执行剩余步骤。

  5. 如果以下步骤或引用的过程要求 抛出错误, 则在crypto 任务源排队 一个全局任务, 给定 realm 的全局对象, 以返回的错误拒绝 promise; 然后终止算法

  6. 如果 key[[algorithm]] 内部 槽的 name 成员未标识一个支持 export key 操作的 已注册算法, 则抛出一个 NotSupportedError

  7. 如果 key[[extractable]] 内部 槽为 false,则抛出一个 InvalidAccessError

  8. result 为使用 keyformat, 执行由 key[[algorithm]] 内部槽指定的 export key 操作所得的结果。

  9. crypto 任务源排队 一个全局任务, 给定 realm 的全局对象,以执行剩余步骤。

  10. 如果 format 等于字符串 "raw"、 "pkcs8" 或 "spki":
    result 为在 realm创建一个包含 resultArrayBuffer 所得的结果。
    如果 format 等于字符串 "jwk":
    result 为在 realm 中将 result 转换为 ECMAScript Object 所得的结果, 如 [WebIDL] 中所定义。
  11. result 解决 promise

为了互操作性,鼓励支持 "raw" 密钥格式。 Web 开发者应查阅测试套件,以获取 关于实现对其他密钥格式支持情况的详细信息。

14.3.11 wrapKey 方法

调用时,wrapKey 方法 MUST 执行 以下步骤:

  1. formatkeywrappingKeyalgorithm 分别为传递给 wrapKey() 方法的 formatkeywrappingKeywrapAlgorithm 参数。

  2. normalizedAlgorithm规范化 算法所得的结果,其中 alg 设置为 algorithmop 设置为 "wrapKey"。

  3. 如果发生错误,则令 normalizedAlgorithm规范化 算法所得的结果,其中 alg 设置为 algorithmop 设置为 "encrypt"。

  4. 如果发生错误,则返回一个以 normalizedAlgorithm 拒绝的 Promise。

  5. realm相关 realm,其属于 this

  6. promise 为一个新的 Promise。

  7. 返回 promise,并并行 执行剩余步骤。

  8. 如果以下步骤或引用的过程要求 抛出错误, 则在crypto 任务源排队 一个全局任务, 给定 realm 的全局对象, 以返回的错误拒绝 promise; 然后终止算法

  9. 如果 normalizedAlgorithmname 成员不等于 wrappingKey[[algorithm]] 内部 槽的 name 属性,则 抛出一个 InvalidAccessError

  10. 如果 wrappingKey[[usages]] 内部槽 不包含值为 "wrapKey" 的条目, 则抛出一个 InvalidAccessError

  11. 如果由 key[[algorithm]] 内部 槽标识的算法不支持 export key 操作,则抛出一个 NotSupportedError

  12. 如果 key[[extractable]] 内部 槽为 false,则抛出一个 InvalidAccessError

    因为 wrapKey 方法实际上会导出密钥,所以只有标记为 extractable 的密钥才可以被包装。特别是,这意味着此 API 无法使用 ext JWK 成员创建一个标记为不可提取的已包装 JWK 密钥。

    但是,unwrapKey 方法确实支持 ext JWK 成员, 因此,在其他地方(例如由服务器)创建的已包装不可提取密钥 可以 使用此 API 解包。

  13. exportedKey 为使用 keyformat, 执行由 key[[algorithm]] 内部 槽指定的 export key 操作所得的结果。

  14. 如果 format 等于字符串 "raw"、 "pkcs8" 或 "spki":
    bytesexportedKey
    如果 format 等于字符串 "jwk":
    1. json 为将 exportedKey 表示为 符合 JSON 语法的 UTF-16 字符串所得的结果;例如,通过在新全局对象上下文中执行 [ECMA-262] 中指定的 JSON.stringify 算法。

    2. bytes 为对 json 进行UTF-8 编码 所得的结果。

    某些算法的密钥包装操作会对载荷 大小施加限制。例如,AES-KW 要求载荷长度为 8 字节的倍数, 而 RSA-OAEP 会对长度施加限制。对于在给定密钥的序列化方面 提供灵活性的密钥格式(例如 JWK), 实现可以选择使序列化适配 包装算法的约束。这就是为什么没有规范性要求 JSON.stringify, 否则它将禁止实现引入额外的 填充。

  15. 如果 normalizedAlgorithm 支持 wrap key 操作:

    result 为使用 algorithmwrappingKey 作为 key,并以 bytes 作为 plaintext,执行由 normalizedAlgorithm 指定的 wrap key 操作所得的结果。

    否则,如果 normalizedAlgorithm 支持 encrypt 操作:

    result 为使用 algorithmwrappingKey 作为 key,并以 bytes 作为 plaintext,执行由 normalizedAlgorithm 指定的 encrypt 操作所得的结果。

    否则:
    抛出一个 NotSupportedError
  16. crypto 任务源排队 一个全局任务, 给定 realm 的全局对象,以执行剩余步骤。

  17. result 为在 realm创建一个包含 resultArrayBuffer 所得的结果。

  18. result 解决 promise

为了互操作性,鼓励支持 "raw" 密钥格式。 Web 开发者应查阅测试套件,以获取 关于实现对其他密钥格式支持情况的详细信息。

14.3.12 unwrapKey 方法

调用时,unwrapKey 方法 MUST 执行以下步骤:

  1. formatunwrappingKeyalgorithmunwrappedKeyAlgorithmextractableusages 分别为传递给 unwrapKey() 方法的 formatunwrappingKeyunwrapAlgorithmunwrappedKeyAlgorithmextractablekeyUsages 参数。

  2. wrappedKey获取传递给 unwrapKey() 方法的 wrappedKey 参数所持有字节的副本所得的结果。

  3. normalizedAlgorithm规范化 算法所得的结果,其中 alg 设置为 algorithmop 设置为 "unwrapKey"。

  4. 如果发生错误,则令 normalizedAlgorithm规范化 算法所得的结果,其中 alg 设置为 algorithmop 设置为 "decrypt"。

  5. 如果发生错误,则返回一个以 normalizedAlgorithm 拒绝的 Promise。

  6. normalizedKeyAlgorithm规范化算法所得的结果,其中 alg 设置为 unwrappedKeyAlgorithmop 设置 为 "importKey"。

  7. 如果发生错误,则返回一个以 normalizedKeyAlgorithm 拒绝的 Promise。

  8. realm相关 realm,其属于 this

  9. promise 为一个新的 Promise。

  10. 返回 promise,并并行 执行剩余步骤。

  11. 如果以下步骤或引用的过程要求 抛出错误, 则在crypto 任务源排队 一个全局任务, 给定 realm 的全局对象, 以返回的错误拒绝 promise; 然后终止算法

  12. 如果 normalizedAlgorithmname 成员不等于 unwrappingKey[[algorithm]] 内部 槽的 name 属性,则 抛出一个 InvalidAccessError

  13. 如果 unwrappingKey[[usages]] 内部槽 不包含值为 "unwrapKey" 的条目,则抛出一个 InvalidAccessError

  14. 如果 normalizedAlgorithm 支持 unwrap key 操作:
    bytes 为使用 algorithmunwrappingKey 作为 key,并以 wrappedKey 作为 ciphertext,执行由 normalizedAlgorithm 指定的 unwrap key 操作所得的结果。
    否则,如果 normalizedAlgorithm 支持 decrypt 操作:
    bytes 为使用 algorithmunwrappingKey 作为 key,并以 wrappedKey 作为 ciphertext,执行由 normalizedAlgorithm 指定的 decrypt 操作所得的结果。
    否则:
    抛出一个 NotSupportedError
  15. 如果 format 等于字符串 "raw"、 "pkcs8" 或 "spki":
    keybytes
    如果 format 等于字符串 "jwk":
    key 为以 bytes 作为要解析的 data,执行 解析 JWK算法所得的结果。
  16. result 为使用 unwrappedKeyAlgorithm 作为 algorithmformatusagesextractable,并以 key 作为 keyData,执行由 normalizedKeyAlgorithm 指定的 import key 操作所得的结果。

  17. 如果 result[[type]] 内部槽为 "secret" 或 "private",并且 usages 为空,则抛出一个 SyntaxError

  18. result[[extractable]] 内部 槽设置为 extractable

  19. result[[usages]] 内部 槽设置为 usages规范化值

  20. crypto 任务源排队 一个全局任务, 给定 realm 的全局对象,以执行剩余步骤。

  21. result 为在 realm 中将 result 转换为 ECMAScript Object 所得的结果, 如 [WebIDL] 中所定义。

  22. result 解决 promise

为了互操作性,鼓励支持 "raw" 密钥格式。 Web 开发者应查阅测试套件,以获取 关于实现对其他密钥格式支持情况的详细信息。

14.4 异常

SubtleCrypto 接口的方法通过 使用 ECMAScript [ECMA-262] 或 DOMException 中定义的预定义异常拒绝返回的 promise 来返回错误。使用以下 预定义异常:TypeError。使用 [DOM] 中的以下 DOMException 类型:

名称 描述
NotSupportedError 不支持该算法
SyntaxError 缺少必需参数或参数超出范围
InvalidAccessError 所请求的操作对所提供的密钥无效
DataError 提供给操作的数据不满足要求
OperationError 操作因操作特定的原因而失败

当本规范要求 抛出错误时,用户 代理必须按照 [WebIDL] 中所述 抛出错误。当这发生在子算法中时, 这会导致该子算法以及所有祖先算法的执行终止, 直到到达某个显式描述了捕获异常过程的算法为止。 被抛出的错误对象应与 相关 realm,其属于 this

15. JsonWebKey 字典

WebIDLdictionary RsaOtherPrimesInfo {
  // The following fields are defined in Section 6.3.2.7 of JSON Web Algorithms
  DOMString r;
  DOMString d;
  DOMString t;
};

dictionary JsonWebKey {
  // The following fields are defined in Section 3.1 of JSON Web Key
  DOMString kty;
  DOMString use;
  sequence<DOMString> key_ops;
  DOMString alg;

  // The following fields are defined in JSON Web Key Parameters Registration
  boolean ext;

  // The following fields are defined in Section 6 of JSON Web Algorithms
  DOMString crv;
  DOMString x;
  DOMString y;
  DOMString d;
  DOMString n;
  DOMString e;
  DOMString p;
  DOMString q;
  DOMString dp;
  DOMString dq;
  DOMString qi;
  sequence<RsaOtherPrimesInfo> oth;
  DOMString k;
};

JsonWebKey 字典提供了一种表示 和交换由 JSON Web Key [JWK] 结构表示的加密密钥的方法,同时允许在 Web Cryptography API 应用中进行原生且高效的使用。

RsaOtherPrimesInfo 的成员定义于 JSON Web Algorithms 第 6.3.2.7 节。

16. BigInteger

WebIDLtypedef Uint8Array BigInteger;

BigInteger typedef 是一个 Uint8Array, 其 以大端序保存任意大小的无符号整数。从 API 读取的值SHALL具有最小类型化数组长度(即至多 7 个前导零 位, 但值 0 应具有 8 位长度)。API SHALL 接受 具有任意数量前导零位的值,包括表示零的空数组。

由于整数是无符号的,最高有效位 不是符号位。实现者在映射到期望有符号整数的 大整数实现时应谨慎。

17. CryptoKeyPair 字典

WebIDLdictionary CryptoKeyPair {
  CryptoKey publicKey;
  CryptoKey privateKey;
};

CryptoKeyPair 字典表示一个 非对称密钥对,由公钥(publicKey)和私钥 (privateKey)组成。

18. 算法

18.1 概述

本节是非规范性的。

除了通过 SubtleCrypto 接口提供执行加密操作的 通用接口之外,本规范 还提供了作者可能希望使用、且用户代理可以选择实现的各种算法的描述。 这包括一组常用部署的 对称和非对称算法、密钥派生机制,以及用于包装 和解包密钥的方法。此外,本规范定义了一个过程,允许其他 规范引入额外的加密算法。

18.2 概念

18.2.1 命名

为与 Web Cryptography API 一起使用而定义的每个加密算法 MUST 具有一个唯一名称,称为其 已识别算法名称,使得没有 其他规范为 Web Cryptography API 的使用定义相同的不区分大小写字符串。

18.2.2 支持的操作

为与 Web Cryptography API 一起使用而定义的每个加密算法都有一个 支持的操作列表,它们是一组 由 SubtleCrypto 接口调用以执行所需加密操作的子算法。本规范 使用以下操作:

  • encrypt
  • decrypt
  • sign
  • verify
  • digest
  • deriveBits
  • wrapKey
  • unwrapKey
  • generateKey
  • importKey
  • exportKey
  • get key length

如果给定的算法规范没有列出某个特定操作为受支持, 或显式列出某个操作为不受支持,则用户代理 MUST 表现得好像调用该子算法 抛出了 NotSupportedError。

18.2.3 规范化

为与 Web Cryptography API 一起使用而定义的每个加密算法 MUST 针对每个支持的 操作,定义用于算法规范化的 IDL 类型,以及 子算法返回值的 IDL 类型或类型集合。

18.3 规范约定

本规范中的每个加密算法定义都采用以下 规范约定。标题为 "Registration" 的小节将包括 已识别算法名称。此外,它 包括一个表,该表将把每个支持的 操作列为行,并由 Operation 列标识。给定行中 Parameters 列的内容 将包含用于该操作算法规范化的 IDL 类型, 而该行中 Result 列的内容 指示执行该支持的操作后所得的 IDL 类型。

如果一致的用户代理实现某个算法,则它 MUST 实现所有 支持的操作,并且 MUST 返回指定的 IDL 类型。

此外,在初始化时,一致的用户代理必须对每个 支持的操作执行定义算法步骤, 按指示注册其 IDL 参数类型。

除非另有说明,由本规范中定义的操作创建的对象 应与 相关 realm 关联,其属于 this

18.4 算法规范化

18.4.1 描述

本节是非规范性的。

AlgorithmIdentifier typedef 允许 算法被指定为 DOMString 或一个 对象。使用 DOMString 是为了允许 作者用 简写来表示没有参数的算法(例如 SHA-1)。 使用对象是为了允许指定 Algorithm(或适当的 子类),其 包含对象的所有关联参数。

因此,有必要定义将 AlgorithmIdentifier 转换为可与此 API 一起使用的适当 字典的算法。该算法必须是可扩展的,以允许添加新的 加密算法,并且必须是一致的,以便 Web IDL 类型映射可以在任何控制 返回给调用脚本之前发生,否则可能允许 参数或脚本环境发生变异。

18.4.2 内部状态对象

本规范使用一个内部对象 supportedAlgorithms。该内部对象 不暴露给应用。

由于该值不暴露给应用,因此未指定其确切类型。 仅要求它表现为键/值对的关联容器,其中 键的比较以区分大小写的方式执行。

此内部对象的初始内容如下:

  1. 对于支持的操作列表中的每个值 v, 将内部对象 supportedAlgorithmsv 键设置为新的关联容器。

18.4.3 定义算法

定义算法算法由规范作者使用, 用于指示用户代理应如何为特定算法规范化参数。 其输入为算法名称 alg(表示为 DOMString)、 操作名称 op(表示为 DOMString),以及所需的 IDL 字典类型 type。该算法行为如下:

  1. registeredAlgorithms 为存储在 supportedAlgorithmsop 键处的关联容器。
  2. registeredAlgorithmsalg 键设置为 IDL 字典 类型 type

18.4.4 规范化算法

规范化算法算法定义了 在 Web IDL 转换发生之后,将输入强制转换为目标 IDL 字典类型的过程。 它被设计为可扩展,以允许未来规范 定义额外算法,同时也安全适用于 Promise。其输入为 操作名称 op 和一个 AlgorithmIdentifier alg。其 输出为 IDL 字典类型或错误。其行为如下:

如果 alg 是 DOMString 的实例:

返回运行规范化算法算法所得的结果,其中 alg 设置为一个新的 Algorithm 字典,其 name 属性为 alg,并且 op 设置为 op

如果 alg 是对象:
  1. registeredAlgorithms 为存储在 supportedAlgorithmsop 键处的关联容器。
  2. initialAlg 为将 alg 表示的 ECMAScript 对象转换为 IDL 字典类型 Algorithm 所得的结果,如 [WebIDL] 中所定义。
  3. 如果发生错误,则返回该错误并终止此算法。
  4. algNameinitialAlgname 属性的值。
  5. 如果 registeredAlgorithms 包含一个键,该键与 algName不区分大小写字符串匹配:
    1. algName 设置为匹配键的值。

    2. desiredType 为存储在 registeredAlgorithmsalgName 处的 IDL 字典类型。

    否则:
    返回一个新的 NotSupportedError 并终止此算法。
  6. normalizedAlgorithm 为将 alg 表示的 ECMAScript 对象转换为 IDL 字典类型 desiredType 所得的结果,如 [WebIDL] 中所定义。
  7. normalizedAlgorithmname 属性设置为 algName
  8. 如果发生错误,则返回该错误并终止此算法。
  9. dictionaries 为一个列表,由 IDL 字典类型 desiredTypedesiredType 的所有继承字典组成, 按从最不派生到最派生的顺序排列。
  10. dictionaries 中的每个字典 dictionary

    1. dictionary 上声明的每个字典成员 member, 按顺序:

      1. keymember 的标识符。
      2. idlValuenormalizedAlgorithm 上键名为 key 的字典成员的值。
      3. 如果 member 的类型为 BufferSource 且存在:
        normalizedAlgorithm 上键名为 key 的字典成员设置为 获取其持有字节副本 idlValue 所得的结果,以替换当前值。
        如果 member 的类型为 HashAlgorithmIdentifier
        normalizedAlgorithm 上键名为 key 的字典成员设置为 规范化 算法所得的结果, 其中 alg 设置为 idlValue,并且 op 设置为 "digest"。
        如果 member 的类型为 AlgorithmIdentifier
        normalizedAlgorithm 上键名为 key 的字典成员设置为 规范化 算法所得的结果, 其中 alg 设置为 idlValue,并且 op 设置为由标识 algName 的算法所属规范 定义的操作。
      4. 如果发生错误,则返回该错误并终止此算法。
  11. 返回 normalizedAlgorithm

18.5 建议

本节是非规范性的。

18.5.1 面向作者

由于此 API 旨在可扩展,以跟上密码学领域的未来发展, 因此没有要求一致的用户代理必须实现的算法。 因此,作者应检查当前哪些算法被推荐并由实现支持。

安全性考虑中所强调的, 即使某些加密算法在某一目的下可能被认为很强, 用于另一目的时也可能不足。因此,作者在发明新的 加密协议之前应极其谨慎。

此外,本规范包括若干算法,其默认 用法可能导致加密漏洞。虽然这些问题可以被 缓解,例如通过与本规范提供的额外算法组合和合成, 作者在使用给定算法之前仍应谨慎行事并查阅 相关密码学文献。本规范中包含 算法并不表示它们适合任何 或所有目的,而仅仅是提供一个规范,说明一致的用户代理 如果选择实现该算法时,必须如何实现给定算法。

18.5.2 面向实现者

为了促进开发者的互操作性,本规范包括一个 建议算法列表。这些算法被认为是在撰写本文时实践中使用最广泛的 算法,因此为本规范的初始实现提供了良好的 起点。建议的算法为:

19. 算法概述

本节是非规范性的。

下表包含本规范中描述的算法概述,以及该算法可与之一起使用的 SubtleCrypto 方法集合。为了使 某个算法可与某个方法一起使用,必须在算法规范中定义 该方法的过程中所定义的相应 操作或操作集合。 请注意,方法到底层 操作的这种映射不是一对一的:

应用开发者和脚本作者不应将此表解释为 推荐使用特定算法。相反,它只是记录了支持哪些 方法。作者应参考本文档的面向作者的安全 考虑一节,以更好地理解使用某些 算法时可能产生的风险和顾虑。

算法名称 encrypt decrypt sign verify digest generateKey deriveKey deriveBits importKey exportKey wrapKey unwrapKey
RSASSA-PKCS1-v1_5
RSA-PSS
RSA-OAEP
ECDSA
ECDH
Ed25519
X25519
AES-CTR
AES-CBC
AES-GCM
AES-KW
HMAC
SHA-1
SHA-256
SHA-384
SHA-512
HKDF
PBKDF2

20. RSASSA-PKCS1-v1_5

20.1 描述

本节是非规范性的。

"RSASSA-PKCS1-v1_5" 算法标识符用于执行 [RFC3447] 中指定的 RSASSA-PKCS1-v1_5 算法的签名和验证, 并使用本规范中定义的 SHA 哈希函数。

其他 规范 可以指定将其他哈希算法与 RSASSA-PKCS1-v1_5 一起使用。此类 规范必须定义其他哈希算法的摘要操作,以及 RSASSA-PKCS1-v1_5 的 密钥导入步骤密钥 导出步骤

20.2 注册

此算法的已识别算法名称为 "RSASSA-PKCS1-v1_5"。

操作 参数 结果
sign 字节 序列
verify boolean
generateKey RsaHashedKeyGenParams CryptoKeyPair
importKey RsaHashedImportParams CryptoKey
exportKey object

20.3 RsaKeyGenParams 字典

WebIDLdictionary RsaKeyGenParams : Algorithm {
  required [EnforceRange] unsigned long modulusLength;
  required BigInteger publicExponent;
};

modulusLength 成员包含 RSA 模数的长度, 以位为单位。

publicExponent 成员包含 RSA 公共 指数。

20.4 RsaHashedKeyGenParams 字典

WebIDLdictionary RsaHashedKeyGenParams : RsaKeyGenParams {
  required HashAlgorithmIdentifier hash;
};

hash 成员表示要 使用的哈希算法。

20.5 RsaKeyAlgorithm 字典

WebIDLdictionary RsaKeyAlgorithm : KeyAlgorithm {
  required unsigned long modulusLength;
  required BigInteger publicExponent;
};

modulusLength 成员包含 RSA 模数的长度, 以位为单位。

publicExponent 成员包含 RSA 公共 指数。

20.6 RsaHashedKeyAlgorithm 字典

WebIDLdictionary RsaHashedKeyAlgorithm : RsaKeyAlgorithm {
  required KeyAlgorithm hash;
};

hash 成员描述与 此密钥一起使用的哈希算法。

20.7 RsaHashedImportParams 字典

WebIDLdictionary RsaHashedImportParams : Algorithm {
  required HashAlgorithmIdentifier hash;
};

hash 成员描述要 使用的哈希算法。

20.8 操作

20.8.1 签名

  1. 如果 key[[type]] 内部槽不是 "private",则 抛出一个 InvalidAccessError

  2. 执行 [RFC3447] 第 8.2 节中定义的签名生成操作,其中使用 key[[handle]] 内部槽表示的密钥 作为签名者的私钥,以 message 作为 M,并使用 key[[algorithm]] 内部 槽的 hash 属性中指定的哈希函数, 作为 EMSA-PKCS1-v1_5 编码方法的 Hash 选项。

  3. 如果执行该操作导致错误, 则抛出一个 OperationError

  4. signature 为执行该操作所得的值 S

  5. 返回 signature

20.8.2 验证

  1. 如果 key[[type]] 内部槽不是 "public",则抛出一个 InvalidAccessError

  2. 执行 [RFC3447] 第 8.2 节中定义的签名验证操作,其中使用 key[[handle]] 内部槽表示的密钥 作为签名者的 RSA 公钥,以 message 作为 M,并以 signature 作为 S,并使用 key[[algorithm]] 内部 槽的 hash 属性中指定的 哈希函数作为 EMSA-PKCS1-v1_5 编码方法的 Hash 选项。

  3. result 为一个 boolean;如果该操作的 结果为 "valid signature",则其值为 true,否则其值 为 false。

  4. 返回 result

20.8.3 生成密钥

  1. 如果 usages 包含不是 "sign" 或 "verify" 的条目, 则抛出一个 SyntaxError

  2. 按 [RFC3447] 中的定义生成一个 RSA 密钥对,其 RSA 模数长度等于 normalizedAlgorithmmodulusLength 属性,RSA 公共指数等于 normalizedAlgorithmpublicExponent 属性。

  3. 如果密钥对生成失败, 则抛出一个 OperationError

  4. algorithm 为一个新的 RsaHashedKeyAlgorithm 字典。

  5. algorithmname 属性设置为 "RSASSA-PKCS1-v1_5"。

  6. algorithmmodulusLength 属性设置为等于 normalizedAlgorithmmodulusLength 属性。

  7. algorithmpublicExponent 属性设置为等于 normalizedAlgorithmpublicExponent 属性。

  8. algorithmhash 属性 设置为等于 normalizedAlgorithmhash 成员。

  9. publicKey 为一个新的 CryptoKey, 表示所生成密钥对的公钥。

  10. publicKey[[type]] 内部槽设置为 "public"

  11. publicKey[[algorithm]] 内部 槽设置为 algorithm

  12. publicKey[[extractable]] 内部 槽设置为 true。

  13. publicKey[[usages]] 内部槽 设置为 usages[ "verify" ]用法交集

  14. privateKey 为一个新的 CryptoKey, 表示所生成密钥对的私钥。

  15. privateKey[[type]] 内部槽设置为 "private"

  16. privateKey[[algorithm]] 内部 槽设置为 algorithm

  17. privateKey[[extractable]] 内部 槽设置为 extractable

  18. privateKey[[usages]] 内部槽 设置为 usages[ "sign" ]用法交集

  19. result 为一个新的 CryptoKeyPair 字典。

  20. resultpublicKey 属性 设置为 publicKey

  21. resultprivateKey 属性 设置为 privateKey

  22. 返回 result

20.8.4 导入密钥

  1. keyData 为要导入的密钥数据。

  2. 如果 format 为 "spki":
    1. 如果 usages 包含不是 "verify" 的条目, 则抛出一个 SyntaxError

    2. spki 为对 keyData 运行 解析 subjectPublicKeyInfo 算法所得的结果。

    3. 如果解析过程中发生错误, 则抛出一个 DataError

    4. 如果 spkialgorithm AlgorithmIdentifier 字段的 algorithm 对象标识符字段 不等于 [RFC3447] 中定义的 rsaEncryption 对象标识符,则抛出一个 DataError

    5. publicKey 为执行解析 ASN.1 结构 算法所得的结果,其中 dataspkisubjectPublicKeyInfo 字段, structure 为 [RFC3447] 第 A.1.1 节中指定的 RSAPublicKey 结构, 并将 exactData 设置为 true。

    6. 如果解析过程中发生错误,或者可以确定 publicKey 不是符合 [RFC3447] 的有效公钥,则抛出一个 DataError

    7. key 为一个新的 CryptoKey, 它表示由 publicKey 标识的 RSA 公钥。

    8. key[[type]] 内部槽 设置为 "public"

    如果 format 为 "pkcs8":
    1. 如果 usages 包含不是 "sign" 的条目, 则抛出一个 SyntaxError

    2. privateKeyInfo 为对 keyData 运行 解析 privateKeyInfo 算法所得的结果。

    3. 如果解析过程中发生错误, 则抛出一个 DataError

    4. 如果 privateKeyInfoprivateKeyAlgorithm PrivateKeyAlgorithm 字段的 algorithm 对象标识符字段不等于 [RFC3447] 中定义的 rsaEncryption 对象标识符, 则抛出一个 DataError

    5. rsaPrivateKey 为执行解析 ASN.1 结构 算法所得的结果,其中 dataprivateKeyInfoprivateKey 字段, structure 为 [RFC3447] 第 A.1.2 节中指定的 RSAPrivateKey 结构, 并将 exactData 设置为 true。

    6. 如果解析过程中发生错误,或者 rsaPrivateKey 不是 符合 [RFC3447] 的有效 RSA 私钥,则抛出一个 DataError

    7. key 为一个新的 CryptoKey, 它表示由 rsaPrivateKey 标识的 RSA 私钥。

    8. key[[type]] 内部槽 设置为 "private"

    如果 format 为 "jwk":
    1. 如果 keyData 是一个 JsonWebKey 字典:

      jwk 等于 keyData

      否则:

      抛出一个 DataError

    2. 如果 jwkd 字段存在,且 usages 包含不是 "sign" 的条目;或者,如果 jwkd 字段 不存在,且 usages 包含不是 "verify" 的条目, 则抛出一个 SyntaxError

    3. 如果 jwkkty 字段 与 "RSA" 不是区分大小写的字符串匹配, 则抛出一个 DataError

    4. 如果 usages 非空,且 jwkuse 字段存在,并且 与 "sig" 不是区分大小写的字符串匹配, 则抛出一个 DataError

    5. 如果 jwkkey_ops 字段存在,且 根据 JSON Web Key [JWK] 的要求无效,或 不包含所有指定的 usages 值, 则抛出一个 DataError

    6. 如果 jwkext 字段存在且 值为 false,并且 extractable 为 true, 则抛出一个 DataError

    7. hash 为一个初始值为 undefined 的字符串。

    8. 如果 jwkalg 字段 不存在:

      hash 为 undefined。

      如果 alg 字段 等于字符串 "RS1":

      hash 为字符串 "SHA-1"。

      如果 alg 字段 等于字符串 "RS256":

      hash 为字符串 "SHA-256"。

      如果 alg 字段 等于字符串 "RS384":

      hash 为字符串 "SHA-384"。

      如果 alg 字段 等于字符串 "RS512":

      hash 为字符串 "SHA-512"。

      否则:
      1. 执行由 其他适用 规范定义的任何 密钥 导入步骤,传入 formatjwk 并获得 hash

      2. 如果发生错误或不存在 适用 规范, 则抛出 一个 DataError

    9. 如果 hash 不是 undefined:
      1. normalizedHash规范化 算法所得的结果, 其中 alg 设置为 hash,并将 op 设置 为 digest

      2. 如果 normalizedHash 不等于 normalizedAlgorithmhash 成员,则抛出 一个 DataError

    10. 如果 jwkd 字段存在:
      1. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.3.2 节的要求, 则抛出 一个 DataError

      2. privateKey 表示 按照 JSON Web Algorithms [JWA] 第 6.3.2 节解释 jwk 所标识的 RSA 私钥。

      3. 如果 privateKey 不是符合 [RFC3447] 的有效 RSA 私钥, 则抛出 一个 DataError

      4. key 为一个新的 CryptoKey 对象,它表示 privateKey

      5. key[[type]] 内部槽设置为 "private"

      否则:
      1. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.3.1 节的要求, 则抛出 一个 DataError

      2. publicKey 表示 按照 JSON Web Algorithms [JWA] 第 6.3.1 节解释 jwk 所标识的 RSA 公钥。

      3. 如果可以确定 publicKey 不是符合 [RFC3447] 的有效 RSA 公钥, 则抛出 一个 DataError

      4. key 为一个新的 CryptoKey, 表示 publicKey

      5. key[[type]] 内部槽设置为 "public"

    否则:
    抛出一个 NotSupportedError
  3. algorithm 为一个新的 RsaHashedKeyAlgorithm 字典。

  4. algorithmname 属性设置为 "RSASSA-PKCS1-v1_5"

  5. algorithmmodulusLength 属性设置为 RSA 公共模数的长度,以位为单位。

  6. algorithmpublicExponent 属性设置为 RSA 公共指数的 BigInteger 表示。

  7. algorithmhash 属性设置为 normalizedAlgorithmhash 成员。

  8. key[[algorithm]] 内部 槽设置为 algorithm

  9. 返回 key

20.8.5 导出密钥

  1. key 为要导出的密钥。

  2. 如果无法访问由 key[[handle]] 内部槽表示的底层加密密钥材料, 则抛出一个 OperationError

  3. 如果 format 为 "spki"
    1. 如果 key[[type]] 内部槽 不是 "public",则抛出一个 InvalidAccessError

    2. data 为 [RFC5280] 中定义的 SubjectPublicKeyInfo ASN.1 结构的一个实例,并具有以下属性:

      • algorithm 字段设置为具有以下 属性的 AlgorithmIdentifier ASN.1 类型:

        • algorithm 字段设置为 [RFC3447] 中定义的 OID rsaEncryption

        • params 字段设置为 ASN.1 类型 NULL。

      • subjectPublicKey 字段设置为 对 [RFC3447] 附录 A.1.1 中定义的 RSAPublicKey ASN.1 类型进行 DER 编码所得的结果,该类型 表示由 key[[handle]] 内部槽表示的 RSA 公钥

    3. result 为对 data 进行 DER 编码所得的结果。

    如果 format 为 "pkcs8":
    1. 如果 key[[type]] 内部槽 不是 "private",则抛出一个 InvalidAccessError

    2. data 为 [RFC5208] 中定义的 PrivateKeyInfo ASN.1 结构的一个实例,并具有以下属性:

      • version 字段设置为 0

      • privateKeyAlgorithm 字段设置为具有以下属性的 PrivateKeyAlgorithmIdentifier ASN.1 类型:

        • algorithm 字段设置为 [RFC3447] 中定义的 OID rsaEncryption

        • params 字段设置为 ASN.1 类型 NULL。

      • privateKey 字段设置为对 [RFC3447] 附录 A.1.2 中定义的 RSAPrivateKey ASN.1 类型进行 DER 编码所得的结果, 该类型表示由 key[[handle]] 内部槽表示的 RSA 私钥

        [RFC5208] 在第 5 节中规定,此字段的编码应进行 BER 编码(作为 “例如”)。然而,为了避免要求 WebCrypto 实现 支持 BER 编码和 BER 解码,只会生成或接受 DER 编码。
    3. result 为对 data 进行 DER 编码所得的结果。

    如果 format 为 "jwk":
    1. jwk 为一个新的 JsonWebKey 字典。

    2. jwkkty 属性设置为字符串 "RSA"。

    3. hashkey[[algorithm]] 内部槽的 hash 属性的 name 属性。

    4. 如果 hash 为 "SHA-1":

      jwkalg 属性设置为字符串 "RS1"。

      如果 hash 为 "SHA-256":

      jwkalg 属性设置为字符串 "RS256"。

      如果 hash 为 "SHA-384":

      jwkalg 属性设置为字符串 "RS384"。

      如果 hash 为 "SHA-512":

      jwkalg 属性设置为字符串 "RS512"。

      否则:
      1. 执行由 其他适用 规范定义的任何 密钥 导出步骤,传入 formatkey 并获得 alg

      2. 如果发生错误或不存在 适用 规范, 则抛出 一个 NotSupportedError

      3. jwkalg 属性设置为 alg

    5. 按照 JSON Web Algorithms [JWA] 第 6.3.1 节中的 相应定义,设置 jwk 的属性 ne

    6. 如果 key[[type]] 内部槽 为 "private":
      1. 按照 JSON Web Algorithms [JWA] 第 6.3.2 节中的相应定义,设置 jwk 的名为 dpqdpdqqi 的属性。

      2. 如果由 key[[handle]] 内部槽表示的底层 RSA 私钥由多于两个素数表示, 则按照 JSON Web Algorithms [JWA] 第 6.3.2.7 节中的相应定义,设置 jwk 的名为 oth 的属性

    7. jwkkey_ops 属性设置为 keyusages 属性。

    8. jwkext 属性设置为 key[[extractable]] 内部槽。

    9. resultjwk

    否则

    抛出一个 NotSupportedError

  4. 返回 result

21. RSA-PSS

21.1 描述

本节是非规范性的。

"RSA-PSS" 算法标识符用于执行使用 [RFC3447] 中指定的 RSASSA-PSS 算法的签名 和验证, 并使用本规范中定义的 SHA 哈希函数和掩码生成 公式 MGF1。

其他 规范 可以指定将其他哈希算法与 RSASSA-PSS 一起使用。此类规范 必须定义其他哈希算法的摘要操作,以及 RSASSA-PSS 的 密钥导入步骤密钥导出步骤

21.2 注册

此算法的已识别算法名称为 "RSA-PSS"。

操作 参数 结果
sign RsaPssParams 字节 序列
verify RsaPssParams boolean
generateKey RsaHashedKeyGenParams CryptoKeyPair
importKey RsaHashedImportParams CryptoKey
exportKey object

21.3 RsaPssParams 字典

WebIDLdictionary RsaPssParams : Algorithm {
  required [EnforceRange] unsigned long saltLength;
};

saltLength 成员表示所需的 随机盐长度,以字节为单位。

21.4 操作

21.4.1 签名

  1. 如果 key[[type]] 内部槽不是 "private",则 抛出一个 InvalidAccessError

  2. 执行 [RFC3447] 第 8.1 节中定义的签名生成操作,其中使用 key[[handle]] 内部槽表示的密钥 作为签名者的私钥 K,以 message 作为 要签名的消息 M,并使用 key[[algorithm]] 内部 槽的 hash 属性指定的哈希函数 作为 Hash 选项,MGF1(定义于 [RFC3447] 第 B.2.1 节) 作为 MGF 选项,并使用 normalizedAlgorithmsaltLength 成员作为 EMSA-PSS-ENCODE 操作的盐长度选项。

  3. 如果执行该操作导致错误, 则抛出一个 OperationError

  4. signature 为执行该操作所得的 签名 S

  5. 返回 signature

21.4.2 验证

  1. 如果 key[[type]] 内部槽不是 "public",则抛出一个 InvalidAccessError

  2. 执行 [RFC3447] 第 8.1 节中定义的签名验证操作,其中使用 key[[handle]] 内部槽表示的密钥 作为签名者的 RSA 公钥,以 message 作为 M,并以 signature 作为 S,并使用 key[[algorithm]] 内部 槽的 hash 属性指定的哈希函数 作为 Hash 选项,MGF1(定义于 [RFC3447] 第 B.2.1 节) 作为 MGF 选项,并使用 normalizedAlgorithmsaltLength 成员作为 EMSA-PSS-VERIFY 操作的盐长度选项。

  3. result 为一个 boolean;如果该操作的 结果为 "valid signature",则其值为 true,否则其值 为 false。

21.4.3 生成密钥

  1. 如果 usages 包含不是 "sign" 或 "verify" 的条目, 则抛出一个 SyntaxError

  2. 按 [RFC3447] 中的定义生成一个 RSA 密钥对,其 RSA 模数长度等于 normalizedAlgorithmmodulusLength 成员, RSA 公共指数等于 normalizedAlgorithmpublicExponent 成员。

  3. 如果执行该操作导致错误, 则抛出一个 OperationError

  4. algorithm 为一个新的 RsaHashedKeyAlgorithm 字典。

  5. algorithmname 属性设置为 "RSA-PSS"。

  6. algorithmmodulusLength 属性设置为等于 normalizedAlgorithmmodulusLength 成员。

  7. algorithmpublicExponent 属性设置为等于 normalizedAlgorithmpublicExponent 成员。

  8. algorithmhash 属性 设置为等于 normalizedAlgorithmhash 成员。

  9. publicKey 为一个新的 CryptoKey, 表示所生成密钥对的公钥。

  10. publicKey[[type]] 内部槽设置为 "public"

  11. publicKey[[algorithm]] 内部 槽设置为 algorithm

  12. publicKey[[extractable]] 内部 槽设置为 true。

  13. publicKey[[usages]] 内部槽 设置为 usages[ "verify" ]用法交集

  14. privateKey 为一个新的 CryptoKey, 表示所生成密钥对的私钥。

  15. privateKey[[type]] 内部槽设置为 "private"

  16. privateKey[[algorithm]] 内部 槽设置为 algorithm

  17. privateKey[[extractable]] 内部 槽设置为 extractable

  18. privateKey[[usages]] 内部槽 设置为 usages[ "sign" ]用法交集

  19. result 为一个新的 CryptoKeyPair 字典。

  20. resultpublicKey 属性 设置为 publicKey

  21. resultprivateKey 属性 设置为 privateKey

  22. 返回 result

21.4.4 导入密钥

  1. keyData 为要导入的密钥数据。

  2. 如果 format 为 "spki":
    1. 如果 usages 包含不是 "verify" 的条目, 则抛出一个 SyntaxError

    2. spki 为对 keyData 运行 解析 subjectPublicKeyInfo 算法所得的结果。

    3. 如果解析过程中发生错误, 则抛出一个 DataError

    4. 如果 spkialgorithm AlgorithmIdentifier 字段的 algorithm 对象标识符字段 不等于 [RFC3447] 中定义的 rsaEncryption 对象标识符,则抛出一个 DataError

    5. publicKey 为执行解析 ASN.1 结构 算法所得的结果,其中 dataspkisubjectPublicKeyInfo 字段, structure 为 [RFC3447] 第 A.1.1 节中指定的 RSAPublicKey 结构, 并将 exactData 设置为 true。

    6. 如果解析过程中发生错误,或者可以确定 publicKey 不是符合 [RFC3447] 的有效公钥,则抛出一个 DataError

    7. key 为一个新的 CryptoKey, 它表示由 publicKey 标识的 RSA 公钥。

    8. key[[type]] 内部槽 设置为 "public"

    如果 format 为 "pkcs8":
    1. 如果 usages 包含不是 "sign" 的条目, 则抛出一个 SyntaxError

    2. privateKeyInfo 为对 keyData 运行 解析 privateKeyInfo 算法所得的结果。

    3. 如果解析过程中发生错误,则抛出一个 DataError

    4. 如果 privateKeyInfoprivateKeyAlgorithm PrivateKeyAlgorithm 字段的 algorithm 对象标识符字段不等于 [RFC3447] 中定义的 rsaEncryption 对象标识符, 则抛出一个 DataError

    5. rsaPrivateKey 为执行解析 ASN.1 结构 算法所得的结果,其中 dataprivateKeyInfoprivateKey 字段, structure 为 [RFC3447] 第 A.1.2 节中指定的 RSAPrivateKey 结构, 并将 exactData 设置为 true。

    6. 如果解析过程中发生错误,或者 rsaPrivateKey 不是 符合 [RFC3447] 的有效 RSA 私钥,则抛出一个 DataError

    7. key 为一个新的 CryptoKey, 它表示由 rsaPrivateKey 标识的 RSA 私钥。

    8. key[[type]] 内部槽 设置为 "private"

    如果 format 为 "jwk":
    1. 如果 keyData 是一个 JsonWebKey 字典:

      jwk 等于 keyData

      否则:

      抛出一个 DataError

    2. 如果 jwkd 字段存在,且 usages 包含不是 "sign" 的条目;或者,如果 jwkd 字段 不存在,且 usages 包含不是 "verify" 的条目, 则抛出一个 SyntaxError

    3. 如果 jwkkty 字段 与 "RSA" 不是区分大小写的字符串匹配, 则抛出一个 DataError

    4. 如果 usages 非空,且 jwkuse 字段存在,并且 与 "sig" 不是区分大小写的字符串匹配, 则抛出一个 DataError

    5. 如果 jwkkey_ops 字段存在,且 根据 JSON Web Key [JWK] 的要求无效,或 不包含所有指定的 usages 值, 则抛出一个 DataError

    6. 如果 jwkext 字段存在且 值为 false,并且 extractable 为 true, 则抛出一个 DataError

    7. 如果 jwkalg 字段 不存在:

      hash 为 undefined。

      如果 alg 字段 等于字符串 "PS1":

      hash 为字符串 "SHA-1"。

      如果 alg 字段 等于字符串 "PS256":

      hash 为字符串 "SHA-256"。

      如果 alg 字段 等于字符串 "PS384":

      hash 为字符串 "SHA-384"。

      如果 alg 字段 等于字符串 "PS512":

      hash 为字符串 "SHA-512"。

      否则:
      1. 执行由 其他适用 规范定义的任何 密钥 导入步骤,传入 formatjwk 并获得 hash

      2. 如果发生错误或不存在 适用 规范, 则抛出 一个 DataError

    8. 如果 hash 不是 undefined:
      1. normalizedHash规范化 算法所得的结果, 其中 alg 设置为 hash,并将 op 设置 为 digest

      2. 如果 normalizedHash 不等于 normalizedAlgorithmhash 成员,则抛出 一个 DataError

    9. 如果 jwkd 字段存在:
      1. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.3.2 节的要求, 则抛出 一个 DataError

      2. privateKey 表示 按照 JSON Web Algorithms [JWA] 第 6.3.2 节解释 jwk 所标识的 RSA 私钥。

      3. 如果可以确定 privateKey 不是符合 [RFC3447] 的有效 RSA 私钥, 则抛出 一个 DataError

      4. key 为一个新的 CryptoKey, 表示 privateKey

      5. key[[type]] 内部槽设置为 "private"

      否则:
      1. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.3.1 节的要求, 则抛出 一个 DataError

      2. publicKey 表示 按照 JSON Web Algorithms [JWA] 第 6.3.1 节解释 jwk 所标识的 RSA 公钥。

      3. 如果可以确定 publicKey 不是符合 [RFC3447] 的有效 RSA 公钥, 则抛出 一个 DataError

      4. key 为一个新的 CryptoKey, 表示 publicKey

      5. key[[type]] 内部槽设置为 "public"

    否则:
    抛出一个 NotSupportedError
  3. algorithm 为一个新的 RsaHashedKeyAlgorithm 字典。

  4. algorithmname 属性设置为 "RSA-PSS"

  5. algorithmmodulusLength 属性设置为 RSA 公共模数的长度,以位为单位。

  6. algorithmpublicExponent 属性设置为 RSA 公共指数的 BigInteger 表示。

  7. algorithmhash 属性设置为 normalizedAlgorithmhash 成员。

  8. key[[algorithm]] 内部 槽设置为 algorithm

  9. 返回 key

21.4.5 导出密钥

  1. key 为要导出的密钥。

  2. 如果无法访问由 key[[handle]] 内部槽表示的 底层加密密钥材料, 则抛出一个 OperationError

  3. 如果 format 为 "spki"
    1. 如果 key[[type]] 内部槽 不是 "public",则抛出一个 InvalidAccessError

    2. data 为 [RFC5280] 中定义的 SubjectPublicKeyInfo ASN.1 结构的一个实例,并具有以下属性:

      • algorithm 字段设置为具有以下 属性的 AlgorithmIdentifier ASN.1 类型:

        • algorithm 字段设置为 [RFC3447] 中定义的 OID rsaEncryption

        • params 字段设置为 ASN.1 类型 NULL。

      • subjectPublicKey 字段设置为 对 [RFC3447] 附录 A.1.1 中定义的 RSAPublicKey ASN.1 类型进行 DER 编码所得的结果,该类型 表示由 key[[handle]] 内部槽表示的 RSA 公钥

    3. result 为对 data 进行 DER 编码所得的结果。

    如果 format 为 "pkcs8":
    1. 如果 key[[type]] 内部槽 不是 "private",则抛出一个 InvalidAccessError

    2. data 为 [RFC5208] 中定义的 PrivateKeyInfo ASN.1 结构的一个实例,并具有以下属性:

      • version 字段设置为 0

      • privateKeyAlgorithm 字段设置为具有以下 属性的 PrivateKeyAlgorithmIdentifier ASN.1 类型:

        • algorithm 字段设置为 [RFC3447] 中定义的 OID rsaEncryption

        • params 字段设置为 ASN.1 类型 NULL。

      • privateKey 字段设置为对 [RFC3447] 附录 A.1.2 中定义的 RSAPrivateKey ASN.1 类型进行 DER 编码所得的结果, 该类型表示由 key[[handle]] 内部槽表示的 RSA 私钥

        [RFC5208] 在第 5 节中规定,此字段的编码应进行 BER 编码(作为 “例如”)。然而,为了避免要求 WebCrypto 实现 支持 BER 编码和 BER 解码,只会生成或接受 DER 编码。
    3. result 为对 data 进行 DER 编码所得的结果。

    如果 format 为 "jwk":
    1. jwk 为一个新的 JsonWebKey 字典。

    2. jwkkty 属性设置为字符串 "RSA"。

    3. hashkey[[algorithm]] 内部槽的 hash 属性的 name 属性。

    4. 如果 hash 为 "SHA-1":

      jwkalg 属性设置为字符串 "PS1"。

      如果 hash 为 "SHA-256":

      jwkalg 属性设置为字符串 "PS256"。

      如果 hash 为 "SHA-384":

      jwkalg 属性设置为字符串 "PS384"。

      如果 hash 为 "SHA-512":

      jwkalg 属性设置为字符串 "PS512"。

      否则:
      1. 执行由其他适用 规范定义的任何 密钥 导出步骤,传入 formatkey[[algorithm]] 内部槽的 hash 属性, 并获得 alg

      2. jwkalg 属性设置为 alg

    5. 按照 JSON Web Algorithms [JWA] 第 6.3.1 节中的 相应定义,设置 jwk 的属性 ne

    6. 如果 key[[type]] 内部槽为 "private":
      1. 按照 JSON Web Algorithms [JWA] 第 6.3.2 节中的相应定义,设置 jwk 的名为 dpqdpdqqi 的属性。

      2. 如果由 key[[handle]] 内部槽表示的底层 RSA 私钥由多于两个素数表示, 则按照 JSON Web Algorithms [JWA] 第 6.3.2.7 节中的相应定义,设置 jwk 的名为 oth 的属性

    7. jwkkey_ops 属性设置为 keyusages 属性。

    8. jwkext 属性设置为 key[[extractable]] 内部槽。

    9. resultjwk

    否则

    抛出一个 NotSupportedError

  4. 返回 result

22. RSA-OAEP

22.1 描述

本节是非规范性的。

"RSA-OAEP" 算法标识符用于根据 [RFC3447] 中指定的 RSAES-OAEP 算法执行加密 和解密, 并使用本规范中定义的 SHA 哈希函数以及掩码 生成函数 MGF1。

其他 规范 可以指定将其他哈希算法与 RSAES-OAEP 一起使用。此类规范 必须定义其他哈希算法的摘要操作,以及 RSAES-OAEP 的 密钥导入步骤密钥导出步骤

22.2 注册

此算法的已识别算法名称为 "RSA-OAEP"。

操作 参数 结果
encrypt RsaOaepParams 字节 序列
decrypt RsaOaepParams 字节 序列
generateKey RsaHashedKeyGenParams CryptoKeyPair
importKey RsaHashedImportParams CryptoKey
exportKey object

22.3 RsaOaepParams 字典

WebIDLdictionary RsaOaepParams : Algorithm {
  BufferSource label;
};

label 成员表示要与消息关联的可选标签/应用 数据。

22.4 操作

22.4.1 加密

  1. 如果 key[[type]] 内部槽 不是 "public", 则抛出一个 InvalidAccessError

  2. labelnormalizedAlgorithmlabel 成员; 如果 normalizedAlgorithmlabel 成员不存在,则为空字节序列。

  3. 执行 [RFC3447] 第 7.1 节中定义的加密操作,其中使用由 key 表示的密钥作为接收者的 RSA 公钥,以 plaintext 作为要加密的消息 M,以 label 作为标签 L,并使用 key[[algorithm]] 内部 槽的 hash 属性指定的哈希函数作为 Hash 选项,并以 MGF1(定义于 [RFC3447] 第 B.2.1 节) 作为 MGF 选项。

  4. 如果执行该操作导致错误, 则抛出一个 OperationError

  5. ciphertext 为执行该操作所得的值 C

  6. 返回 ciphertext

22.4.2 解密

  1. 如果 key[[type]] 内部槽 不是 "private", 则抛出一个 InvalidAccessError

  2. labelnormalizedAlgorithmlabel 成员; 如果 normalizedAlgorithmlabel 成员不存在,则为空字节序列。

  3. 执行 [RFC3447] 第 7.1 节中定义的解密操作,其中使用由 key 表示的密钥作为接收者的 RSA 私钥,以 ciphertext 作为要解密的密文 C,以 label 作为标签 L,并使用 key[[algorithm]] 内部 槽的 hash 属性指定的哈希函数作为 Hash 选项,并以 MGF1(定义于 [RFC3447] 第 B.2.1 节) 作为 MGF 选项。

  4. 如果执行该操作导致错误, 则抛出一个 OperationError

  5. plaintext 为执行该操作所得的值 M

  6. 返回 plaintext

22.4.3 生成密钥

  1. 如果 usages 包含不是 "encrypt"、"decrypt"、 "wrapKey" 或 "unwrapKey" 的条目, 则抛出一个 SyntaxError

  2. 按 [RFC3447] 中的定义生成一个 RSA 密钥对,其 RSA 模数长度等于 normalizedAlgorithmmodulusLength 成员, RSA 公共指数等于 normalizedAlgorithmpublicExponent 成员。

  3. 如果执行该操作导致错误, 则抛出一个 OperationError

  4. algorithm 为一个新的 RsaHashedKeyAlgorithm 对象。

  5. algorithmname 属性设置为 "RSA-OAEP"。

  6. algorithmmodulusLength 属性设置为等于 normalizedAlgorithmmodulusLength 成员。

  7. algorithmpublicExponent 属性设置为等于 normalizedAlgorithmpublicExponent 成员。

  8. algorithmhash 属性 设置为等于 normalizedAlgorithmhash 成员。

  9. publicKey 为一个新的 CryptoKey, 表示所生成密钥对的公钥。

  10. publicKey[[type]] 内部槽 设置为 "public"

  11. publicKey[[algorithm]] 内部 槽设置为 algorithm

  12. publicKey[[extractable]] 内部 槽设置为 true。

  13. publicKey[[usages]] 内部槽 设置为 usages[ "encrypt", "wrapKey" ]用法交集

  14. privateKey 为一个新的 CryptoKey, 表示所生成密钥对的私钥。

  15. privateKey[[type]] 内部槽 设置为 "private"

  16. privateKey[[algorithm]] 内部 槽设置为 algorithm

  17. privateKey[[extractable]] 内部 槽设置为 extractable

  18. privateKey[[usages]] 内部槽 设置为 usages[ "decrypt", "unwrapKey" ]用法交集

  19. result 为一个新的 CryptoKeyPair 字典。

  20. resultpublicKey 属性 设置为 publicKey

  21. resultprivateKey 属性 设置为 privateKey

  22. 返回 result

22.4.4 导入密钥

  1. keyData 为要导入的密钥数据。

  2. 如果 format 为 "spki":
    1. 如果 usages 包含不是 "encrypt" 或 "wrapKey" 的条目, 则抛出一个 SyntaxError

    2. spki 为对 keyData 运行 解析 subjectPublicKeyInfo 算法所得的结果。

    3. 如果解析过程中发生错误, 则抛出一个 DataError

    4. 如果 spkialgorithm AlgorithmIdentifier 字段的 algorithm 对象标识符字段 不等于 [RFC3447] 中定义的 rsaEncryption 对象标识符,则抛出一个 DataError

    5. publicKey 为执行解析 ASN.1 结构 算法所得的结果,其中 dataspkisubjectPublicKeyInfo 字段, structure 为 [RFC3447] 第 A.1.1 节中指定的 RSAPublicKey 结构, 并将 exactData 设置为 true。

    6. 如果解析过程中发生错误,或者可以确定 publicKey 不是符合 [RFC3447] 的有效公钥,则抛出一个 DataError

    7. key 为一个新的 CryptoKey, 它表示由 publicKey 标识的 RSA 公钥。

    8. key[[type]] 内部槽设置为 "public"

    如果 format 为 "pkcs8":
    1. 如果 usages 包含不是 "decrypt" 或 "unwrapKey" 的条目, 则抛出一个 SyntaxError

    2. privateKeyInfo 为对 keyData 运行 解析 privateKeyInfo 算法所得的结果。

    3. 如果解析过程中发生错误,则抛出一个 DataError

    4. 如果 privateKeyInfoprivateKeyAlgorithm PrivateKeyAlgorithm 字段的 algorithm 对象标识符字段不等于 [RFC3447] 中定义的 rsaEncryption 对象标识符, 则抛出一个 DataError

    5. rsaPrivateKey 为执行解析 ASN.1 结构 算法所得的结果,其中 dataprivateKeyInfoprivateKey 字段, structure 为 [RFC3447] 第 A.1.2 节中指定的 RSAPrivateKey 结构, 并将 exactData 设置为 true。

    6. 如果解析过程中发生错误,或者 rsaPrivateKey 不是 符合 [RFC3447] 的有效 RSA 私钥,则抛出一个 DataError

    7. key 为一个新的 CryptoKey, 它表示由 rsaPrivateKey 标识的 RSA 私钥。

    8. key[[type]] 内部槽 设置为 "private"

    如果 format 为 "jwk":
    1. 如果 keyData 是一个 JsonWebKey 字典:

      jwk 等于 keyData

      否则:

      抛出一个 DataError

    2. 如果 jwkd 字段存在,且 usages 包含不是 "decrypt" 或 "unwrapKey" 的条目, 则抛出一个 SyntaxError

    3. 如果 jwkd 字段不存在,且 usages 包含不是 "encrypt" 或 "wrapKey" 的条目, 则抛出一个 SyntaxError

    4. 如果 jwkkty 字段 与 "RSA" 不是区分大小写的字符串匹配, 则抛出一个 DataError

    5. 如果 usages 非空,且 jwkuse 字段存在,并且 与 "enc" 不是区分大小写的字符串匹配, 则抛出一个 DataError

    6. 如果 jwkkey_ops 字段存在,且 根据 JSON Web Key [JWK] 的要求无效,或 不包含所有指定的 usages 值, 则抛出一个 DataError

    7. 如果 jwkext 字段存在且 值为 false,并且 extractable 为 true, 则抛出一个 DataError

    8. 如果 jwkalg 字段不存在:
      hash 为 undefined。
      如果 jwkalg 字段等于 "RSA-OAEP":
      hash 为字符串 "SHA-1"。
      如果 jwkalg 字段等于 "RSA-OAEP-256":
      hash 为字符串 "SHA-256"。
      如果 jwkalg 字段等于 "RSA-OAEP-384":
      hash 为字符串 "SHA-384"。
      如果 jwkalg 字段等于 "RSA-OAEP-512":
      hash 为字符串 "SHA-512"。
      否则:
      1. 执行由 其他适用 规范定义的任何 密钥 导入步骤,传入 formatjwk 并获得 hash

      2. 如果发生错误或不存在 适用 规范, 则抛出 一个 DataError

    9. 如果 hash 不是 undefined:
      1. normalizedHash规范化 算法所得的结果, 其中 alg 设置为 hash,并将 op 设置 为 digest

      2. 如果 normalizedHash 不等于 normalizedAlgorithmhash 成员,则抛出 一个 DataError

    10. 如果 jwkd 字段存在:
      1. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.3.2 节的要求, 则抛出 一个 DataError

      2. privateKey 表示 按照 JSON Web Algorithms [JWA] 第 6.3.2 节解释 jwk 所标识的 RSA 私钥。

      3. 如果可以确定 privateKey 不是符合 [RFC3447] 的有效 RSA 私钥, 则抛出 一个 DataError

      4. key 为一个新的 CryptoKey, 表示 privateKey

      5. key[[type]] 内部槽设置为 "private"

      否则:
      1. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.3.1 节的要求, 则抛出 一个 DataError

      2. publicKey 表示 按照 JSON Web Algorithms [JWA] 第 6.3.1 节解释 jwk 所标识的 RSA 公钥。

      3. 如果可以确定 publicKey 不是符合 [RFC3447] 的有效 RSA 公钥, 则抛出 一个 DataError

      4. key 为一个新的 CryptoKey, 表示 publicKey

      5. key[[type]] 内部槽设置为 "public"

    否则:
    抛出一个 NotSupportedError
  3. algorithm 为一个新的 RsaHashedKeyAlgorithm

  4. algorithmname 属性设置为 "RSA-OAEP"

  5. algorithmmodulusLength 属性设置为 RSA 公共模数的长度,以位为单位。

  6. algorithmpublicExponent 属性设置为 RSA 公共指数的 BigInteger 表示。

  7. algorithmhash 属性设置为 normalizedAlgorithmhash 成员。

  8. key[[algorithm]] 内部 槽设置为 algorithm

  9. 返回 key

22.4.5 导出密钥

  1. key 为要导出的密钥。

  2. 如果无法访问由 key[[handle]] 内部槽表示的 底层加密密钥材料, 则抛出一个 OperationError

  3. 如果 format 为 "spki"
    1. 如果 key[[type]] 内部槽 不是 "public",则抛出一个 InvalidAccessError

    2. data 为 [RFC5280] 中定义的 SubjectPublicKeyInfo ASN.1 结构的一个实例,并具有以下属性:

      • algorithm 字段设置为具有以下 属性的 AlgorithmIdentifier ASN.1 类型:

        • algorithm 字段设置为 [RFC3447] 中定义的 OID rsaEncryption

        • params 字段设置为 ASN.1 类型 NULL。

      • subjectPublicKey 字段设置为 对 [RFC3447] 附录 A.1.1 中定义的 RSAPublicKey ASN.1 类型进行 DER 编码所得的结果,该类型 表示由 key[[handle]] 内部槽表示的 RSA 公钥

    3. result 为对 data 进行 DER 编码所得的结果。

    如果 format 为 "pkcs8":
    1. 如果 key[[type]] 内部槽 不是 "private",则抛出一个 InvalidAccessError

    2. data 为 [RFC5208] 中定义的 PrivateKeyInfo ASN.1 结构的一个实例,并具有以下属性:

      • version 字段设置为 0

      • privateKeyAlgorithm 字段设置为具有以下 属性的 PrivateKeyAlgorithmIdentifier ASN.1 类型:

        • algorithm 字段设置为 [RFC3447] 中定义的 OID rsaEncryption

        • params 字段设置为 ASN.1 类型 NULL。

      • privateKey 字段设置为对 [RFC3447] 附录 A.1.2 中定义的 RSAPrivateKey ASN.1 类型进行 DER 编码所得的结果, 该类型表示由 key[[handle]] 内部槽表示的 RSA 私钥

        [RFC5208] 在第 5 节中规定,此字段的编码应进行 BER 编码(作为 “例如”)。然而,为了避免要求 WebCrypto 实现 支持 BER 编码和 BER 解码,只会生成或接受 DER 编码。
    3. result 为对 data 进行 DER 编码所得的结果。

    如果 format 为 "jwk":
    1. jwk 为一个新的 JsonWebKey 字典。

    2. jwkkty 属性设置为字符串 "RSA"。

    3. hashkey[[algorithm]] 内部槽的 hash 属性的 name 属性。

    4. 如果 hash 为 "SHA-1":

      jwkalg 属性设置为字符串 "RSA-OAEP"。

      如果 hash 为 "SHA-256":

      jwkalg 属性设置为字符串 "RSA-OAEP-256"。

      如果 hash 为 "SHA-384":

      jwkalg 属性设置为字符串 "RSA-OAEP-384"。

      如果 hash 为 "SHA-512":

      jwkalg 属性设置为字符串 "RSA-OAEP-512"。

      否则:
      1. 执行由其他适用 规范定义的任何 密钥 导出步骤,传入 formatkey[[algorithm]] 内部槽的 hash 属性, 并获得 alg

      2. jwkalg 属性设置为 alg

    5. 按照 JSON Web Algorithms [JWA] 第 6.3.1 节中的 相应定义,设置 jwk 的属性 ne

    6. 如果 key[[type]] 内部槽 为 "private":
      1. 按照 JSON Web Algorithms [JWA] 第 6.3.2 节中的相应定义,设置 jwk 的名为 dpqdpdqqi 的属性。

      2. 如果由 key[[handle]] 内部槽表示的底层 RSA 私钥由多于两个素数表示, 则按照 JSON Web Algorithms [JWA] 第 6.3.2.7 节中的相应定义,设置 jwk 的名为 oth 的属性

    7. jwkkey_ops 属性设置为 keyusages 属性。

    8. jwkext 属性设置为 key[[extractable]] 内部槽。

    9. resultjwk

    否则

    抛出一个 NotSupportedError

  4. 返回 result

23. ECDSA

23.1 描述

本节是非规范性的。

"ECDSA" 算法标识符用于使用 [RFC6090] 中指定的 ECDSA 算法执行签名 和验证,并使用本规范中定义的 SHA 哈希函数和椭圆 曲线。

其他 规范 可以指定将其他椭圆曲线和哈希算法与 ECDSA 一起使用。要 指定与 ECDSA 一起使用的其他哈希算法,规范必须定义 一个支持摘要操作的注册算法。 要指定额外的椭圆曲线,规范必须定义 曲线名称ECDSA 签名步骤ECDSA 验证步骤ECDSA 生成步骤ECDSA 密钥导入步骤ECDSA 密钥导出步骤

23.2 注册

此算法的已识别算法名称为 "ECDSA"。

操作 参数 结果
sign EcdsaParams 字节 序列
verify EcdsaParams boolean
generateKey EcKeyGenParams CryptoKeyPair
importKey EcKeyImportParams CryptoKey
exportKey object

23.3 EcdsaParams 字典

WebIDLdictionary EcdsaParams : Algorithm {
  required HashAlgorithmIdentifier hash;
};

hash 成员表示要使用的哈希算法。

23.4 EcKeyGenParams 字典

WebIDLtypedef DOMString NamedCurve;

dictionary EcKeyGenParams : Algorithm {
  required NamedCurve namedCurve;
};

NamedCurve 类型表示命名椭圆曲线, 它们是指定知名椭圆 曲线的域参数的一种便捷方式。本规范定义了以下值:

"P-256"
NIST 推荐曲线 P-256,也称为 secp256r1
"P-384"
NIST 推荐曲线 P-384,也称为 secp384r1
"P-521"
NIST 推荐曲线 P-521,也称为 secp521r1

其他 规范可以定义 额外值

EcKeyGenParams 字典的 namedCurve 成员表示命名 曲线。

23.5 EcKeyAlgorithm 字典

WebIDLdictionary EcKeyAlgorithm : KeyAlgorithm {
  required NamedCurve namedCurve;
};

namedCurve 成员表示 该密钥使用的命名曲线。

23.6 EcKeyImportParams 字典

WebIDLdictionary EcKeyImportParams : Algorithm {
  required NamedCurve namedCurve;
};

namedCurve 成员表示命名曲线。

23.7 操作

23.7.1 签名

  1. 如果 key[[type]] 内部槽不是 "private",则 抛出一个 InvalidAccessError

  2. hashAlgorithmnormalizedAlgorithmhash 成员。

  3. M 为使用 message 执行由 hashAlgorithm 指定的摘要操作所得的结果。

  4. d 为与 key 关联的 ECDSA 私钥。

  5. params 为与 key 关联的 EC 域参数。

  6. 如果 key[[algorithm]] 内部 槽的 namedCurve 属性 为 "P-256"、"P-384" 或 "P-521":
    1. 执行 [RFC6090] 第 5.4 节中指定的 ECDSA 签名过程,其中 M 作为消息,使用 params 作为 EC 域参数,并以 d 作为私钥。

    2. rs 为执行 ECDSA 签名过程所得的 整数对。

    3. result 为空字节序列

    4. n 为满足 n * 8 大于 由 params 标识的椭圆曲线基点阶数以 2 为底的对数的 最小整数。

    5. r 转换为长度为 n 的字节序列并追加到 result

    6. s 转换为长度为 n 的字节序列并追加到 result

    否则,如果 key[[algorithm]] 内部 槽的 namedCurve 属性 是适用规范中指定的值:

    执行该规范中指定的 ECDSA 签名步骤, 传入 Mparamsd,并得到 result

  7. 返回 result

23.7.2 验证

  1. 如果 key[[type]] 内部槽不是 "public",则抛出一个 InvalidAccessError

  2. hashAlgorithmnormalizedAlgorithmhash 成员。

  3. M 为使用 message 执行由 hashAlgorithm 指定的摘要操作所得的结果。

  4. Q 为与 key 关联的 ECDSA 公钥。

  5. params 为与 key 关联的 EC 域参数。

  6. 如果 key[[algorithm]] 内部 槽的 namedCurve 属性 为 "P-256"、"P-384" 或 "P-521":

    执行 [RFC6090] 第 5.3 节中指定的 ECDSA 验证过程,其中 M 作为接收到的 消息,signature 作为接收到的签名,并使用 params 作为 EC 域参数,且以 Q 作为公钥。

    否则,如果 key[[algorithm]] 内部 槽的 namedCurve 属性 是适用规范中指定的值:

    执行该规范中指定的 ECDSA 验证 步骤, 传入 MsignatureparamsQ,并得到所谓签名是否 有效的指示。

  7. result 为 boolean;如果签名 有效,则其值为 true, 否则其值为 false

  8. 返回 result

23.7.3 生成密钥

  1. 如果 usages 包含不是 "sign" 或 "verify" 之一的值, 则抛出一个 SyntaxError

  2. 如果 normalizedAlgorithmnamedCurve 成员为 "P-256"、"P-384" 或 "P-521":

    按 [RFC6090] 中的定义生成一个椭圆曲线密钥对,其域参数用于 normalizedAlgorithmnamedCurve 成员 所标识的曲线。

    如果 normalizedAlgorithmnamedCurve 成员 是适用规范中指定的值:

    执行该规范中指定的 ECDSA 生成步骤, 传入 normalizedAlgorithm,并得到椭圆曲线密钥对。

    否则:

    抛出一个 NotSupportedError

  3. 如果执行密钥生成操作导致错误, 则抛出一个 OperationError

  4. algorithm 为一个新的 EcKeyAlgorithm 对象。

  5. algorithmname 属性设置为 "ECDSA"。

  6. algorithmnamedCurve 属性设置为等于 normalizedAlgorithmnamedCurve 成员。

  7. publicKey 为一个新的 CryptoKey, 表示所生成密钥对的公钥。

  8. publicKey[[type]] 内部槽设置为 "public"

  9. publicKey[[algorithm]] 内部 槽设置为 algorithm

  10. publicKey[[extractable]] 内部 槽设置为 true。

  11. publicKey[[usages]] 内部槽 设置为 usages[ "verify" ]用法交集

  12. privateKey 为一个新的 CryptoKey, 表示所生成密钥对的私钥。

  13. privateKey[[type]] 内部槽设置为 "private"

  14. privateKey[[algorithm]] 内部 槽设置为 algorithm

  15. privateKey[[extractable]] 内部 槽设置为 extractable

  16. privateKey[[usages]] 内部槽 设置为 usages[ "sign" ]用法交集

  17. result 为一个新的 CryptoKeyPair 字典。

  18. resultpublicKey 属性 设置为 publicKey

  19. resultprivateKey 属性 设置为 privateKey

  20. 返回 result

23.7.4 导入密钥

  1. keyData 为要导入的密钥数据。

  2. 如果 format 为 "spki":
    1. 如果 usages 包含不是 "verify" 的值, 则抛出一个 SyntaxError

    2. spki 为对 keyData 运行 解析 subjectPublicKeyInfo 算法所得的结果

    3. 如果解析过程中发生错误, 则抛出一个 DataError

    4. 如果 spkialgorithm AlgorithmIdentifier 字段的 algorithm 对象标识符字段 不等于 [RFC5480] 中定义的 id-ecPublicKey 对象标识符,则抛出一个 DataError

    5. 如果 spkialgorithm AlgorithmIdentifier 字段的 parameters 字段缺失, 则抛出一个 DataError

    6. paramsspkialgorithm AlgorithmIdentifier 字段的 parameters 字段。

    7. 如果 params 不是 [RFC5480] 中定义的、指定了 namedCurveECParameters ASN.1 类型实例,则抛出一个 DataError

    8. namedCurve 为一个初始值为 undefined 的字符串。

    9. 如果 params 等价于 [RFC5480] 中定义的 secp256r1 对象标识符:

      namedCurve 设置为 "P-256"。

      如果 params 等价于 [RFC5480] 中定义的 secp384r1 对象标识符:

      namedCurve 设置为 "P-384"。

      如果 params 等价于 [RFC5480] 中定义的 secp521r1 对象标识符:

      namedCurve 设置为 "P-521"。

    10. 如果 namedCurve 不是 undefined:
      1. publicKey 为通过 使用 spkisubjectPublicKey 字段执行 [SEC1] 第 2.3.4 节中定义的转换步骤 所标识的椭圆曲线公钥。

        未压缩点格式 MUST 被支持。

      2. 如果实现不支持压缩点 格式,并且提供了 压缩点, 则抛出 一个 DataError

      3. 如果发生解码错误或发现单位点, 则抛出 一个 DataError

      4. key 为一个新的 CryptoKey, 它表示 publicKey

      否则:
      1. 执行由 其他适用 规范定义的任何 密钥 导入步骤,传入 formatspki 并获得 namedCurvekey

      2. 如果发生错误或不存在 适用 规范, 则抛出 一个 DataError

    11. 如果 namedCurve 已定义,且不等于 normalizedAlgorithmnamedCurve 成员,则抛出一个 DataError

    12. 如果公钥值不是 normalizedAlgorithmnamedCurve 成员所标识的椭圆曲线上的有效点,则抛出一个 DataError

    13. key[[type]] 内部槽 设置为 "public"

    14. algorithm 为一个新的 EcKeyAlgorithm

    15. algorithmname 属性设置为 "ECDSA"。

    16. algorithmnamedCurve 属性设置为 namedCurve

    17. key[[algorithm]] 内部槽设置为 algorithm

    如果 format 为 "pkcs8":
    1. 如果 usages 包含不是 "sign" 的值, 则抛出一个 SyntaxError

    2. privateKeyInfo 为对 keyData 运行 解析 privateKeyInfo 算法所得的结果。

    3. 如果解析过程中发生错误, 则抛出一个 DataError

    4. 如果 privateKeyInfoprivateKeyAlgorithm PrivateKeyAlgorithm 字段的 algorithm 对象标识符字段不等于 [RFC5480] 中定义的 id-ecPublicKey 对象标识符, 则抛出一个 DataError

    5. 如果 privateKeyInfoprivateKeyAlgorithm PrivateKeyAlgorithmIdentifier 字段 的 parameters 字段不存在, 则抛出一个 DataError

    6. paramsprivateKeyInfoprivateKeyAlgorithm PrivateKeyAlgorithmIdentifier 字段 的 parameters 字段。

    7. 如果 params 不是 [RFC5480] 中定义的、指定了 namedCurveECParameters ASN.1 类型实例,则抛出一个 DataError

    8. namedCurve 为一个初始值为 undefined 的字符串。

    9. 如果 params 等价于 [RFC5480] 中定义的 secp256r1 对象标识符:

      namedCurve 设置为 "P-256"。

      如果 params 等价于 [RFC5480] 中定义的 secp384r1 对象标识符:

      namedCurve 设置为 "P-384"。

      如果 params 等价于 [RFC5480] 中定义的 secp521r1 对象标识符:

      namedCurve 设置为 "P-521"。

    10. 如果 namedCurve 不是 undefined:
      1. ecPrivateKey 为执行 解析 ASN.1 结构 算法所得的结果,其中 dataprivateKeyInfoprivateKey 字段,structure 为 [RFC5915] 第 3 节中指定的 ASN.1 ECPrivateKey 结构, 并将 exactData 设置为 true。

      2. 如果解析过程中发生错误, 则抛出 一个 DataError

      3. 如果 ecPrivateKeyparameters 字段 存在,并且不是 [RFC5480] 中定义的 namedCurve ASN.1 类型实例,或者不包含 与 privateKeyInfoprivateKeyAlgorithm PrivateKeyAlgorithmIdentifier 字段的 parameters 字段相同的对象标识符, 则抛出 一个 DataError

      4. key 为一个新的 CryptoKey, 它表示通过使用 ecPrivateKey 执行 [RFC5915] 第 3 节中定义的转换步骤所标识的椭圆曲线私钥。

      否则:
      1. 执行由 其他适用 规范定义的任何 密钥 导入步骤,传入 formatprivateKeyInfo 并获得 namedCurvekey

      2. 如果发生错误或不存在 适用 规范, 则抛出 一个 DataError

    11. 如果 namedCurve 已定义,且不等于 normalizedAlgorithmnamedCurve 成员,则抛出一个 DataError

    12. 如果私钥值不是 normalizedAlgorithmnamedCurve 成员所标识的椭圆曲线上的有效点,则抛出一个 DataError

    13. key[[type]] 内部槽 设置为 "private"

    14. algorithm 为一个新的 EcKeyAlgorithm

    15. algorithmname 属性设置为 "ECDSA"。

    16. algorithmnamedCurve 属性设置为 namedCurve

    17. key[[algorithm]] 内部槽设置为 algorithm

    如果 format 为 "jwk":
    1. 如果 keyData 是一个 JsonWebKey 字典:

      jwk 等于 keyData

      否则:

      抛出一个 DataError

    2. 如果 d 字段存在且 usages 包含 不是 "sign" 的值,或者, 如果 d 字段不存在 且 usages 包含 不是 "verify" 的值, 则抛出一个 SyntaxError

    3. 如果 jwkkty 字段 不是 "EC", 则抛出一个 DataError

    4. 如果 usages 非空,且 jwkuse 字段存在,并且 不是 "sig", 则抛出一个 DataError

    5. 如果 jwkkey_ops 字段存在,且 根据 JSON Web Key [JWK] 的要求无效,或者不包含 所有指定的 usages 值, 则抛出一个 DataError

    6. 如果 jwkext 字段存在且 值为 false,并且 extractable 为 true, 则抛出一个 DataError

    7. namedCurve 为一个字符串,其值等于 jwkcrv 字段。

    8. 如果 namedCurve 不等于 normalizedAlgorithmnamedCurve 成员,则抛出一个 DataError

    9. 如果 namedCurve 等于 "P-256"、 "P-384" 或 "P-521":
      1. algNamedCurve 为一个初始值为 undefined 的字符串。

      2. 如果 alg 字段不存在:
        algNamedCurve 为 undefined。
        如果 alg 字段等于字符串 "ES256":
        algNamedCurve 为字符串 "P-256"。
        如果 alg 字段等于字符串 "ES384":
        algNamedCurve 为字符串 "P-384"。
        如果 alg 字段等于字符串 "ES512":
        algNamedCurve 为字符串 "P-521"。
        否则:
        抛出 一个 DataError
      3. 如果 algNamedCurve 已定义,且不等于 namedCurve,则抛出 一个 DataError

      4. 如果 d 字段存在:
        1. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.2.2 节的要求, 则抛出 一个 DataError

        2. key 为一个新的 CryptoKey 对象,它表示按照 JSON Web Algorithms [JWA] 第 6.2.2 节解释 jwk 所标识的 椭圆曲线私钥。

        3. Key[[type]] 内部槽设置为 "private"。

        否则:
        1. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.2.1 节的要求, 则抛出 一个 DataError

        2. key 为一个新的 CryptoKey 对象,它表示按照 JSON Web Algorithms [JWA] 第 6.2.1 节解释 jwk 所标识的 椭圆曲线公钥。

        3. Key[[type]] 内部槽设置为 "public"。

      否则:
      1. 执行由 其他适用 规范定义的任何 密钥 导入步骤,传入 formatjwk 并获得 key

      2. 如果发生错误或不存在 适用 规范, 则抛出 一个 DataError

    10. 如果密钥值不是 normalizedAlgorithmnamedCurve 成员所标识的椭圆曲线上的有效点,则抛出一个 DataError

    11. algorithm 为一个新的 EcKeyAlgorithm 对象实例。

    12. algorithmname 属性设置为 "ECDSA"。

    13. algorithmnamedCurve 属性设置为 namedCurve

    14. key[[algorithm]] 内部槽设置为 algorithm

    如果 format 为 "raw":
    1. 如果 normalizedAlgorithmnamedCurve 成员不是命名曲线, 则抛出一个 DataError

    2. 如果 usages 包含不是 "verify" 的值, 则抛出一个 SyntaxError

    3. 如果 namedCurve 为 "P-256"、 "P-384" 或 "P-521":
      1. Q 为通过对 keyData 执行 [SEC1] 第 2.3.4 节中定义的转换步骤所标识的、 位于 normalizedAlgorithmnamedCurve 成员所标识曲线上的椭圆曲线点。

        未压缩点格式 MUST 被支持。

      2. 如果实现不支持压缩点 格式,并且提供了 压缩点, 则抛出 一个 DataError

      3. 如果发生解码错误或发现单位点, 则抛出 一个 DataError

      4. key 为一个新的 CryptoKey, 它表示 Q

      否则:
      1. 执行由 其他适用 规范定义的任何 密钥导入 步骤,传入 formatkeyData 并获得 key

      2. 如果发生错误或不存在 适用 规范, 则抛出 一个 DataError

    4. algorithm 为一个新的 EcKeyAlgorithm 对象。

    5. algorithmname 属性设置为 "ECDSA"。

    6. algorithmnamedCurve 属性设置为等于 normalizedAlgorithmnamedCurve 成员。

    7. key[[type]] 内部槽 设置为 "public"

    8. key[[algorithm]] 内部槽设置为 algorithm

    否则:

    抛出一个 NotSupportedError

  3. 返回 key

23.7.5 导出密钥

  1. key 为要导出的 CryptoKey

  2. 如果无法访问由 key[[handle]] 内部槽表示的 底层加密密钥材料, 则抛出一个 OperationError

  3. 如果 format 为 "spki":
    1. 如果 key[[type]] 内部槽 不是 "public",则抛出一个 InvalidAccessError

    2. data 为 [RFC5280] 中定义的 SubjectPublicKeyInfo ASN.1 结构的一个实例,并具有以下属性:

      • algorithm 字段设置为具有以下 属性的 AlgorithmIdentifier ASN.1 类型:

        • algorithm 字段设置为 [RFC5480] 中定义的 OID id-ecPublicKey

        • parameters 字段设置为 [RFC5480] 中定义的 ECParameters ASN.1 类型实例, 如下所示:

          如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-256"、 "P-384" 或 "P-521":

          keyData 为一个 字节 序列,其按照 [RFC5480] 第 2.2 节中指定的编码规则,并使用未压缩形式, 表示由 key[[handle]] 内部槽表示的椭圆曲线公钥。以及 keyData

          如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-256":

          parameters 设置为 namedCurve 选项, 其值等于 [RFC5480] 中定义的对象标识符 secp256r1

          如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-384":

          parameters 设置为 namedCurve 选项, 其值等于 [RFC5480] 中定义的对象标识符 secp384r1

          如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-521":

          parameters 设置为 namedCurve 选项, 其值等于 [RFC5480] 中定义的对象标识符 secp521r1

          否则:
          1. 执行由其他 适用 规范定义的任何 密钥 导出步骤,传入 formatkey[[algorithm]] 内部槽的 namedCurve 属性, 并获得 namedCurveOidkeyData

          2. parameters 设置为 namedCurve 选项, 其值等于对象标识符 namedCurveOid

      • subjectPublicKey 字段设置为 keyData

    3. result 为对 data 进行 DER 编码所得的结果。

    如果 format 为 "pkcs8":
    1. 如果 key[[type]] 内部槽 不是 "private",则抛出一个 InvalidAccessError

    2. data 为 [RFC5208] 中定义的 PrivateKeyInfo ASN.1 结构的一个实例,并具有以下属性:

      • version 字段设置为 0

      • privateKeyAlgorithm 字段设置为具有以下 属性的 PrivateKeyAlgorithmIdentifier ASN.1 类型:

        • algorithm 字段设置为 [RFC5480] 中定义的 OID id-ecPublicKey

        • parameters 字段设置为 [RFC5480] 中定义的 ECParameters ASN.1 类型实例, 如下所示:

          如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-256"、 "P-384" 或 "P-521":

          keyData 为 对 [RFC5915] 第 3 节中定义的 ECPrivateKey 结构的一个实例进行 DER 编码所得的结果,该实例用于 由 key[[handle]] 内部槽表示的椭圆 曲线私钥,并符合以下要求:

          • parameters 字段存在,并且等价于此 PrivateKeyInfo ASN.1 结构的 privateKeyAlgorithm 字段的 parameters 字段。

          • publicKey 字段存在,并表示 与由 key[[handle]] 内部槽表示的椭圆曲线 私钥相关联的椭圆曲线公钥。

          如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-256":

          parameters 设置为 namedCurve 选项, 其值等于 [RFC5480] 中定义的对象标识符 secp256r1

          如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-384":

          parameters 设置为 namedCurve 选项, 其值等于 [RFC5480] 中定义的对象标识符 secp384r1

          如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-521":

          parameters 设置为 namedCurve 选项, 其值等于 [RFC5480] 中定义的对象标识符 secp521r1

          否则:
          1. 执行由其他 适用 规范定义的任何 密钥 导出步骤,传入 formatkey[[algorithm]] 内部槽的 namedCurve 属性, 并获得 namedCurveOidkeyData

          2. parameters 设置为 namedCurve 选项, 其值等于对象标识符 namedCurveOid

      • privateKey 字段设置为 keyData

    3. result 为对 data 进行 DER 编码所得的结果。

    如果 format 为 "jwk":
    1. jwk 为一个新的 JsonWebKey 字典。

    2. jwkkty 属性设置为 "EC"。

    3. 如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-256"、"P-384" 或 "P-521":
      1. 如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-256":
        jwkcrv 属性设置为 "P-256"
        如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-384":
        jwkcrv 属性设置为 "P-384"
        如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-521":
        jwkcrv 属性设置为 "P-521"
      2. 按照 JSON Web Algorithms [JWA] 第 6.2.1.2 节中的定义,设置 jwkx 属性。

      3. 按照 JSON Web Algorithms [JWA] 第 6.2.1.3 节中的定义,设置 jwky 属性。

      4. 如果 key[[type]] 内部槽 为 "private"

        按照 JSON Web Algorithms [JWA] 第 6.2.2.1 节中的定义,设置 jwkd 属性。

      否则:
      1. 执行由其他 适用 规范定义的任何 密钥 导出步骤,传入 formatkey[[algorithm]] 内部槽的 namedCurve 属性, 并获得 namedCurvejwk 的新值。

      2. jwkcrv 属性设置为 namedCurve

    4. jwkkey_ops 属性设置为 keyusages 属性。

    5. jwkext 属性设置为 key[[extractable]] 内部槽。

    6. resultjwk

    如果 format 为 "raw":
    1. 如果 key[[type]] 内部槽 不是 "public",则抛出一个 InvalidAccessError

    2. 如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-256"、"P-384" 或 "P-521":

      data 为一个字节 序列,其按照 [SEC1] 第 2.3.3 节使用未压缩格式,表示由 key[[handle]] 内部槽表示的椭圆曲线 点 Q

      否则:

      执行由其他适用 规范定义的任何 密钥导出 步骤,传入 formatkey[[algorithm]] 内部槽的 namedCurve 属性, 并获得 namedCurvedata

    3. resultdata

    否则:

    抛出一个 NotSupportedError

  4. 返回 result

24. ECDH

24.1 描述

本节是非规范性的。

本节描述了使用 Elliptic Curve Diffie-Hellman (ECDH) 进行密钥生成和密钥 协商,如 [RFC6090] 所指定。

其他 规范 可以指定将其他椭圆曲线与 ECDH 一起使用。 要指定额外的椭圆曲线,规范必须定义 曲线名称ECDH 生成步骤ECDH 派生步骤ECDH 密钥导入步骤ECDH 密钥导出步骤

24.2 注册

此算法的已识别算法名称为 "ECDH"。

操作 参数 结果
generateKey EcKeyGenParams CryptoKeyPair
deriveBits EcdhKeyDeriveParams 字节 序列
importKey EcKeyImportParams CryptoKey
exportKey object

24.3 EcdhKeyDeriveParams 字典

WebIDLdictionary EcdhKeyDeriveParams : Algorithm {
  required CryptoKey public;
};

public 成员表示对等方的 EC 公钥。

24.4 操作

24.4.1 生成密钥

  1. 如果 usages 包含不是 "deriveKey" 或 "deriveBits" 的条目, 则抛出一个 SyntaxError

  2. 如果 normalizedAlgorithmnamedCurve 成员为 "P-256"、"P-384" 或 "P-521":

    按 [RFC6090] 中的定义生成一个椭圆曲线密钥对,其域参数用于 normalizedAlgorithmnamedCurve 成员 所标识的曲线。

    如果 normalizedAlgorithmnamedCurve 成员 是适用规范中指定的值,且 该规范指定了将此值与 ECDH 一起使用:

    执行该规范中指定的 ECDH 生成步骤, 传入 normalizedAlgorithm,并得到一个椭圆曲线密钥对。

    否则:

    抛出一个 NotSupportedError

  3. 如果执行该操作导致错误, 则抛出一个 OperationError

  4. algorithm 为一个新的 EcKeyAlgorithm 对象。

  5. algorithmname 成员设置为 "ECDH"。

  6. algorithmnamedCurve 属性设置为等于 normalizedAlgorithmnamedCurve 成员。

  7. publicKey 为一个新的 CryptoKey, 表示所生成密钥对的公钥。

  8. publicKey[[type]] 内部槽设置为 "public"

  9. publicKey[[algorithm]] 内部 槽设置为 algorithm

  10. publicKey[[extractable]] 内部 槽设置为 true。

  11. publicKey[[usages]] 内部槽 设置为空列表。

  12. privateKey 为一个新的 CryptoKey, 表示所生成密钥对的私钥。

  13. privateKey[[type]] 内部槽设置为 "private"

  14. privateKey[[algorithm]] 内部 槽设置为 algorithm

  15. privateKey[[extractable]] 内部 槽设置为 extractable

  16. privateKey[[usages]] 内部槽 设置为 usages[ "deriveKey", "deriveBits" ]用法交集

  17. result 为一个新的 CryptoKeyPair 字典。

  18. resultpublicKey 属性 设置为 publicKey

  19. resultprivateKey 属性 设置为 privateKey

  20. 返回 result

24.4.2 派生位

  1. 如果 key[[type]] 内部槽不是 "private",则 抛出一个 InvalidAccessError

  2. publicKeynormalizedAlgorithmpublic 成员。

  3. 如果 publicKey[[type]] 内部槽不是 "public",则抛出一个 InvalidAccessError

  4. 如果 publicKey[[algorithm]] 内部 槽的 name 属性不等于 key[[algorithm]] 内部 槽的 name 属性,则抛出一个 InvalidAccessError

  5. 如果 publicKey[[algorithm]] 内部 槽的 namedCurve 属性不等于 key[[algorithm]] 内部 槽的 namedCurve 属性,则 抛出一个 InvalidAccessError

  6. 如果 key[[algorithm]] 内部 槽的 namedCurve 属性 为 "P-256"、"P-384" 或 "P-521":
    1. 执行 [RFC6090] 第 4 节中指定的 ECDH 原语,其中 key 作为 EC 私钥 d,并以由 publicKey[[handle]] 内部槽表示的 EC 公钥作为 EC 公钥。

    2. secret 为一个字节序列, 其中包含将 [RFC6090] 第 6.2 节中定义的从域元素到 八位字节字符串的转换应用于 ECDH 原语输出所得的结果。

    如果 key[[algorithm]] 内部 槽的 namedCurve 属性 是适用规范中指定的值,且 该规范指定了将此值与 ECDH 一起使用:

    执行该规范中指定的 ECDH 派生步骤, 传入 keypublicKey,并得到 secret

    否则:

    抛出一个 NotSupportedError

  7. 如果执行该操作导致错误, 则抛出一个 OperationError

  8. 如果 length 为 null:
    返回 secret
    否则:
    如果 secret位长度小于 length
    抛出一个 OperationError
    否则:
    返回一个包含 secret 的前 length 位的字节序列。

24.4.3 导入密钥

  1. keyData 为要导入的密钥数据。

  2. 如果 format 为 "spki":
    1. 如果 usages 不是空的, 则抛出一个 SyntaxError

    2. spki 为对 keyData 运行 解析 subjectPublicKeyInfo 算法所得的结果

    3. 如果解析过程中发生错误, 则抛出一个 DataError

    4. 如果 spkialgorithm AlgorithmIdentifier 字段的 algorithm 对象标识符字段 不等于 [RFC5480] 中定义的 id-ecPublicKey 对象标识符,则抛出一个 DataError

    5. 如果 spkialgorithm AlgorithmIdentifier 字段的 parameters 字段缺失, 则抛出一个 DataError

    6. paramsspkialgorithm AlgorithmIdentifier 字段的 parameters 字段。

    7. 如果 params 不是 [RFC5480] 中定义的、指定了 namedCurveECParameters ASN.1 类型实例,则抛出一个 DataError

    8. namedCurve 为一个初始值为 undefined 的字符串。

    9. 如果 params 等价于 [RFC5480] 中定义的 secp256r1 对象标识符:

      namedCurve 设置为 "P-256"。

      如果 params 等价于 [RFC5480] 中定义的 secp384r1 对象标识符:

      namedCurve 设置为 "P-384"。

      如果 params 等价于 [RFC5480] 中定义的 secp521r1 对象标识符:

      namedCurve 设置为 "P-521"。

    10. 如果 namedCurve 不是 undefined:
      1. publicKey 为通过对 spkisubjectPublicKey 字段 执行 [SEC1] 第 2.3.4 节中定义的转换步骤 所标识的椭圆曲线公钥。

        未压缩点格式 MUST 被支持。

      2. 如果实现不支持压缩点 格式,并且提供了 压缩点, 则抛出 一个 DataError

      3. 如果发生解码错误或发现单位点, 则抛出 一个 DataError

      4. key 为一个新的 CryptoKey, 它表示 publicKey

      否则:
      1. 执行由 其他 适用 规范定义的任何 密钥导入 步骤,传入 formatspki 并获得 namedCurvekey

      2. 如果发生错误或不存在 适用 规范, 则抛出 一个 DataError

    11. 如果 namedCurve 已定义,且不等于 normalizedAlgorithmnamedCurve 成员,则抛出一个 DataError

    12. 如果密钥值不是 normalizedAlgorithmnamedCurve 成员所标识的椭圆曲线上的有效点,则抛出一个 DataError

    13. key[[type]] 内部槽 设置为 "public"

    14. algorithm 为一个新的 EcKeyAlgorithm

    15. algorithmname 属性设置为 "ECDH"。

    16. algorithmnamedCurve 属性设置为 namedCurve

    17. key[[algorithm]] 内部槽设置为 algorithm

    如果 format 为 "pkcs8":
    1. 如果 usages 包含不是 "deriveKey" 或 "deriveBits" 的条目, 则抛出一个 SyntaxError

    2. privateKeyInfo 为对 keyData 运行 解析 privateKeyInfo 算法所得的结果。

    3. 如果解析过程中发生错误, 则抛出一个 DataError

    4. 如果 privateKeyInfoprivateKeyAlgorithm PrivateKeyAlgorithm 字段的 algorithm 对象标识符字段不等于 [RFC5480] 中定义的 id-ecPublicKey 对象标识符, 则抛出一个 DataError

    5. 如果 privateKeyInfoprivateKeyAlgorithm PrivateKeyAlgorithmIdentifier 字段 的 parameters 字段不存在, 则抛出一个 DataError

    6. paramsprivateKeyInfoprivateKeyAlgorithm PrivateKeyAlgorithmIdentifier 字段 的 parameters 字段。

    7. 如果 params 不是 [RFC5480] 中定义的、指定了 namedCurveECParameters ASN.1 类型实例,则抛出一个 DataError

    8. namedCurve 为一个初始值为 undefined 的字符串。

    9. 如果 params 等价于 [RFC5480] 中定义的 secp256r1 对象标识符:

      namedCurve 设置为 "P-256"。

      如果 params 等价于 [RFC5480] 中定义的 secp384r1 对象标识符:

      namedCurve 设置为 "P-384"。

      如果 params 等价于 [RFC5480] 中定义的 secp521r1 对象标识符:

      namedCurve 设置为 "P-521"。

    10. 如果 namedCurve 不是 undefined:
      1. ecPrivateKey 为执行 解析 ASN.1 结构 算法所得的结果,其中 dataprivateKeyInfoprivateKey 字段,structure 为 [RFC5915] 第 3 节中指定的 ASN.1 ECPrivateKey 结构, 并将 exactData 设置为 true。

      2. 如果解析过程中发生错误, 则抛出 一个 DataError

      3. 如果 ecPrivateKeyparameters 字段 存在,并且不是 [RFC5480] 中定义的 namedCurve ASN.1 类型实例,或者不包含 与 privateKeyInfoprivateKeyAlgorithm PrivateKeyAlgorithmIdentifier 字段的 parameters 字段相同的对象标识符, 则抛出 一个 DataError

      4. key 为一个新的 CryptoKey, 它表示通过使用 ecPrivateKey 执行 [RFC5915] 第 3 节中定义的转换步骤所标识的椭圆曲线私钥。

      否则:
      1. 执行由 其他 适用 规范定义的任何 密钥导入 步骤,传入 formatprivateKeyInfo 并获得 namedCurvekey

      2. 如果发生错误或不存在 适用 规范, 则抛出 一个 DataError

    11. 如果 namedCurve 已定义,且不等于 normalizedAlgorithmnamedCurve 成员,则抛出一个 DataError

    12. 如果密钥值不是 normalizedAlgorithmnamedCurve 成员所标识的椭圆曲线上的有效点,则抛出一个 DataError

    13. key[[type]] 内部槽 设置为 "private"。

    14. algorithm 为一个新的 EcKeyAlgorithm

    15. algorithmname 属性设置为 "ECDH"。

    16. algorithmnamedCurve 属性设置为 namedCurve

    17. key[[algorithm]] 内部槽设置为 algorithm

    如果 format 为 "jwk":
    1. 如果 keyData 是一个 JsonWebKey 字典:

      jwk 等于 keyData

      否则:

      抛出一个 DataError

    2. 如果 d 字段存在,且 usages 包含不是 "deriveKey" 或 "deriveBits" 的条目, 则抛出一个 SyntaxError

    3. 如果 d 字段不存在,且 usages 不是 空的, 则抛出一个 SyntaxError

    4. 如果 jwkkty 字段 不是 "EC", 则抛出一个 DataError

    5. 如果 usages 非空,且 jwkuse 字段存在,并且 不等于 "enc",则抛出一个 DataError

    6. 如果 jwkkey_ops 字段存在,且 根据 JSON Web Key [JWK] 的要求无效,或者不包含 所有指定的 usages 值,则抛出一个 DataError

    7. 如果 jwkext 字段存在且 值为 false,并且 extractable 为 true, 则抛出一个 DataError

    8. namedCurve 为一个字符串,其值等于 jwkcrv 字段。

    9. 如果 namedCurve 不等于 normalizedAlgorithmnamedCurve 成员,则抛出一个 DataError

    10. 如果 namedCurve 为 "P-256"、 "P-384" 或 "P-521":
      如果 d 字段 存在:
      1. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.2.2 节的要求, 则抛出 一个 DataError

      2. key 为一个新的 CryptoKey 对象,它表示按照 JSON Web Algorithms [JWA] 第 6.2.2 节解释 jwk 所标识的 椭圆曲线私钥。

      3. Key[[type]] 内部槽设置为 "private"。

      否则:
      1. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.2.1 节的要求, 则抛出 一个 DataError

      2. key 为一个新的 CryptoKey 对象,它表示按照 JSON Web Algorithms [JWA] 第 6.2.1 节解释 jwk 所标识的椭圆曲线公钥。

      3. Key[[type]] 内部槽设置为 "public"。

      否则
      1. 执行由 其他 适用 规范定义的任何 密钥导入 步骤,传入 formatjwk 并获得 key

      2. 如果发生错误或不存在 适用 规范, 则抛出 一个 DataError

    11. 如果密钥值不是 normalizedAlgorithmnamedCurve 成员所标识的椭圆曲线上的有效点,则抛出一个 DataError

    12. algorithm 为一个新的 EcKeyAlgorithm 对象实例。

    13. algorithmname 属性设置为 "ECDH"。

    14. algorithmnamedCurve 属性设置为 namedCurve

    15. key[[algorithm]] 内部槽设置为 algorithm

    如果 format 为 "raw":
    1. 如果 normalizedAlgorithmnamedCurve 成员不是命名曲线, 则抛出一个 DataError

    2. 如果 usages 不是空列表, 则抛出一个 SyntaxError

    3. 如果 namedCurve 为 "P-256"、 "P-384" 或 "P-521":
      1. Q 为位于 normalizedAlgorithmnamedCurve 成员所标识曲线上的椭圆曲线公钥,该公钥通过对 keyData 执行 [SEC1] 第 2.3.4 节中定义的转换步骤来标识。

        未压缩点格式 MUST 被支持。

      2. 如果实现不支持压缩点 格式,并且提供了 压缩点, 则抛出 一个 DataError

      3. 如果发生解码错误或发现单位点, 则抛出 一个 DataError

      4. key 为一个新的 CryptoKey, 它表示 Q

      否则:
      1. 执行由 其他 适用 规范定义的任何 密钥导入 步骤,传入 formatkeyData 并获得 key

      2. 如果发生错误或不存在 适用 规范, 则抛出 一个 DataError

    4. algorithm 为一个新的 EcKeyAlgorithm 对象。

    5. algorithmname 属性设置为 "ECDH"。

    6. algorithmnamedCurve 属性设置为等于 normalizedAlgorithmnamedCurve 成员。

    7. key[[type]] 内部槽 设置为 "public"

    8. key[[algorithm]] 内部槽设置为 algorithm

  3. 返回 key

24.4.4 导出密钥

  1. key 为要导出的 CryptoKey

  2. 如果无法访问由 key[[handle]] 内部槽表示的 底层加密密钥材料, 则抛出一个 OperationError

  3. 如果 format 为 "spki":
    1. 如果 key[[type]] 内部槽 不是 "public",则抛出一个 InvalidAccessError

    2. data 为 [RFC5280] 中定义的 SubjectPublicKeyInfo ASN.1 结构的一个实例,并具有以下属性:

      • algorithm 字段设置为具有以下 属性的 AlgorithmIdentifier ASN.1 类型:

        • algorithm 字段设置为 [RFC5480] 中定义的 OID id-ecPublicKey

        • parameters 字段设置为 [RFC5480] 中定义的 ECParameters ASN.1 类型实例, 如下所示:

          如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-256"、 "P-384" 或 "P-521":

          keyData 为一个字节 序列,其按照 [SEC1] 第 2.3.3 节中指定的编码规则并使用 未压缩形式,表示由 key[[handle]] 内部槽表示的椭圆曲线公钥。

          如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-256":

          parameters 设置为 namedCurve 选择, 其值等于 [RFC5480] 中定义的对象标识符 secp256r1

          如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-384":

          parameters 设置为 namedCurve 选择, 其值等于 [RFC5480] 中定义的对象标识符 secp384r1

          如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-521":

          parameters 设置为 namedCurve 选择, 其值等于 [RFC5480] 中定义的对象标识符 secp521r1

          否则:
          1. 执行由其他 适用 规范定义的任何 密钥 导出步骤,传入 formatkey[[algorithm]] 内部槽的 namedCurve 属性,并获得 namedCurveOidkeyData

          2. parameters 设置为 namedCurve 选择, 其值等于对象标识符 namedCurveOid

      • subjectPublicKey 字段设置为 keyData

    如果 format 为 "pkcs8":
    1. 如果 key[[type]] 内部槽 不是 "private",则抛出一个 InvalidAccessError

    2. data 为 [RFC5208] 中定义的 PrivateKeyInfo ASN.1 结构的一个实例,并具有以下属性:

      • version 字段设置为 0

      • privateKeyAlgorithm 字段设置为具有以下 属性的 PrivateKeyAlgorithmIdentifier ASN.1 类型:

        • algorithm 字段设置为 [RFC5480] 中定义的 OID id-ecPublicKey

        • parameters 字段设置为 [RFC5480] 中定义的 ECParameters ASN.1 类型实例, 如下所示:

          如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-256"、 "P-384" 或 "P-521":

          keyData 为对 [RFC5915] 第 3 节中定义的 ECPrivateKey 结构的一个实例进行 DER 编码所得的结果,该实例用于由 key[[handle]] 内部槽表示的椭圆 曲线私钥,并符合以下要求:

          • parameters 字段存在,并且等价于此 PrivateKeyInfo ASN.1 结构的 privateKeyAlgorithm 字段的 parameters 字段。

          • publicKey 字段存在,并表示 与由 key[[handle]] 内部槽表示的椭圆曲线 私钥相关联的椭圆曲线公钥。

          如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-256":

          parameters 设置为 namedCurve 选择, 其值等于 [RFC5480] 中定义的对象标识符 secp256r1

          如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-384":

          parameters 设置为 namedCurve 选择, 其值等于 [RFC5480] 中定义的对象标识符 secp384r1

          如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-521":

          parameters 设置为 namedCurve 选择, 其值等于 [RFC5480] 中定义的对象标识符 secp521r1

          否则:
          1. 执行由其他 适用 规范定义的任何 密钥 导出步骤,传入 formatkey[[algorithm]] 内部槽的 namedCurve 属性,并获得 namedCurveOidkeyData

          2. parameters 设置为 namedCurve 选择, 其值等于对象标识符 namedCurveOid

      • privateKey 字段设置为 keyData

    如果 format 为 "jwk":
    1. jwk 为一个新的 JsonWebKey 字典。

    2. jwkkty 属性设置为 "EC"。

    3. 如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-256"、"P-384" 或 "P-521":
      1. 如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-256":
        jwkcrv 属性设置为 "P-256"
        如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-384":
        jwkcrv 属性设置为 "P-384"
        如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-521":
        jwkcrv 属性设置为 "P-521"
      2. 按照 JSON Web Algorithms [JWA] 第 6.2.1.2 节中的定义,设置 jwkx 属性。

      3. 按照 JSON Web Algorithms [JWA] 第 6.2.1.3 节中的定义,设置 jwky 属性。

      4. 如果 key[[type]] 内部槽为 "private"

        按照 JSON Web Algorithms [JWA] 第 6.2.2.1 节中的定义,设置 jwkd 属性。

      否则:
      1. 执行由其他 适用 规范定义的任何 密钥导出 步骤,传入 formatkey[[algorithm]] 内部槽的 namedCurve 属性, 并获得 namedCurvejwk 的新值。

      2. jwkcrv 属性设置为 namedCurve

    4. jwkkey_ops 属性设置为 keyusages 属性。

    5. jwkext 属性设置为 key[[extractable]] 内部槽。

    6. resultjwk

    如果 format 为 "raw":
    1. 如果 key[[type]] 内部槽 不是 "public",则抛出一个 InvalidAccessError

    2. 如果 key[[algorithm]] 内部槽的 namedCurve 属性为 "P-256"、"P-384" 或 "P-521":

      data 为一个字节 序列,其按照 [SEC1] 第 2.3.3 节中指定的编码规则并使用 未压缩形式,表示由 key[[handle]] 内部槽表示的椭圆曲线公钥。

      否则:

      执行由其他适用 规范定义的任何 密钥导出 步骤,传入 formatkey[[algorithm]] 内部槽的 namedCurve 属性, 并获得 namedCurvedata

    3. resultdata

  4. 返回 result

25. Ed25519

25.1 描述

本节是非规范性的。

"Ed25519" 算法标识符用于使用 [RFC8032] 中指定的 Ed25519 算法执行签名 和验证。

25.2 注册

此算法的已识别算法名称为 "Ed25519"。

操作 参数 结果
sign 字节 序列
verify boolean
generateKey CryptoKeyPair
importKey CryptoKey
exportKey object

25.3 操作

25.3.1 签名

  1. 如果 key[[type]] 内部槽不是 "private",则 抛出一个 InvalidAccessError

  2. result 为执行 [RFC8032] 第 5.1.6 节中指定的 Ed25519 签名过程所得的结果,其中 message 作为 M, 并使用与 key 关联的 Ed25519 私钥。

    问题 1

    某些实现可能(希望)按照 draft-irtf-cfrg-det-sigs-with-noise 生成随机化签名,而不是按照 [RFC8032] 生成确定性签名。

    参见 WICG/webcrypto-secure-curves 议题 28

  3. 返回 result

25.3.2 验证

  1. 如果 key[[type]] 内部槽不是 "public",则抛出一个 InvalidAccessError

  2. 如果 key 的密钥数据表示 Ed25519 椭圆曲线上的无效点或 小阶元素,则返回 false

    问题 2

    并非所有实现都会执行此检查。

    参见 WICG/webcrypto-secure-curves 议题 27

  3. 如果编码在 signature 前半部分中的点 R 表示 Ed25519 椭圆曲线上的无效点或 小阶元素,则返回 false

    问题 3

    并非所有实现都会执行此检查。

    参见 WICG/webcrypto-secure-curves 议题 27

  4. 执行 [RFC8032] 第 5.1.7 节中指定的 Ed25519 验证步骤,使用无余因子(非批处理)方程 [S]B = R + [k]A',对 signature 进行验证,其中 message 作为 M, 并使用与 key 关联的 Ed25519 公钥。

  5. result 为一个 boolean;如果签名 有效,则其值为 true, 否则其值为 false

  6. 返回 result

25.3.3 生成密钥

  1. 如果 usages 包含不是 "sign" 或 "verify" 之一的值, 则抛出一个 SyntaxError

  2. 按 [RFC8032] 第 5.1.5 节中的定义生成一个 Ed25519 密钥对。

  3. algorithm 为一个新的 KeyAlgorithm 对象。

  4. algorithmname 属性设置为 "Ed25519"。

  5. publicKey 为一个新的 CryptoKey, 表示所生成密钥对的公钥。

  6. publicKey[[type]] 内部槽设置为 "public"

  7. publicKey[[algorithm]] 内部 槽设置为 algorithm

  8. publicKey[[extractable]] 内部 槽设置为 true。

  9. publicKey[[usages]] 内部槽 设置为 usages[ "verify" ]用法交集

  10. privateKey 为一个新的 CryptoKey, 表示所生成密钥对的私钥。

  11. privateKey[[type]] 内部槽设置为 "private"

  12. privateKey[[algorithm]] 内部 槽设置为 algorithm

  13. privateKey[[extractable]] 内部 槽设置为 extractable

  14. privateKey[[usages]] 内部槽 设置为 usages[ "sign" ]用法交集

  15. result 为一个新的 CryptoKeyPair 字典。

  16. resultpublicKey 属性 设置为 publicKey

  17. resultprivateKey 属性 设置为 privateKey

  18. 返回 result

25.3.4 导入密钥

  1. keyData 为要导入的密钥数据。

  2. 如果 format 为 "spki":
    1. 如果 usages 包含不是 "verify" 的值, 则抛出一个 SyntaxError

    2. spki 为对 keyData 运行 解析 subjectPublicKeyInfo 算法所得的结果。

    3. 如果解析过程中发生错误, 则抛出一个 DataError

    4. 如果 spkialgorithm AlgorithmIdentifier 字段的 algorithm 对象标识符字段 不等于 [RFC8410] 中定义的 id-Ed25519 对象标识符,则抛出一个 DataError

    5. 如果 spkialgorithm AlgorithmIdentifier 字段的 parameters 字段存在, 则抛出一个 DataError

    6. publicKey 为由 spkisubjectPublicKey 字段标识的 Ed25519 公钥。

    7. key 为一个新的 CryptoKey, 它表示 publicKey

    8. key[[type]] 内部槽 设置为 "public"

    9. algorithm 为一个新的 KeyAlgorithm

    10. algorithmname 属性设置为 "Ed25519"。

    11. key[[algorithm]] 内部槽设置为 algorithm

    如果 format 为 "pkcs8":
    1. 如果 usages 包含不是 "sign" 的值, 则抛出一个 SyntaxError

    2. privateKeyInfo 为对 keyData 运行 解析 privateKeyInfo 算法所得的结果。

    3. 如果解析过程中发生错误, 则抛出一个 DataError

    4. 如果 privateKeyInfoprivateKeyAlgorithm PrivateKeyAlgorithm 字段的 algorithm 对象标识符字段不等于 [RFC8410] 中定义的 id-Ed25519 对象标识符, 则抛出一个 DataError

    5. 如果 privateKeyInfoprivateKeyAlgorithm PrivateKeyAlgorithmIdentifier 字段 的 parameters 字段存在, 则抛出一个 DataError

    6. curvePrivateKey 为执行 解析 ASN.1 结构 算法所得的结果,其中 dataprivateKeyInfoprivateKey 字段, structure 为 [RFC8410] 第 7 节中指定的 ASN.1 CurvePrivateKey 结构, 并将 exactData 设置为 true。

    7. 如果解析过程中发生错误, 则抛出一个 DataError

    8. key 为一个新的 CryptoKey, 它表示由 curvePrivateKey 标识的 Ed25519 私钥。

    9. key[[type]] 内部槽 设置为 "private"

    10. algorithm 为一个新的 KeyAlgorithm

    11. algorithmname 属性设置为 "Ed25519"。

    12. key[[algorithm]] 内部槽设置为 algorithm

    如果 format 为 "jwk":
    1. 如果 keyData 是一个 JsonWebKey 字典:

      jwk 等于 keyData

      否则:

      抛出一个 DataError

    2. 如果 d 字段存在且 usages 包含 不是 "sign" 的值,或者, 如果 d 字段不存在 且 usages 包含 不是 "verify" 的值, 则抛出一个 SyntaxError

    3. 如果 jwkkty 字段不是 "OKP", 则抛出一个 DataError

    4. 如果 jwkcrv 字段不是 "Ed25519", 则抛出一个 DataError

    5. 如果 jwkalg 字段存在,且 不是 "Ed25519" 或 "EdDSA", 则抛出一个 DataError

    6. 如果 usages 非空,且 jwkuse 字段存在,且 不是 "sig", 则抛出一个 DataError

    7. 如果 jwkkey_ops 字段存在,且 根据 JSON Web Key [JWK] 的要求无效,或者不包含 所有指定的 usages 值, 则抛出一个 DataError

    8. 如果 jwkext 字段存在且 值为 false,并且 extractable 为 true, 则抛出一个 DataError

    9. 如果 d 字段 存在:
      1. 如果 jwk 不满足 [RFC8037] 第 2 节中描述的 JWK 私钥格式要求, 则抛出 一个 DataError

      2. key 为一个新的 CryptoKey 对象,它表示按照 [RFC8037] 第 2 节解释 jwk 所标识的 Ed25519 私钥。

      3. Key[[type]] 内部槽设置为 "private"。

      否则:
      1. 如果 jwk 不满足 [RFC8037] 第 2 节中描述的 JWK 公钥格式要求, 则抛出 一个 DataError

      2. key 为一个新的 CryptoKey 对象,它表示按照 [RFC8037] 第 2 节解释 jwk 所标识的 Ed25519 公钥。

      3. Key[[type]] 内部槽设置为 "public"。

    10. algorithm 为一个新的 KeyAlgorithm 对象实例。

    11. algorithmname 属性设置为 "Ed25519"。

    12. key[[algorithm]] 内部槽设置为 algorithm

    如果 format 为 "raw":
    1. 如果 usages 包含不是 "verify" 的值, 则抛出一个 SyntaxError

    2. algorithm 为一个新的 KeyAlgorithm 对象。

    3. algorithmname 属性设置为 "Ed25519"。

    4. key 为一个新的 CryptoKey, 表示 keyData 中提供的密钥数据。

    5. key[[type]] 内部槽 设置为 "public"

    6. key[[algorithm]] 内部槽设置为 algorithm

    否则:

    抛出一个 NotSupportedError

  3. 返回 key

25.3.5 导出密钥

  1. key 为要导出的 CryptoKey

  2. 如果无法访问由 key[[handle]] 内部槽表示的 底层加密密钥材料, 则抛出一个 OperationError

  3. 如果 format 为 "spki":
    1. 如果 key[[type]] 内部槽 不是 "public",则抛出一个 InvalidAccessError

    2. data 为 [RFC5280] 中定义的 SubjectPublicKeyInfo ASN.1 结构的一个实例,并具有以下属性:

      • algorithm 字段设置为具有以下 属性的 AlgorithmIdentifier ASN.1 类型:

        • algorithm 对象标识符设置为 [RFC8410] 中定义的 id-Ed25519 OID。

      • subjectPublicKey 字段设置为 keyData

    3. result 为对 data 进行 DER 编码所得的结果。

    如果 format 为 "pkcs8":
    1. 如果 key[[type]] 内部槽 不是 "private",则抛出一个 InvalidAccessError

    2. data 为 [RFC5208] 中定义的 PrivateKeyInfo ASN.1 结构的一个实例,并具有以下属性:

      • version 字段设置为 0

      • privateKeyAlgorithm 字段设置为具有以下 属性的 PrivateKeyAlgorithmIdentifier ASN.1 类型:

        • algorithm 对象标识符设置为 [RFC8410] 中定义的 id-Ed25519 OID。

      • privateKey 字段设置为对 [RFC8410] 第 7 节中定义的 CurvePrivateKey ASN.1 类型进行 DER 编码所得的结果, 该类型表示由 key[[handle]] 内部槽表示的 Ed25519 私钥

    3. result 为对 data 进行 DER 编码所得的结果。

    如果 format 为 "jwk":
    1. jwk 为一个新的 JsonWebKey 字典。

    2. jwkkty 属性设置为 "OKP"。

    3. jwkalg 属性设置为 "Ed25519"。

    4. jwkcrv 属性设置为 "Ed25519"。

    5. 按照 [RFC8037] 第 2 节中的定义,设置 jwkx 属性。

    6. 如果 key[[type]] 内部槽为 "private"
      按照 [RFC8037] 第 2 节中的定义,设置 jwkd 属性。
    7. jwkkey_ops 属性设置为 keyusages 属性。

    8. jwkext 属性设置为 key[[extractable]] 内部槽。

    9. resultjwk

    如果 format 为 "raw":
    1. 如果 key[[type]] 内部槽 不是 "public",则抛出一个 InvalidAccessError

    2. data 为表示 Ed25519 公钥的字节序列, 该公钥由 key[[handle]] 内部槽表示。

    3. resultdata

    否则:

    抛出一个 NotSupportedError

  4. 返回 result

26. X25519

26.1 描述

本节是非规范性的。

"X25519" 算法标识符用于使用 [RFC7748] 中指定的 X25519 算法执行密钥协商。

26.2 注册

此算法的已识别算法名称为 "X25519"。

操作 参数 结果
deriveBits EcdhKeyDeriveParams 字节 序列
generateKey CryptoKeyPair
importKey CryptoKey
exportKey object

26.3 操作

26.3.1 派生位

  1. 如果 key[[type]] 内部槽不是 "private",则 抛出一个 InvalidAccessError

  2. publicKeynormalizedAlgorithmpublic 成员。

  3. 如果 publicKey[[type]] 内部槽不是 "public",则抛出一个 InvalidAccessError

  4. 如果 publicKey[[algorithm]] 内部 槽的 name 属性不等于 key[[algorithm]] 内部 槽的 name 属性,则抛出一个 InvalidAccessError

  5. secret 为执行 [RFC7748] 第 5 节中指定的 X25519 函数所得的结果,其中 key 作为 X25519 私钥 k, 且由 publicKey[[handle]] 内部槽表示的 X25519 公钥作为 X25519 公钥 u

  6. 如果 secret 为全零值, 则抛出一个 OperationError。 按 [RFC7748] 第 6.1 节,此检查必须以常数时间执行。

  7. 如果 length 为 null:
    返回 secret
    否则:
    如果 secret 的位长度小于 length
    抛出一个 OperationError
    否则:
    返回一个包含 secret 的前 length 位的字节序列。

26.3.2 生成密钥

  1. 如果 usages 包含不是 "deriveKey" 或 "deriveBits" 的条目, 则抛出一个 SyntaxError

  2. 按 [RFC7748] 第 6.1 节中的定义生成一个 X25519 密钥对,其中私钥为 32 个随机字节, 公钥为 X25519(a, 9)

  3. algorithm 为一个新的 KeyAlgorithm 对象。

  4. algorithmname 属性设置为 "X25519"。

  5. publicKey 为一个新的 CryptoKey, 表示所生成密钥对的公钥。

  6. publicKey[[type]] 内部槽设置为 "public"

  7. publicKey[[algorithm]] 内部 槽设置为 algorithm

  8. publicKey[[extractable]] 内部 槽设置为 true。

  9. publicKey[[usages]] 内部槽 设置为空列表。

  10. privateKey 为一个新的 CryptoKey, 表示所生成密钥对的私钥。

  11. privateKey[[type]] 内部槽设置为 "private"

  12. privateKey[[algorithm]] 内部 槽设置为 algorithm

  13. privateKey[[extractable]] 内部 槽设置为 extractable

  14. privateKey[[usages]] 内部槽 设置为 usages[ "deriveKey", "deriveBits" ]用法交集

  15. result 为一个新的 CryptoKeyPair 字典。

  16. resultpublicKey 属性 设置为 publicKey

  17. resultprivateKey 属性 设置为 privateKey

  18. 返回 result

26.3.3 导入密钥

  1. keyData 为要导入的密钥数据。

  2. 如果 format 为 "spki":
    1. 如果 usages 不是空的, 则抛出一个 SyntaxError

    2. spki 为对 keyData 运行 解析 subjectPublicKeyInfo 算法所得的结果。

    3. 如果解析过程中发生错误, 则抛出一个 DataError

    4. 如果 spkialgorithm AlgorithmIdentifier 字段的 algorithm 对象标识符字段 不等于 [RFC8410] 中定义的 id-X25519 对象标识符,则抛出一个 DataError

    5. 如果 spkialgorithm AlgorithmIdentifier 字段的 parameters 字段存在, 则抛出一个 DataError

    6. publicKey 为由 spkisubjectPublicKey 字段标识的 X25519 公钥。

    7. key 为一个新的 CryptoKey, 它表示 publicKey

    8. key[[type]] 内部槽 设置为 "public"

    9. algorithm 为一个新的 KeyAlgorithm

    10. algorithmname 属性设置为 "X25519"。

    11. key[[algorithm]] 内部槽设置为 algorithm

    如果 format 为 "pkcs8":
    1. 如果 usages 包含不是 "deriveKey" 或 "deriveBits" 的条目, 则抛出一个 SyntaxError

    2. privateKeyInfo 为对 keyData 运行 解析 privateKeyInfo 算法所得的结果。

    3. 如果解析过程中发生错误, 则抛出一个 DataError

    4. 如果 privateKeyInfoprivateKeyAlgorithm PrivateKeyAlgorithm 字段的 algorithm 对象标识符字段不等于 [RFC8410] 中定义的 id-X25519 对象标识符, 则抛出一个 DataError

    5. 如果 privateKeyInfoprivateKeyAlgorithm PrivateKeyAlgorithmIdentifier 字段 的 parameters 字段存在, 则抛出一个 DataError

    6. curvePrivateKey 为执行 解析 ASN.1 结构 算法所得的结果,其中 dataprivateKeyInfoprivateKey 字段, structure 为 [RFC8410] 第 7 节中指定的 ASN.1 CurvePrivateKey 结构, 并将 exactData 设置为 true。

    7. 如果解析过程中发生错误, 则抛出一个 DataError

    8. key 为一个新的 CryptoKey, 它表示由 curvePrivateKey 标识的 X25519 私钥。

    9. key[[type]] 内部槽 设置为 "private"

    10. algorithm 为一个新的 KeyAlgorithm

    11. algorithmname 属性设置为 "X25519"。

    12. key[[algorithm]] 内部槽设置为 algorithm

    如果 format 为 "jwk":
    1. 如果 keyData 是一个 JsonWebKey 字典:

      jwk 等于 keyData

      否则:

      抛出一个 DataError

    2. 如果 d 字段存在,且 usages 包含不是 "deriveKey" 或 "deriveBits" 的条目, 则抛出一个 SyntaxError

    3. 如果 d 字段不存在,且 usages 不是 空的, 则抛出一个 SyntaxError

    4. 如果 jwkkty 字段不是 "OKP", 则抛出一个 DataError

    5. 如果 jwkcrv 字段不是 "X25519", 则抛出一个 DataError

    6. 如果 usages 非空,且 jwkuse 字段存在 且不等于 "enc",则抛出一个 DataError

    7. 如果 jwkkey_ops 字段存在,且 根据 JSON Web Key [JWK] 的要求无效,或者不包含 所有指定的 usages 值, 则抛出一个 DataError

    8. 如果 jwkext 字段存在且 值为 false,并且 extractable 为 true, 则抛出一个 DataError

    9. 如果 d 字段 存在:
      1. 如果 jwk 不满足 [RFC8037] 第 2 节中描述的 JWK 私钥格式要求, 则抛出 一个 DataError

      2. key 为一个新的 CryptoKey 对象,它表示按照 [RFC8037] 第 2 节解释 jwk 所标识的 X25519 私钥。

      3. Key[[type]] 内部槽设置为 "private"。

      否则:
      1. 如果 jwk 不满足 [RFC8037] 第 2 节中描述的 JWK 公钥格式要求, 则抛出 一个 DataError

      2. key 为一个新的 CryptoKey 对象,它表示按照 [RFC8037] 第 2 节解释 jwk 所标识的 X25519 公钥。

      3. Key[[type]] 内部槽设置为 "public"。

    10. algorithm 为一个新的 KeyAlgorithm 对象实例。

    11. algorithmname 属性设置为 "X25519"。

    12. key[[algorithm]] 内部槽设置为 algorithm

    如果 format 为 "raw":
    1. 如果 usages 不是空的, 则抛出一个 SyntaxError

    2. algorithm 为一个新的 KeyAlgorithm 对象。

    3. algorithmname 属性设置为 "X25519"。

    4. key 为一个新的 CryptoKey, 表示 keyData 中提供的密钥数据。

    5. key[[type]] 内部槽 设置为 "public"

    6. key[[algorithm]] 内部槽设置为 algorithm

    否则:

    抛出一个 NotSupportedError

  3. 返回 key

26.3.4 导出密钥

  1. key 为要导出的 CryptoKey

  2. 如果无法访问由 key[[handle]] 内部槽表示的 底层加密密钥材料, 则抛出一个 OperationError

  3. 如果 format 为 "spki":
    1. 如果 key[[type]] 内部槽 不是 "public",则抛出一个 InvalidAccessError

    2. data 为 [RFC5280] 中定义的 SubjectPublicKeyInfo ASN.1 结构的一个实例,并具有以下属性:

      • algorithm 字段设置为具有以下 属性的 AlgorithmIdentifier ASN.1 类型:

        • algorithm 对象标识符设置为 [RFC8410] 中定义的 id-X25519 OID。

      • subjectPublicKey 字段设置为 keyData

    3. result 为对 data 进行 DER 编码所得的结果。

    如果 format 为 "pkcs8":
    1. 如果 key[[type]] 内部槽 不是 "private",则抛出一个 InvalidAccessError

    2. data 为 [RFC5208] 中定义的 PrivateKeyInfo ASN.1 结构的一个实例,并具有以下属性:

      • version 字段设置为 0

      • privateKeyAlgorithm 字段设置为具有以下 属性的 PrivateKeyAlgorithmIdentifier ASN.1 类型:

        • algorithm 对象标识符设置为 [RFC8410] 中定义的 id-X25519 OID。

      • privateKey 字段设置为对 [RFC8410] 第 7 节中定义的 CurvePrivateKey ASN.1 类型进行 DER 编码所得的结果, 该类型表示由 key[[handle]] 内部槽表示的 X25519 私钥

    3. result 为对 data 进行 DER 编码所得的结果。

    如果 format 为 "jwk":
    1. jwk 为一个新的 JsonWebKey 字典。

    2. jwkkty 属性设置为 "OKP"。

    3. jwkcrv 属性设置为 "X25519"。

    4. 按照 [RFC8037] 第 2 节中的定义,设置 jwkx 属性。

    5. 如果 key[[type]] 内部槽为 "private"
      按照 [RFC8037] 第 2 节中的定义,设置 jwkd 属性。
    6. jwkkey_ops 属性设置为 keyusages 属性。

    7. jwkext 属性设置为 key[[extractable]] 内部槽。

    8. resultjwk

    如果 format 为 "raw":
    1. 如果 key[[type]] 内部槽 不是 "public",则抛出一个 InvalidAccessError

    2. data 为表示 X25519 公钥的字节序列, 该公钥由 key[[handle]] 内部槽表示。

    3. resultdata

    否则:

    抛出一个 NotSupportedError

  4. 返回 result

27. AES-CTR

27.1 描述

本节是非规范性的。

"AES-CTR" 算法标识符用于使用计数器模式下的 AES 执行加密和解密,如 [NIST-SP800-38A] 中所述。

27.2 注册

此算法的已识别算法名称为 "AES-CTR"。

操作 参数 结果
encrypt AesCtrParams 字节 序列
decrypt AesCtrParams 字节 序列
generateKey AesKeyGenParams CryptoKey
importKey CryptoKey
exportKey object
get key length AesDerivedKeyParams Integer

27.3 AesCtrParams 字典

WebIDLdictionary AesCtrParams : Algorithm {
  required BufferSource counter;
  required [EnforceRange] octet length;
};

counter 成员包含计数器块的初始值。 counter MUST 为 16 字节(AES 块大小)。计数器位是计数器块最右侧的 length 位。计数器块的其余部分用于 nonce。计数器位使用 NIST SP 800-38A 附录 B.1 中指定的标准 递增函数来递增: 计数器位被解释为一个大端整数,并 加一。

length 成员包含计数器块中 被递增的最右侧部分的长度(以位为单位)。

27.4 AesKeyAlgorithm 字典

WebIDLdictionary AesKeyAlgorithm : KeyAlgorithm {
  required unsigned short length;
};

length 成员表示密钥的长度(以位为单位)。

27.5 AesKeyGenParams 字典

WebIDLdictionary AesKeyGenParams : Algorithm {
  required [EnforceRange] unsigned short length;
};

length 成员表示密钥的长度(以位为单位)。

27.6 AesDerivedKeyParams 字典

WebIDLdictionary AesDerivedKeyParams : Algorithm {
  required [EnforceRange] unsigned short length;
};

length 成员表示密钥的长度(以位为单位)。

27.7 操作

27.7.1 加密

  1. 如果 normalizedAlgorithmcounter 成员的 长度不是 16 字节, 则抛出一个 OperationError

  2. 如果 normalizedAlgorithmlength 成员为零或大于 128, 则抛出一个 OperationError

  3. ciphertext 为执行 [NIST-SP800-38A] 第 6.5 节中描述的 CTR Encryption 操作所得的结果,其中使用 AES 作为分组密码, 使用 normalizedAlgorithmcounter 成员作为计数器块的初始值,使用 normalizedAlgorithmlength 成员作为 [NIST-SP800-38A] 附录 B.1 中定义的标准计数器块递增函数的输入参数 m, 并使用 plaintext 作为输入明文。

  4. 返回 ciphertext

27.7.2 解密

  1. 如果 normalizedAlgorithmcounter 成员的 长度不是 16 字节, 则抛出一个 OperationError

  2. 如果 normalizedAlgorithmlength 成员为零或大于 128, 则抛出一个 OperationError

  3. plaintext 为执行 [NIST-SP800-38A] 第 6.5 节中描述的 CTR Decryption 操作所得的结果,其中使用 AES 作为分组密码, 使用 normalizedAlgorithmcounter 成员作为计数器块的初始值,使用 normalizedAlgorithmlength 成员作为 [NIST-SP800-38A] 附录 B.1 中定义的标准计数器块递增函数的输入参数 m, 并使用 ciphertext 作为输入密文。

  4. 返回 plaintext

27.7.3 生成密钥

  1. 如果 usages 包含不是 "encrypt"、"decrypt"、 "wrapKey" 或 "unwrapKey" 之一的任何条目, 则抛出一个 SyntaxError

  2. 如果 normalizedAlgorithmlength 成员不等于 128、192 或 256 之一, 则抛出一个 OperationError

  3. 生成一个长度等于 normalizedAlgorithmlength 成员的 AES 密钥。

  4. 如果密钥生成步骤失败, 则抛出一个 OperationError

  5. key 为一个新的 CryptoKey 对象,表示所生成的 AES 密钥。

  6. algorithm 为一个新的 AesKeyAlgorithm

  7. algorithmname 属性设置为 "AES-CTR"。

  8. algorithmlength 属性设置为等于 normalizedAlgorithmlength 成员。

  9. key[[type]] 内部槽设置为 "secret"。

  10. key[[algorithm]] 内部 槽设置为 algorithm

  11. key[[extractable]] 内部 槽设置为 extractable

  12. key[[usages]] 内部槽 设置为 usages

  13. 返回 key

27.7.4 导入密钥

  1. 如果 usages 包含不是 "encrypt"、"decrypt"、 "wrapKey" 或 "unwrapKey" 之一的条目, 则抛出一个 SyntaxError

  2. 如果 format 为 "raw":
    1. datakeyData

    2. 如果 data位长度 不是 128、192 或 256, 则抛出一个 DataError

    如果 format 为 "jwk":
    1. 如果 keyData 是一个 JsonWebKey 字典:

      jwk 等于 keyData

      否则:

      抛出一个 DataError

    2. 如果 jwkkty 字段不是 "oct", 则抛出一个 DataError

    3. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.4 节的要求, 则抛出一个 DataError

    4. data 为通过解码 jwkk 字段 获得的字节序列

    5. 如果 data位长度 为 128:
      如果 jwkalg 字段存在,且 不是 "A128CTR",则抛出一个 DataError
      如果 data位长度 为 192:
      如果 jwkalg 字段存在,且 不是 "A192CTR",则抛出一个 DataError
      如果 data位长度 为 256:
      如果 jwkalg 字段存在,且 不是 "A256CTR",则抛出一个 DataError
      否则:
      抛出一个 DataError
    6. 如果 usages 非空,且 jwkuse 字段存在,并且 不是 "enc", 则抛出一个 DataError

    7. 如果 jwkkey_ops 字段存在,且 根据 JSON Web Key [JWK] 的要求无效,或者 不包含所有指定的 usages 值, 则抛出一个 DataError

    8. 如果 jwkext 字段存在且 值为 false,并且 extractable 为 true, 则抛出一个 DataError

    否则:
    抛出一个 NotSupportedError
  3. key 为一个新的 CryptoKey 对象,表示值为 data 的 AES 密钥。

  4. key[[type]] 内部槽设置为 "secret"。

  5. algorithm 为一个新的 AesKeyAlgorithm

  6. algorithmname 属性设置为 "AES-CTR"。

  7. algorithmlength 属性设置为 data 的长度(以位为单位)。

  8. key[[algorithm]] 内部 槽设置为 algorithm

  9. 返回 key

27.7.5 导出密钥

  1. 如果无法访问由 key[[handle]] 内部槽表示的 底层加密密钥材料, 则抛出一个 OperationError

  2. 如果 format 为 "raw":
    1. data 为一个字节序列,其中包含 由 key[[handle]] 内部槽表示的密钥的原始八位字节。

    2. resultdata

    如果 format 为 "jwk":
    1. jwk 为一个新的 JsonWebKey 字典。

    2. jwkkty 属性设置为 字符串 "oct"。

    3. jwkk 属性设置为一个字符串, 其中包含由 key[[handle]] 内部槽表示的密钥的原始八位字节,并按照 JSON Web Algorithms [JWA] 第 6.4 节进行编码。

    4. 如果 keylength 属性为 128:
      jwkalg 属性设置为 字符串 "A128CTR"。
      如果 keylength 属性为 192:
      jwkalg 属性设置为 字符串 "A192CTR"。
      如果 keylength 属性为 256:
      jwkalg 属性设置为 字符串 "A256CTR"。
    5. jwkkey_ops 属性设置为等于 key[[usages]] 内部槽。

    6. jwkext 属性设置为等于 key[[extractable]] 内部槽。

    7. resultjwk

    否则:

    抛出一个 NotSupportedError

  3. 返回 result

27.7.6 获取密钥长度

  1. 如果 normalizedDerivedKeyAlgorithmlength 成员不是 128、192 或 256, 则抛出一个 OperationError

  2. 返回 normalizedDerivedKeyAlgorithmlength 成员。

28. AES-CBC

28.1 描述

本节是非规范性的。

"AES-CBC" 算法标识符用于使用 Cipher Block Chaining 模式下的 AES 执行加密和解密,如 [NIST-SP800-38A] 中所述。

当以 CBC 模式运行时,不是 AES 块大小(16 字节)精确倍数的消息, 可以在多种填充方案下进行填充。在 Web Crypto API 中,唯一受支持的 填充模式是 PKCS#7,如 [RFC2315] 第 10.3 节第 2 步所述。

28.2 注册

此算法的已识别算法名称为 "AES-CBC"。

操作 参数 结果
encrypt AesCbcParams 字节 序列
decrypt AesCbcParams 字节 序列
generateKey AesKeyGenParams CryptoKey
importKey CryptoKey
exportKey object
get key length AesDerivedKeyParams Integer

28.3 AesCbcParams 字典

WebIDLdictionary AesCbcParams : Algorithm {
  required BufferSource iv;
};

iv 成员表示初始化向量。它MUST为 16 字节。

28.4 操作

28.4.1 加密

  1. 如果 normalizedAlgorithmiv 成员的 长度不是 16 字节, 则抛出一个 OperationError

  2. paddedPlaintext 为按照 [RFC2315] 第 10.3 节第 2 步中定义的过程,使用 k 的值为 16,向 plaintext 添加填充八位字节所得的结果。

  3. ciphertext 为执行 [NIST-SP800-38A] 第 6.2 节中描述的 CBC Encryption 操作所得的结果,其中使用 AES 作为分组密码, 使用 normalizedAlgorithmiv 成员作为 IV 输入参数,并使用 paddedPlaintext 作为输入明文。

  4. 返回 ciphertext

28.4.2 解密

  1. 如果 normalizedAlgorithmiv 成员的 长度不是 16 字节, 则抛出一个 OperationError

  2. 如果 ciphertext 的长度为零,或不是 16 字节的倍数, 则抛出一个 OperationError

  3. paddedPlaintext 为执行 [NIST-SP800-38A] 第 6.2 节中描述的 CBC Decryption 操作所得的结果,其中使用 AES 作为分组密码, 使用 normalizedAlgorithmiv 成员作为 IV 输入参数,并使用 ciphertext 作为输入密文。

  4. ppaddedPlaintext 最后一个八位字节的值。

  5. 如果 p 为零或大于 16,或者 paddedPlaintext 的最后 p 个八位字节中的任何一个的值不是 p, 则抛出一个 OperationError

  6. plaintext 为从 paddedPlaintext 末尾移除 p 个八位字节所得的结果。

  7. 返回 plaintext

28.4.3 生成密钥

  1. 如果 usages 包含不是 "encrypt"、"decrypt"、 "wrapKey" 或 "unwrapKey" 之一的任何条目, 则抛出一个 SyntaxError

  2. 如果 normalizedAlgorithmlength 成员不等于 128、192 或 256 之一, 则抛出一个 OperationError

  3. 生成一个长度等于 normalizedAlgorithmlength 成员的 AES 密钥。

  4. 如果密钥生成步骤失败, 则抛出一个 OperationError

  5. key 为一个新的 CryptoKey 对象,表示所生成的 AES 密钥。

  6. algorithm 为一个新的 AesKeyAlgorithm

  7. algorithmname 属性设置为 "AES-CBC"。

  8. algorithmlength 属性设置为等于 normalizedAlgorithmlength 成员。

  9. key[[type]] 内部槽设置为 "secret"。

  10. key[[algorithm]] 内部 槽设置为 algorithm

  11. key[[extractable]] 内部 槽设置为 extractable

  12. key[[usages]] 内部槽 设置为 usages

  13. 返回 key

28.4.4 导入密钥

  1. 如果 usages 包含不是 "encrypt"、"decrypt"、 "wrapKey" 或 "unwrapKey" 之一的条目, 则抛出一个 SyntaxError

  2. 如果 format 为 "raw":
    1. datakeyData

    2. 如果 data位长度 不是 128、192 或 256, 则抛出一个 DataError

    如果 format 为 "jwk":
    1. 如果 keyData 是一个 JsonWebKey 字典:

      jwk 等于 keyData

      否则:

      抛出一个 DataError

    2. 如果 jwkkty 字段不是 "oct", 则抛出一个 DataError

    3. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.4 节的要求, 则抛出一个 DataError

    4. data 为通过解码 jwkk 字段 获得的字节序列

    5. 如果 data位长度 为 128:
      如果 jwkalg 字段存在,且 不是 "A128CBC", 则抛出一个 DataError
      如果 data位长度 为 192:
      如果 jwkalg 字段存在,且 不是 "A192CBC", 则抛出一个 DataError
      如果 data位长度 为 256:
      如果 jwkalg 字段存在,且 不是 "A256CBC", 则抛出一个 DataError
      否则:
      抛出一个 DataError
    6. 如果 usages 非空,且 jwkuse 字段存在,并且 不是 "enc", 则抛出一个 DataError

    7. 如果 jwkkey_ops 字段存在,且 根据 JSON Web Key [JWK] 的要求无效,或者 不包含所有指定的 usages 值, 则抛出一个 DataError

    8. 如果 jwkext 字段存在且 值为 false,并且 extractable 为 true, 则抛出一个 DataError

    否则:
    抛出一个 NotSupportedError
  3. key 为一个新的 CryptoKey 对象,表示值为 data 的 AES 密钥。

  4. key[[type]] 内部槽设置为 "secret"。

  5. algorithm 为一个新的 AesKeyAlgorithm

  6. algorithmname 属性设置为 "AES-CBC"。

  7. algorithmlength 属性设置为 data 的长度(以位为单位)。

  8. key[[algorithm]] 内部 槽设置为 algorithm

  9. 返回 key

28.4.5 导出密钥

  1. 如果无法访问由 key[[handle]] 内部槽表示的 底层加密密钥材料, 则抛出一个 OperationError

  2. 如果 format 为 "raw":
    1. data 为一个字节序列,其中包含 由 key[[handle]] 内部槽表示的密钥的原始八位字节。

    2. resultdata

    如果 format 为 "jwk":
    1. jwk 为一个新的 JsonWebKey 字典。

    2. jwkkty 属性设置为 字符串 "oct"。

    3. jwkk 属性设置为一个字符串, 其中包含由 key[[handle]] 内部槽表示的密钥的原始八位字节,并按照 JSON Web Algorithms [JWA] 第 6.4 节进行编码。

    4. 如果 keylength 属性为 128:
      jwkalg 属性设置为 字符串 "A128CBC"。
      如果 keylength 属性为 192:
      jwkalg 属性设置为 字符串 "A192CBC"。
      如果 keylength 属性为 256:
      jwkalg 属性设置为 字符串 "A256CBC"。
    5. jwkkey_ops 属性设置为等于 keyusages 属性。

    6. jwkext 属性设置为等于 key[[extractable]] 内部槽。

    7. resultjwk

    否则:

    抛出一个 NotSupportedError

  3. 返回 result

28.4.6 获取密钥长度

  1. 如果 normalizedDerivedKeyAlgorithmlength 成员不是 128、192 或 256, 则抛出一个 OperationError

  2. 返回 normalizedDerivedKeyAlgorithmlength 成员。

29. AES-GCM

29.1 描述

本节是非规范性的。

"AES-GCM" 算法标识符用于使用 Galois/Counter Mode 模式下的 AES 执行认证加密和解密,如 [NIST-SP800-38D] 中所述。

29.2 注册

此算法的已识别算法名称为 "AES-GCM"。

操作 参数 结果
encrypt AesGcmParams 字节 序列
decrypt AesGcmParams 字节 序列
generateKey AesKeyGenParams CryptoKey
importKey CryptoKey
exportKey object
get key length AesDerivedKeyParams Integer

29.3 AesGcmParams 字典

WebIDLdictionary AesGcmParams : Algorithm {
  required BufferSource iv;
  BufferSource additionalData;
  [EnforceRange] octet tagLength;
};

iv 成员表示要使用的初始化向量。最长可以为 2^64-1 字节。

additionalData 成员表示要包含的 额外认证数据。

tagLength 成员表示所需的 认证标签长度。可以为 0 - 128。

29.4 操作

29.4.1 加密

  1. 如果 plaintext长度 大于 2^39 - 256 字节, 则抛出一个 OperationError

  2. 如果 normalizedAlgorithmiv 成员的长度 大于 2^64 - 1 字节, 则抛出一个 OperationError

  3. 如果 normalizedAlgorithmadditionalData 成员 存在且其长度 大于 2^64 - 1 字节, 则抛出一个 OperationError

  4. 如果 normalizedAlgorithmtagLength 成员不存在:
    tagLength 为 128。
    如果 normalizedAlgorithmtagLength 成员是 32、64、96、104、112、120 或 128 之一:
    tagLength 等于 normalizedAlgorithmtagLength 成员
    否则:
    抛出一个 OperationError
  5. additionalDatanormalizedAlgorithmadditionalData 成员(如果存在), 否则为空字节序列

  6. CT 为执行 [NIST-SP800-38D] 第 7.1 节中描述的 Authenticated Encryption Function 所得到的输出, 其中使用 AES 作为分组密码,使用 normalizedAlgorithmiv 成员作为 IV 输入参数, additionalData 作为 A 输入参数, tagLength 作为 t 前提条件,并使用 plaintext 作为输入明文。

  7. ciphertext 等于 C | T, 其中 “|” 表示连接。

  8. 返回 ciphertext

29.4.2 解密

  1. 如果 normalizedAlgorithmtagLength 成员不存在:
    tagLength 为 128。
    如果 normalizedAlgorithmtagLength 成员是 32、64、96、104、112、120 或 128 之一:
    tagLength 等于 normalizedAlgorithmtagLength 成员
    否则:
    抛出一个 OperationError
  2. 如果 ciphertext位长度 小于 tagLength, 则抛出一个 OperationError

  3. 如果 normalizedAlgorithmiv 成员的长度 大于 2^64 - 1 字节, 则抛出一个 OperationError

  4. 如果 normalizedAlgorithmadditionalData 成员 存在且其长度 大于 2^64 - 1 字节, 则抛出一个 OperationError

  5. tagciphertext 的最后 tagLength 位。

  6. actualCiphertext 为从 ciphertext 中移除最后 tagLength 位所得的结果。

  7. additionalDatanormalizedAlgorithmadditionalData 成员(如果存在), 否则为空字节序列

  8. 执行 [NIST-SP800-38D] 第 7.2 节中描述的 Authenticated Decryption Function, 其中使用 AES 作为分组密码, 使用 normalizedAlgorithmiv 成员作为 IV 输入参数, additionalData 作为 A 输入参数, tagLength 作为 t 前提条件, actualCiphertext 作为输入密文,C,并以 tag 作为认证标签 T

    如果算法的结果是不真实性指示 "FAIL":
    抛出一个 OperationError
    否则:
    plaintext 为 Authenticated Decryption Function 的输出 P
  9. 返回 plaintext

29.4.3 生成密钥

  1. 如果 usages 包含不是 "encrypt"、"decrypt"、 "wrapKey" 或 "unwrapKey" 之一的任何条目, 则抛出一个 SyntaxError

  2. 如果 normalizedAlgorithmlength 成员不等于 128、192 或 256 之一, 则抛出一个 OperationError

  3. 生成一个长度等于 normalizedAlgorithmlength 成员的 AES 密钥。

  4. 如果密钥生成步骤失败, 则抛出一个 OperationError

  5. key 为一个新的 CryptoKey 对象,表示所生成的 AES 密钥。

  6. algorithm 为一个新的 AesKeyAlgorithm

  7. algorithmname 属性设置为 "AES-GCM"。

  8. algorithmlength 属性设置为等于 normalizedAlgorithmlength 成员。

  9. key[[type]] 内部槽设置为 "secret"。

  10. key[[algorithm]] 内部 槽设置为 algorithm

  11. key[[extractable]] 内部 槽设置为 extractable

  12. key[[usages]] 内部槽 设置为 usages

  13. 返回 key

29.4.4 导入密钥

  1. 如果 usages 包含不是 "encrypt"、"decrypt"、 "wrapKey" 或 "unwrapKey" 之一的条目, 则抛出一个 SyntaxError

  2. 如果 format 为 "raw":
    1. datakeyData

    2. 如果 data位长度 不是 128、192 或 256, 则抛出一个 DataError

    如果 format 为 "jwk":
    1. 如果 keyData 是一个 JsonWebKey 字典:

      jwk 等于 keyData

      否则:

      抛出一个 DataError

    2. 如果 jwkkty 字段不是 "oct", 则抛出一个 DataError

    3. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.4 节的要求, 则抛出一个 DataError

    4. data 为通过解码 jwkk 字段 获得的字节序列

    5. 如果 data位长度 为 128:
      如果 jwkalg 字段存在,且 不是 "A128GCM", 则抛出一个 DataError
      如果 data位长度 为 192:
      如果 jwkalg 字段存在,且 不是 "A192GCM", 则抛出一个 DataError
      如果 data位长度 为 256:
      如果 jwkalg 字段存在,且 不是 "A256GCM", 则抛出一个 DataError
      否则:
      抛出一个 DataError
    6. 如果 usages 非空,且 jwkuse 字段存在,并且 不是 "enc", 则抛出一个 DataError

    7. 如果 jwkkey_ops 字段存在,且 根据 JSON Web Key [JWK] 的要求无效,或者 不包含所有指定的 usages 值, 则抛出一个 DataError

    8. 如果 jwkext 字段存在且 值为 false,并且 extractable 为 true, 则抛出一个 DataError

    否则:
    抛出一个 NotSupportedError
  3. key 为一个新的 CryptoKey 对象,表示值为 data 的 AES 密钥。

  4. key[[type]] 内部槽设置为 "secret"。

  5. algorithm 为一个新的 AesKeyAlgorithm

  6. algorithmname 属性设置为 "AES-GCM"。

  7. algorithmlength 属性设置为 data 的长度(以位为单位)。

  8. key[[algorithm]] 内部 槽设置为 algorithm

  9. 返回 key

29.4.5 导出密钥

  1. 如果无法访问由 key[[handle]] 内部槽表示的 底层加密密钥材料, 则抛出一个 OperationError

  2. 如果 format 为 "raw":
    1. data 为一个字节序列,其中包含 由 key[[handle]] 内部槽表示的密钥的原始八位字节。

    2. resultdata

    如果 format 为 "jwk":
    1. jwk 为一个新的 JsonWebKey 字典。

    2. jwkkty 属性设置为 字符串 "oct"。

    3. jwkk 属性设置为一个字符串, 其中包含由 key[[handle]] 内部槽表示的密钥的原始八位字节,并按照 JSON Web Algorithms [JWA] 第 6.4 节进行编码。

    4. 如果 keylength 属性为 128:
      jwkalg 属性设置为 字符串 "A128GCM"。
      如果 keylength 属性为 192:
      jwkalg 属性设置为 字符串 "A192GCM"。
      如果 keylength 属性为 256:
      jwkalg 属性设置为 字符串 "A256GCM"。
    5. jwkkey_ops 属性设置为等于 keyusages 属性。

    6. jwkext 属性设置为等于 key[[extractable]] 内部槽。

    7. resultjwk

    否则:

    抛出一个 NotSupportedError

  3. 返回 result

29.4.6 获取密钥长度

  1. 如果 normalizedDerivedKeyAlgorithmlength 成员不是 128、192 或 256,则抛出一个 OperationError

  2. 返回 normalizedDerivedKeyAlgorithmlength 成员。

30. AES-KW

30.1 描述

本节是非规范性的。

"AES-KW" 算法标识符用于使用 AES 执行密钥包装,如 [RFC3394] 中所述。

30.2 注册

此算法的已识别算法名称为 "AES-KW"。

操作 参数 结果
wrapKey 字节 序列
unwrapKey 字节 序列
generateKey AesKeyGenParams CryptoKey
importKey CryptoKey
exportKey object
get key length AesDerivedKeyParams Integer

30.3 操作

30.3.1 包装密钥

  1. 如果 plaintext 的长度不是 64 位的倍数, 则抛出一个 OperationError

  2. ciphertext 为执行 [RFC3394] 第 2.2.1 节中描述的密钥包装操作所得的结果,其中 plaintext 作为要被包装的明文,并使用同一文档 第 2.2.3.1 节中定义的默认初始值。

  3. 返回 ciphertext

30.3.2 解包密钥

  1. plaintext 为执行 [RFC3394] 第 2.2.2 节中描述的密钥解包操作所得的结果,其中 ciphertext 作为输入密文,并使用同一文档 第 2.2.3.1 节中定义的默认初始值。

  2. 如果密钥解包操作返回错误, 则抛出一个 OperationError

  3. 返回 plaintext

30.3.3 生成密钥

  1. 如果 usages 包含不是 "wrapKey" 或 "unwrapKey" 之一的任何条目, 则抛出一个 SyntaxError

  2. 如果 normalizedAlgorithmlength 属性不等于 128、192 或 256 之一,则抛出一个 OperationError

  3. 生成一个长度等于 normalizedAlgorithmlength 成员的 AES 密钥。

  4. 如果密钥生成步骤失败, 则抛出一个 OperationError

  5. key 为一个新的 CryptoKey 对象,表示所生成的 AES 密钥。

  6. algorithm 为一个新的 AesKeyAlgorithm

  7. algorithmname 属性设置为 "AES-KW"。

  8. algorithmlength 属性设置为等于 normalizedAlgorithmlength 属性。

  9. key[[type]] 内部槽设置为 "secret"。

  10. key[[algorithm]] 内部 槽设置为 algorithm

  11. key[[extractable]] 内部 槽设置为 extractable

  12. key[[usages]] 内部槽 设置为 usages

  13. 返回 key

30.3.4 导入密钥

  1. 如果 usages 包含不是 "wrapKey" 或 "unwrapKey" 之一的条目, 则抛出一个 SyntaxError

  2. 如果 format 为 "raw":
    1. datakeyData

    2. 如果 data位长度 不是 128、192 或 256, 则抛出一个 DataError

    如果 format 为 "jwk":
    1. 如果 keyData 是一个 JsonWebKey 字典:

      jwk 等于 keyData

      否则:

      抛出一个 DataError

    2. 如果 jwkkty 字段不是 "oct", 则抛出一个 DataError

    3. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.4 节的要求, 则抛出一个 DataError

    4. data 为通过解码 jwkk 字段 获得的字节序列

    5. 如果 data位长度 为 128:
      如果 jwkalg 字段存在,且 不是 "A128KW", 则抛出一个 DataError
      如果 data位长度 为 192:
      如果 jwkalg 字段存在,且 不是 "A192KW", 则抛出一个 DataError
      如果 data位长度 为 256:
      如果 jwkalg 字段存在,且 不是 "A256KW", 则抛出一个 DataError
      否则:
      抛出一个 DataError
    6. 如果 usages 非空,且 jwkuse 字段存在,并且 不是 "enc", 则抛出一个 DataError

    7. 如果 jwkkey_ops 字段存在,且 根据 JSON Web Key [JWK] 的要求无效,或者 不包含所有指定的 usages 值, 则抛出一个 DataError

    8. 如果 jwkext 字段存在且 值为 false,并且 extractable 为 true, 则抛出一个 DataError

    否则:
    抛出一个 NotSupportedError
  3. key 为一个新的 CryptoKey, 它表示值为 data 的 AES 密钥。

  4. key[[type]] 内部槽设置为 "secret"。

  5. algorithm 为一个新的 AesKeyAlgorithm

  6. algorithmname 属性设置为 "AES-KW"。

  7. algorithmlength 属性设置为 data 的长度(以位为单位)。

  8. key[[algorithm]] 内部 槽设置为 algorithm

  9. 返回 key

30.3.5 导出密钥

  1. 如果无法访问由 key[[handle]] 内部槽表示的 底层加密密钥材料, 则抛出一个 OperationError

  2. 如果 format 为 "raw":
    1. data 为一个字节序列,其中包含 由 key[[handle]] 内部槽表示的密钥的原始八位字节。

    2. resultdata

    如果 format 为 "jwk":
    1. jwk 为一个新的 JsonWebKey 字典。

    2. jwkkty 属性设置为 字符串 "oct"。

    3. jwkk 属性设置为一个字符串, 其中包含由 key[[handle]] 内部槽表示的密钥的原始八位字节,并按照 JSON Web Algorithms [JWA] 第 6.4 节进行编码。

    4. 如果 keylength 属性为 128:
      jwkalg 属性设置为 字符串 "A128KW"。
      如果 keylength 属性为 192:
      jwkalg 属性设置为 字符串 "A192KW"。
      如果 keylength 属性为 256:
      jwkalg 属性设置为 字符串 "A256KW"。
    5. jwkkey_ops 属性设置为等于 keyusages 属性。

    6. jwkext 属性设置为等于 key[[extractable]] 内部槽。

    7. resultjwk

    否则:

    抛出一个 NotSupportedError

  3. 返回 result

30.3.6 获取密钥长度

  1. 如果 normalizedDerivedKeyAlgorithmlength 成员不是 128、192 或 256,则抛出一个 OperationError

  2. 返回 normalizedDerivedKeyAlgorithmlength 成员。

31. HMAC

31.1 描述

本节是非规范性的。

HMAC 算法根据 [FIPS-198-1] 使用本规范中定义的 SHA 哈希函数,计算和验证基于哈希的消息 认证码。

其他 规范 可以指定 HMAC 对其他哈希算法的使用。此类规范必须为额外的哈希算法 定义摘要操作,并为 HMAC 定义 密钥导入步骤密钥导出步骤

31.2 注册

此算法的已识别算法名称为 "HMAC"。

操作 参数 结果
sign 字节 序列
verify boolean
generateKey HmacKeyGenParams CryptoKey
importKey HmacImportParams CryptoKey
exportKey object
get key length HmacImportParams Integer

31.3 HmacImportParams 字典

WebIDLdictionary HmacImportParams : Algorithm {
  required HashAlgorithmIdentifier hash;
  [EnforceRange] unsigned long length;
};

hash 成员表示要使用的内部哈希 函数。

length 成员表示密钥的长度(以位为单位)。

31.4 HmacKeyAlgorithm 字典

WebIDLdictionary HmacKeyAlgorithm : KeyAlgorithm {
  required KeyAlgorithm hash;
  required unsigned long length;
};

hash 成员表示要使用的内部哈希函数。

length 成员表示密钥的长度(以位为单位)。

31.5 HmacKeyGenParams 字典

WebIDLdictionary HmacKeyGenParams : Algorithm {
  required HashAlgorithmIdentifier hash;
  [EnforceRange] unsigned long length;
};

hash 成员表示要使用的内部哈希 函数。

length 成员表示要生成的密钥 的长度(以位为单位)。如果未指定,则将使用推荐长度,即相关哈希函数的 块大小。

31.6 操作

31.6.1 签名

  1. mac 为执行 [FIPS-198-1] 第 4 节中描述的 MAC Generation 操作所得的结果, 其中使用由 key[[handle]] 内部槽表示的密钥、由 key[[algorithm]] 内部 槽的 hash 属性所标识的哈希函数, 并以 message 作为输入数据 text

  2. 返回 mac

31.6.2 验证

  1. mac 为执行 [FIPS-198-1] 第 4 节中描述的 MAC Generation 操作所得的结果, 其中使用由 key[[handle]] 内部槽表示的密钥、由 key[[algorithm]] 内部 槽的 hash 属性所标识的哈希函数, 并以 message 作为输入数据 text

  2. 如果 mac 等于 signature,则返回 true; 否则返回 false。

31.6.3 生成密钥

  1. 如果 usages 包含不是 "sign" 或 "verify" 的任何条目,则抛出一个 SyntaxError

  2. 如果 normalizedAlgorithmlength 成员不存在:
    lengthnormalizedAlgorithmhash 成员所标识的哈希函数的块大小(以位为单位)。
    否则,如果 normalizedAlgorithmlength 成员非零:
    length 等于 normalizedAlgorithmlength 成员。
    否则:
    抛出一个 OperationError
  3. 生成一个长度为 length 位的密钥。

  4. 如果密钥生成步骤失败, 则抛出一个 OperationError

  5. key 为一个新的 CryptoKey 对象,表示生成的密钥。

  6. algorithm 为一个新的 HmacKeyAlgorithm

  7. algorithmname 属性设置为 "HMAC"。

  8. algorithmlength 属性设置为 length

  9. hash 为一个新的 KeyAlgorithm

  10. hashname 属性设置为等于 normalizedAlgorithmhash 成员的 name 成员。

  11. algorithmhash 属性 设置为 hash

  12. key[[type]] 内部槽设置为 "secret"。

  13. key[[algorithm]] 内部 槽设置为 algorithm

  14. key[[extractable]] 内部 槽设置为 extractable

  15. key[[usages]] 内部槽 设置为 usages

  16. 返回 key

31.6.4 导入密钥

  1. keyData 为要导入的密钥数据。

  2. 如果 usages 包含不是 "sign" 或 "verify" 的条目, 则抛出一个 SyntaxError

  3. hash 为一个新的 KeyAlgorithm

  4. 如果 format 为 "raw":
    1. datakeyData

    2. hash 设置为等于 normalizedAlgorithmhash 成员。

    如果 format 为 "jwk":
    1. 如果 keyData 是一个 JsonWebKey 字典:

      jwk 等于 keyData

      否则:

      抛出一个 DataError

    2. 如果 jwkkty 字段不是 "oct", 则抛出一个 DataError

    3. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.4 节的要求, 则抛出一个 DataError

    4. data 为通过解码 jwkk 字段 获得的字节序列

    5. hash 设置为等于 normalizedAlgorithmhash 成员。

    6. 如果 hashname 属性为 "SHA-1":
      如果 jwkalg 字段存在, 且不是 "HS1", 则抛出一个 DataError
      如果 hashname 属性为 "SHA-256":
      如果 jwkalg 字段存在, 且不是 "HS256", 则抛出一个 DataError
      如果 hashname 属性为 "SHA-384":
      如果 jwkalg 字段存在, 且不是 "HS384", 则抛出一个 DataError
      如果 hashname 属性为 "SHA-512":
      如果 jwkalg 字段存在, 且不是 "HS512", 则抛出一个 DataError
      否则,如果 hashname 属性在 另一个适用 规范中定义:
      执行由 其他适用 规范定义的任何 密钥导入步骤, 传入 formatjwkhash 并获得 hash
    7. 如果 usages 非空,且 jwkuse 字段存在,并且 不是 "sign", 则抛出一个 DataError

    8. 如果 jwkkey_ops 字段存在,且 根据 JSON Web Key [JWK] 的要求无效,或者 不包含所有指定的 usages 值, 则抛出一个 DataError

    9. 如果 jwkext 字段存在且 值为 false,并且 extractable 为 true, 则抛出一个 DataError

    否则:
    抛出一个 NotSupportedError
  5. lengthdata位长度

  6. 如果 length 为零, 则抛出一个 DataError

  7. 如果 normalizedAlgorithmlength 成员存在:
    如果 normalizedAlgorithmlength 成员大于 length
    抛出一个 DataError
    如果 normalizedAlgorithmlength 成员 小于或等于 length 减八:
    抛出一个 DataError
    否则:
    length 设置为等于 normalizedAlgorithmlength 成员。
  8. key 为一个新的 CryptoKey 对象,它表示使用 data 的前 length 位的 HMAC 密钥。

  9. key[[type]] 内部槽设置为 "secret"。

  10. algorithm 为一个新的 HmacKeyAlgorithm

  11. algorithmname 属性设置为 "HMAC"。

  12. algorithmlength 属性设置为 length

  13. algorithmhash 属性设置为 hash

  14. key[[algorithm]] 内部 槽设置为 algorithm

  15. 返回 key

31.6.5 导出密钥

  1. 如果无法访问由 key[[handle]] 内部槽表示的 底层加密密钥材料, 则抛出一个 OperationError

  2. bits 为由 key[[handle]] 内部槽表示的 密钥的原始位。

  3. data 为一个包含 bits 的字节序列。

  4. 如果 format 为 "raw":
    1. resultdata

    如果 format 为 "jwk":
    1. jwk 为一个新的 JsonWebKey 字典。

    2. jwkkty 属性设置为 字符串 "oct"。

    3. jwkk 属性设置为一个字符串, 其中包含 data,并按照 JSON Web Algorithms [JWA] 第 6.4 节进行编码。

    4. algorithmkey[[algorithm]] 内部槽。

    5. hashalgorithmhash 属性。

    6. 如果 hashname 属性为 "SHA-1":
      jwkalg 属性设置为 字符串 "HS1"。
      如果 hashname 属性为 "SHA-256":
      jwkalg 属性设置为 字符串 "HS256"。
      如果 hashname 属性为 "SHA-384":
      jwkalg 属性设置为 字符串 "HS384"。
      如果 hashname 属性为 "SHA-512":
      jwkalg 属性设置为 字符串 "HS512"。
      否则,hashname 属性在 另一个适用 规范中定义:
      1. 执行由 其他 适用 规范定义的任何 密钥导出 步骤,传入 formatkey 并获得 alg

      2. jwkalg 属性设置为 alg

    7. jwkkey_ops 属性设置为等于 keyusages 属性。

    8. jwkext 属性设置为等于 key[[extractable]] 内部槽。

    9. resultjwk

    否则:

    抛出一个 NotSupportedError

  5. 返回 result

31.6.6 获取密钥长度

  1. 如果 normalizedDerivedKeyAlgorithmlength 成员不存在:

    lengthnormalizedDerivedKeyAlgorithmhash 成员 所标识的哈希函数的块大小(以位为单位)。

    否则,如果 normalizedDerivedKeyAlgorithmlength 成员非零:
    length 等于 normalizedDerivedKeyAlgorithmlength 成员。
    否则:
    抛出一个 TypeError
  2. 返回 length

32. SHA

32.1 描述

本节是非规范性的。

这里描述 SHA-1 和 SHA-2 族,如 [FIPS-180-4] 所指定。

32.2 注册

相应 SHA 算法的已识别算法 名称是 "SHA-1"、 "SHA-256"、 "SHA-384" 和 "SHA-512"。

操作 参数 结果
digest 字节 序列

32.3 操作

32.3.1 摘要

  1. 如果 normalizedAlgorithmname 成员区分大小写地字符串匹配 "SHA-1":
    result 为执行 [FIPS-180-4] 第 6.1 节中定义的 SHA-1 哈希函数所得的结果,其中 message 作为输入消息 M
    如果 normalizedAlgorithmname 成员区分大小写地字符串匹配 "SHA-256":
    result 为执行 [FIPS-180-4] 第 6.2 节中定义的 SHA-256 哈希函数所得的结果,其中 message 作为输入消息 M
    如果 normalizedAlgorithmname 成员区分大小写地字符串匹配 "SHA-384":
    result 为执行 [FIPS-180-4] 第 6.5 节中定义的 SHA-384 哈希函数所得的结果,其中 message 作为输入消息 M
    如果 normalizedAlgorithmname 成员区分大小写地字符串匹配 "SHA-512":
    result 为执行 [FIPS-180-4] 第 6.4 节中定义的 SHA-512 哈希函数所得的结果,其中 message 作为输入消息 M
  2. 如果执行操作导致错误,则抛出一个 OperationError

  3. 返回 result

33. HKDF

33.1 描述

本节是非规范性的。

"HKDF" 算法标识符用于 使用 [RFC5869] 中描述的先提取后扩展方法执行密钥派生,并 使用本规范中定义的 SHA 哈希函数。

其他 规范 可以指定 HKDF 对其他哈希算法的使用。 此类规范必须为额外的哈希算法定义摘要操作。

33.2 注册

此算法的已识别算法名称 为 "HKDF"。

操作 参数 结果
deriveBits HkdfParams 字节 序列
importKey CryptoKey
Get key length null

33.3 HkdfParams 字典

WebIDLdictionary HkdfParams : Algorithm {
  required HashAlgorithmIdentifier hash;
  required BufferSource salt;
  required BufferSource info;
};

hash 成员表示要与 HMAC 一起使用的算法 (例如:SHA-256)。

salt 成员表示提取步骤中使用的盐。

info 成员表示派生密钥材料的应用特定上下文。

33.4 操作

33.4.1 派生位

  1. 如果 length 为 null 或不是 8 的倍数,则抛出一个 OperationError

  2. keyDerivationKey 为由 key[[handle]] 内部槽表示的 秘密值。

  3. result 为执行 [RFC5869] 第 2 节中描述的 HKDF 提取步骤然后执行 HKDF 扩展步骤所得的结果, 使用:

    • normalizedAlgorithmhash 成员作为 Hash

    • keyDerivationKey 作为输入密钥材料, IKM

    • normalizedAlgorithmsalt 成员作为 salt

    • normalizedAlgorithminfo 成员作为 info

    • length 除以 8 作为 L 的值,

  4. 如果密钥派生操作失败, 则抛出一个 OperationError

  5. 返回 result

33.4.2 导入密钥

  1. keyData 为要导入的密钥数据。

  2. 如果 format 为 "raw":
    1. 如果 usages 包含不是 "deriveKey" 或 "deriveBits" 的值, 则抛出一个 SyntaxError

    2. 如果 extractable 不是 false, 则抛出一个 SyntaxError

    3. key 为一个新的 CryptoKey, 表示 keyData 中提供的密钥数据。

    4. key[[type]] 内部槽设置为 "secret"。

    5. algorithm 为一个新的 KeyAlgorithm 对象。

    6. algorithmname 属性设置为 "HKDF"。

    7. key[[algorithm]] 内部 槽设置为 algorithm

    8. 返回 key

    否则:
    抛出一个 NotSupportedError

33.4.3 获取密钥长度

  1. 返回 null。

34. PBKDF2

34.1 描述

本节是非规范性的。

"PBKDF2" 算法标识符用于 使用 [RFC8018] 中定义的 PKCS#5 基于口令的密钥派生函数版本 2 执行密钥派生,其中使用 HMAC 作为伪随机函数, 并使用本规范中定义的 SHA 哈希函数。

其他 规范 可以指定 PBKDF2 对其他哈希算法的使用。此类规范 必须为额外的哈希算法定义摘要操作。

34.2 注册

此算法的已识别算法名称为 "PBKDF2"。

操作 参数 结果
deriveBits Pbkdf2Params 字节 序列
importKey CryptoKey
Get key length null

34.3 Pbkdf2Params 字典

WebIDLdictionary Pbkdf2Params : Algorithm {
  required BufferSource salt;
  required [EnforceRange] unsigned long iterations;
  required HashAlgorithmIdentifier hash;
};

Pbkdf2Params 字典具有一个 salt 成员、一个 iterations 成员,以及一个 hash 成员。

34.4 操作

34.4.1 派生位

  1. 如果 length 为 null 或不是 8 的倍数,则抛出一个 OperationError

  2. 如果 normalizedAlgorithmiterations 成员为零, 则抛出一个 OperationError

  3. 如果 length 为零,则返回一个空字节序列

  4. prf 为 [FIPS-198-1] 第 4 节中描述的 MAC Generation 函数, 它使用由 normalizedAlgorithmhash 成员 描述的哈希函数。

  5. result 为执行 [RFC8018] 第 5.2 节中定义的 PBKDF2 操作所得的结果,其中使用 prf 作为 伪随机函数 PRF,由 key[[handle]] 内部槽表示的口令 作为口令 PnormalizedAlgorithmsalt 属性作为盐 SnormalizedAlgorithmiterations 属性的值作为 迭代次数 c,并将 length 除以 8 作为预期密钥长度 dkLen

  6. 如果密钥派生操作失败, 则抛出一个 OperationError

  7. 返回 result

34.4.2 导入密钥

  1. 如果 format 不是 "raw",则抛出一个 NotSupportedError

  2. 如果 usages 包含不是 "deriveKey" 或 "deriveBits" 的值,则 抛出一个 SyntaxError

  3. 如果 extractable 不是 false, 则抛出一个 SyntaxError

  4. key 为一个新的 CryptoKey, 表示 keyData

  5. key[[type]] 内部槽设置为 "secret"。

  6. algorithm 为一个新的 KeyAlgorithm 对象。

  7. algorithmname 属性设置为 "PBKDF2"。

  8. key[[algorithm]] 内部 槽设置为 algorithm

  9. 返回 key

34.4.3 获取密钥长度

  1. 返回 null。

35. JavaScript 示例代码

35.1 生成两个密钥对,派生共享密钥,加密一些数据

此示例生成两个 X25519 密钥对,一个用于 Alice,一个用于 Bob,在二者之间执行 密钥协商,使用带 SHA-256 的 HKDF 从结果中派生一个 256 位 AES-GCM 密钥, 并用它加密和解密一些数据。

示例 1:X25519 密钥协商
// 为 Alice 生成密钥对。
const alice_x25519_key = await crypto.subtle.generateKey('X25519', false /* extractable */, ['deriveKey']);
const alice_private_key = alice_x25519_key.privateKey;

// 通常,公钥会由 Bob 提前通过某个已认证通道发送给 Alice。
// 在此示例中,我们将生成另一个密钥对,并改用其公钥。
const bob_x25519_key = await crypto.subtle.generateKey('X25519', false /* extractable */, ['deriveKey']);
const bob_public_key = bob_x25519_key.publicKey;

// 执行密钥协商。
const alice_x25519_params = { name: 'X25519', public: bob_public_key };
const alice_shared_key = await crypto.subtle.deriveKey(alice_x25519_params, alice_private_key, 'HKDF', false /* extractable */, ['deriveKey']);

// 从结果派生一个对称密钥。
const salt = crypto.getRandomValues(new Uint8Array(32));
const info = new TextEncoder().encode('X25519 key agreement for an AES-GCM-256 key');
const hkdf_params = { name: 'HKDF', hash: 'SHA-256', salt, info };
const gcm_params = { name: 'AES-GCM', length: 256 };
const alice_symmetric_key = await crypto.subtle.deriveKey(hkdf_params, alice_shared_key, gcm_params, false /* extractable */, ['encrypt', 'decrypt']);

// 用对称密钥加密一些数据,并发送给 Bob。IV 也必须一并传递。
const iv = crypto.getRandomValues(new Uint8Array(12));
const message = new TextEncoder().encode('Hi Bob!');
const encrypted = await crypto.subtle.encrypt({ ...gcm_params, iv }, alice_symmetric_key, message);

// 在 Bob 一侧,改用 Alice 的公钥和 Bob 的私钥。
// 为获得相同结果,Alice 和 Bob 必须约定使用相同的 salt 和 info。
const alice_public_key = alice_x25519_key.publicKey;
const bob_private_key = bob_x25519_key.privateKey;
const bob_x25519_params = { name: 'X25519', public: alice_public_key };
const bob_shared_key = await crypto.subtle.deriveKey(bob_x25519_params, bob_private_key, 'HKDF', false /* extractable */, ['deriveKey']);
const bob_symmetric_key = await crypto.subtle.deriveKey(hkdf_params, bob_shared_key, gcm_params, false /* extractable */, ['encrypt', 'decrypt']);

// 在 Bob 一侧,可以解密数据。
const decrypted = await crypto.subtle.decrypt({ ...gcm_params, iv }, bob_symmetric_key, encrypted);
const decrypted_message = new TextDecoder().decode(decrypted);

35.2 生成一个 签名密钥对,签署一些数据

示例 2:Ed25519 签名
const data = new TextEncoder().encode('Hello, world!');
const key = await crypto.subtle.generateKey('Ed25519', false, ['sign']);
const signature = await crypto.subtle.sign('Ed25519', key.privateKey, data);

35.3 生成一个 对称密钥,加密一些数据

示例 3:AES-GCM 加密
const data = new TextEncoder().encode('Hello, world!');
const aesAlgorithmKeyGen = {
  name: 'AES-GCM',
  // AesKeyGenParams
  length: 256
};
const aesAlgorithmEncrypt = {
  name: 'AES-GCM',
  // AesGcmParams
  iv: crypto.getRandomValues(new Uint8Array(16))
};
const key = await crypto.subtle.generateKey(aesAlgorithmKeyGen, false, ['encrypt']);
const encrypted = await crypto.subtle.encrypt(aesAlgorithmEncrypt, key, data);

35.4 为下载生成唯一名称

示例 4:随机 UUID 生成
const filename = `${crypto.randomUUID()}.txt`;

36. IANA 考量

36.1 JSON Web Signature and Encryption Algorithms 注册

本节在 IANA JSON Web Signature and Encryption Algorithms Registry 中注册以下算法标识符, 以便与 JSON Web Key 一起使用。注意,模板中的 'Implementation Requirements' 字段专指与 JSON Web Signature 和 JSON Web Encryption 一起使用,在这种情况下,禁止使用未经认证的加密。

36.2 JSON Web Key 参数注册

37. 致谢

特别感谢 Ryan Sleevi,本文件的原作者和编辑, 以及本文件的前编辑 Mark Watson。

感谢 Adam Barth、Alex Russell、Ali Asad、Arun Ranganathan、 Brian Smith、Brian Warner、Channy Yun、Charles Engelke、Eric Roman、Glenn Adams、Jim Schaad、Kai Engert、 Michael Hutchinson、Michael B. Jones、Nick Van den Bleeken、Richard Barnes、Ryan Hurst、 Tim Taubert、Vijay Bharadwaj、Virginie Galindo 和 Wan-Teh Chang 提供技术反馈和 协助。

感谢 W3C Web Cryptography WG,以及 public-webcrypto@w3.org 邮件列表的参与者。

W3C 感谢 Northrop Grumman Cybersecurity Research ConsortiumW3C/MIT 的支持。

getRandomValues 方法最初由 Adam Barth 向 Crypto 接口中的 WHATWG 提议。

A. JSON Web Key / JSON Web Algorithm 之间的映射

本节是非规范性的。

有关导入和导出 JWK 的规范性要求, 请参见特定于算法的小节。

A.1 算法映射

JSON Web Key AlgorithmIdentifier
{ kty: "RSA",
  alg: "RS1" }
{ name: "RSASSA-PKCS1-v1_5",
  hash: { name: "SHA-1" }
}
{ kty: "RSA",
  alg: "RS256" }
{ name: "RSASSA-PKCS1-v1_5",
  hash: { name: "SHA-256" }
}
{ kty: "RSA",
  alg: "RS384" }
{ name: "RSASSA-PKCS1-v1_5",
  hash: { name: "SHA-384" }
}
{ kty: "RSA",
  alg: "RS512" }
{ name: "RSASSA-PKCS1-v1_5",
  hash: { name: "SHA-512" }
}
{ kty: "RSA",
  alg: "PS256" }
{ name: "RSA-PSS",
  hash: { name: "SHA-256" }
}
{ kty: "RSA",
  alg: "PS384" }
{ name: "RSA-PSS",
  hash: { name: "SHA-384" }
}
{ kty: "RSA",
  alg: "PS512" }
{ name: "RSA-PSS",
  hash: { name: "SHA-512" }
}
{ kty: "RSA",
  alg: "RSA-OAEP" }
{ name: "RSA-OAEP",
  hash: { name: "SHA-1" }
}
{ kty: "RSA",
  alg: "RSA-OAEP-256" }
{ name: "RSA-OAEP",
  hash: { name: "SHA-256" }
}
{ kty: "RSA",
  alg: "RSA-OAEP-384" }
{ name: "RSA-OAEP",
  hash: { name: "SHA-384" }
}
{ kty: "RSA",
  alg: "RSA-OAEP-512" }
{ name: "RSA-OAEP",
  hash: { name: "SHA-512" }
}
{ kty: "EC",
  alg: "ES256" }
{ name: "ECDSA",
  namedCurve: "P-256",
  hash: { name: "SHA-256" }
}
{ kty: "EC",
  alg: "ES384" }
{ name: "ECDSA",
  namedCurve: "P-384",
  hash: { name: "SHA-384" }
}
{ kty: "EC",
  alg: "ES512" }
{ name: "ECDSA",
  namedCurve: "P-521",
  hash: { name: "SHA-512" }
}
{ kty: "OKP",
  crv: "Ed25519",
  alg: "Ed25519" }
{ name: "Ed25519" }
{ kty: "OKP",
  crv: "X25519" }
{ name: "X25519" }
{ kty: "oct",
  alg: "A128CTR" }
{ name: "AES-CTR",
  length: 128 }
{ kty: "oct",
  alg: "A192CTR" }
{ name: "AES-CTR",
  length: 192 }
{ kty: "oct",
  alg: "A256CTR" }
{ name: "AES-CTR",
  length: 256 }
{ kty: "oct",
  alg: "A128CBC" }
{ name: "AES-CBC",
  length: 128 }
{ kty: "oct",
  alg: "A192CBC" }
{ name: "AES-CBC",
  length: 192 }
{ kty: "oct",
  alg: "A256CBC" }
{ name: "AES-CBC",
  length: 256 }
{ kty: "oct",
  alg: "A128KW" }
{ name: "AES-KW",
  length: 128 }
{ kty: "oct",
  alg: "A192KW" }
{ name: "AES-KW",
  length: 192 }
{ kty: "oct",
  alg: "A256KW" }
{ name: "AES-KW",
  length: 256 }
{ kty: "oct",
  alg: "A128GCM" }
{ name: "AES-GCM",
  length: 128 }
{ kty: "oct",
  alg: "A192GCM" }
{ name: "AES-GCM",
  length: 192 }
{ kty: "oct",
  alg: "A256GCM" }
{ name: "AES-GCM",
  length: 256 }
{ kty: "oct",
  alg: "A128GCMKW" }
{ name: "AES-GCM",
  length: 128 }
{ kty: "oct",
  alg: "A192GCMKW" }
{ name: "AES-GCM",
  length: 192 }
{ kty: "oct",
  alg: "A256GCMKW" }
{ name: "AES-GCM",
  length: 256 }
{ kty: "oct",
  alg: "HS1" }
{ name: "HMAC",
  hash: { name: "SHA-1" }
}
{ kty: "oct",
  alg: "HS256" }
{ name: "HMAC",
  hash: { name: "SHA-256" }
}
{ kty: "oct",
  alg: "HS384" }
{ name: "HMAC",
  hash: { name: "SHA-384" }
}
{ kty: "oct",
  alg: "HS512" }
{ name: "HMAC",
  hash: "SHA-512" }

B. Algorithm 与 SubjectPublicKeyInfo 之间的映射

本节是非规范性的。

有关导入和导出 SPKI 的规范性要求, 请参见特定于算法的小节。

Algorithm OID subjectPublicKey ASN.1 结构 AlgorithmIdentifier 参考
rsaEncryption (1.2.840.113549.1.1.1) RSAPublicKey "RSASSA-PKCS1-v1_5"、 "RSA-PSS" 或 "RSA-OAEP" [RFC3447]
id-ecPublicKey (1.2.840.10045.2.1) ECPoint "ECDH" 或 "ECDSA" [RFC5480]
id-Ed25519 (1.3.101.112) BIT STRING "Ed25519" [RFC8410]
id-X25519 (1.3.101.110) BIT STRING "X25519" [RFC8410]

本规范使用的对象标识符不 包含该密钥意图与之一起使用的特定算法和哈希 的信息。如果需要这些信息, 建议改用 "jwk" 密钥格式。

C. Algorithm 与 PKCS#8 PrivateKeyInfo 之间的映射

本节是非规范性的。

有关导入和导出 PKCS#8 PrivateKeyInfo 的规范性要求, 请参见特定于算法的小节。

privateKeyAlgorithm privateKey 格式 AlgorithmIdentifier 参考
rsaEncryption (1.2.840.113549.1.1.1) RSAPrivateKey "RSASSA-PKCS1-v1_5"、 "RSA-PSS" 或 "RSA-OAEP" [RFC3447]
id-ecPublicKey (1.2.840.10045.2.1) ECPrivateKey "ECDH" 或 "ECDSA" [RFC5480]
id-Ed25519 (1.3.101.112) CurvePrivateKey "Ed25519" [RFC8410]
id-X25519 (1.3.101.110) CurvePrivateKey "X25519" [RFC8410]

D. 参考文献

D.1 规范性参考文献

[DOM]
DOM Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMA-262]
ECMAScript Language Specification. Ecma International. URL: https://tc39.es/ecma262/multipage/
[encoding]
Encoding Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://encoding.spec.whatwg.org/
[FIPS-180-4]
FIPS PUB 180-4: Secure Hash Standard (SHS). U.S. Department of Commerce/National Institute of Standards and Technology. August 2015. National Standard. URL: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
[FIPS-198-1]
The Keyed-Hash Message Authentication Code (HMAC). NIST. July 2008. URL: http://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf
[HTML]
HTML Standard. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[Infra]
Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
[JWA]
JSON Web Algorithms (JWA). M. Jones. IETF. May 2015. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc7518
[JWK]
JSON Web Key (JWK). M. Jones. IETF. May 2015. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc7517
[NIST-SP800-38A]
NIST Special Publication 800-38A: Recommendation for Block Cipher Modes of Operation, Methods and Techniques. NIST. December 2001. URL: http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
[NIST-SP800-38D]
NIST Special Publication 800-38D: Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC. NIST. November 2007. URL: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC2141]
URN Syntax. R. Moats. IETF. May 1997. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc2141
[RFC2315]
PKCS #7: Cryptographic Message Syntax Version 1.5. B. Kaliski. IETF. March 1998. Informational. URL: https://www.rfc-editor.org/rfc/rfc2315
[RFC3394]
Advanced Encryption Standard (AES) Key Wrap Algorithm. J. Schaad; R. Housley. IETF. September 2002. Informational. URL: https://www.rfc-editor.org/rfc/rfc3394
[RFC3447]
Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.1. J. Jonsson; B. Kaliski. IETF. February 2003. Informational. URL: https://www.rfc-editor.org/rfc/rfc3447
[RFC4122]
A Universally Unique IDentifier (UUID) URN Namespace. P. Leach; M. Mealling; R. Salz. IETF. July 2005. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc4122
[RFC5208]
Public-Key Cryptography Standards (PKCS) #8: Private-Key Information Syntax Specification Version 1.2. B. Kaliski. IETF. May 2008. Informational. URL: https://www.rfc-editor.org/rfc/rfc5208
[RFC5280]
Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile. D. Cooper; S. Santesson; S. Farrell; S. Boeyen; R. Housley; W. Polk. IETF. May 2008. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc5280
[RFC5480]
Elliptic Curve Cryptography Subject Public Key Information. S. Turner; D. Brown; K. Yiu; R. Housley; T. Polk. IETF. March 2009. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc5480
[RFC5869]
HMAC-based Extract-and-Expand Key Derivation Function (HKDF). H. Krawczyk; P. Eronen. IETF. May 2010. Informational. URL: https://www.rfc-editor.org/rfc/rfc5869
[RFC5915]
Elliptic Curve Private Key Structure. S. Turner; D. Brown. IETF. June 2010. Informational. URL: https://www.rfc-editor.org/rfc/rfc5915
[RFC6090]
Fundamental Elliptic Curve Cryptography Algorithms. D. McGrew; K. Igoe; M. Salter. IETF. February 2011. Informational. URL: https://www.rfc-editor.org/rfc/rfc6090
[RFC7748]
Elliptic Curves for Security. A. Langley; M. Hamburg; S. Turner. IETF. January 2016. Informational. URL: https://www.rfc-editor.org/rfc/rfc7748
[RFC8018]
PKCS #5: Password-Based Cryptography Specification Version 2.1. K. Moriarty, Ed.; B. Kaliski; A. Rusch. IETF. January 2017. Informational. URL: https://www.rfc-editor.org/rfc/rfc8018
[RFC8032]
Edwards-Curve Digital Signature Algorithm (EdDSA). S. Josefsson; I. Liusvaara. IETF. January 2017. Informational. URL: https://www.rfc-editor.org/rfc/rfc8032
[RFC8037]
CFRG Elliptic Curve Diffie-Hellman (ECDH) and Signatures in JSON Object Signing and Encryption (JOSE). I. Liusvaara. IETF. January 2017. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8037
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[RFC8410]
Algorithm Identifiers for Ed25519, Ed448, X25519, and X448 for Use in the Internet X.509 Public Key Infrastructure. S. Josefsson; J. Schaad. IETF. August 2018. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc8410
[SEC1]
SEC 1: Elliptic Curve Cryptography. Certicom Research. URL: http://www.secg.org/sec1-v2.pdf
[WebIDL]
Web IDL Standard. Edgar Chen; Timothy Gu. WHATWG. Living Standard. URL: https://webidl.spec.whatwg.org/
[X690]
Information technology - ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER). Justin Uberti; Cullen Jennings; Eric Rescorla. ITU-T. November 2008. ITU-T Recommendation. URL: https://tools.ietf.org/html/draft-ietf-rtcweb-jsep/

D.2 资料性参考文献

[INDEXEDDB]
Indexed Database API. Nikunj Mehta; Jonas Sicking; Eliot Graff; Andrei Popescu; Jeremy Orlow; Joshua Bell. W3C. 8 January 2015. W3C Recommendation. URL: https://www.w3.org/TR/IndexedDB/