Web 加密 API 中的现代算法

社区组报告草案

最新发布版本:
无
最新编辑稿:
https://wicg.github.io/webcrypto-modern-algos/
编辑:
(Proton AG)
(Okta)
反馈:
GitHub WICG/webcrypto-modern-algos (拉取请求、 新建议题、 未解决的议题)

摘要

本规范为 Web 加密 API 定义了多种后量子安全的现代密码算法, 即 ML-KEM、混合 KEM、 ML-DSA、SLH-DSA、 AES-OCB、ChaCha20-Poly1305、 SHA-3、cSHAKE、 TurboSHAKE、KangarooTwelve、 KMAC 和 Argon2。

本文档状态

本规范由 Web 平台孵化器社区组发布。它不是 W3C 标准,也不处于 W3C 标准流程中。 请注意,根据 W3C 社区贡献者许可协议 (CLA), 退出权受到限制,并且还适用其他条件。 进一步了解 W3C 社区组和商业组。

这是一项非官方提案。

建议通过 GitHub 议题 讨论本规范。

1. 简介

本节不具规范性。

本提案旨在使 Web 加密 API 中可用的密码算法集合现代化,从而使 Web 应用程序能够使用具备后量子安全性且 高性能的密码算法。 为此,添加以下密码算法:

为了支持 ML-KEM、混合 KEM 以及未来可能出现的其他 KEM 的使用, 本提案引入了用于密钥封装和解封装的函数; SubtleCrypto.encapsulateKey、 SubtleCrypto.encapsulateBits、 SubtleCrypto.decapsulateKey 和 SubtleCrypto.decapsulateBits。

此外,本提案还引入了 SubtleCrypto.getPublicKey 函数, 该函数提供了一种从非对称私钥派生公钥的便捷方式, 从而在仅需要私钥时,无需分别存储公钥和私钥。

最后,本提案旨在让特性检测更加容易, 具体方式是添加 SubtleCrypto.supports 函数, 可用于检测给定的算法标识符 (包括任何参数)是否支持给定操作。

2. 规范约定

本规范遵循 [webcrypto] 第 18.3 节中规定的约定。此处定义的算法均 不要求实现,但如果符合规范的用户代理实现了某个 算法,则它必须实现本文档规定的所有受支持操作, 并且必须针对每个受支持的操作,执行 [webcrypto] 第 18.4.3 节中规定的定义算法 步骤。

除了 [webcrypto] 中定义的受支持的操作之外,本规范还使用 以下操作:

3. 部分 SubtleCrypto 接口

本节扩展了 [webcrypto] 的 SubtleCrypto 接口。

WebIDL[SecureContext,Exposed=(Window,Worker)]
partial interface SubtleCrypto {
  Promise<EncapsulatedKey> encapsulateKey(
    AlgorithmIdentifier encapsulationAlgorithm,
    CryptoKey encapsulationKey,
    AlgorithmIdentifier sharedKeyAlgorithm,
    boolean extractable,
    sequence<KeyUsage> keyUsages
  );
  Promise<EncapsulatedBits> encapsulateBits(
    AlgorithmIdentifier encapsulationAlgorithm,
    CryptoKey encapsulationKey
  );

  Promise<CryptoKey> decapsulateKey(
    AlgorithmIdentifier decapsulationAlgorithm,
    CryptoKey decapsulationKey,
    BufferSource ciphertext,
    AlgorithmIdentifier sharedKeyAlgorithm,
    boolean extractable,
    sequence<KeyUsage> keyUsages
  );
  Promise<ArrayBuffer> decapsulateBits(
    AlgorithmIdentifier decapsulationAlgorithm,
    CryptoKey decapsulationKey,
    BufferSource ciphertext
  );

  Promise<CryptoKey> getPublicKey(
    CryptoKey key,
    sequence<KeyUsage> keyUsages
  );

  static boolean supports(DOMString operation,
                   AlgorithmIdentifier algorithm,
                   optional [EnforceRange] unsigned long? length = null);
  static boolean supports(DOMString operation,
                   AlgorithmIdentifier algorithm,
                   AlgorithmIdentifier additionalAlgorithm);
};

3.1 数据类型

3.1.1 密钥格式

本规范将 [webcrypto] 中 KeyFormat 的定义替换为以下内容:

WebIDLenum KeyFormat { "raw-public", "raw-private", "raw-seed", "raw-secret", "raw", "spki", "pkcs8", "jwk" };

本规范规定了多个新的已识别密钥格式 值:

raw-public
未格式化的公钥字节序列。
raw-private
未格式化的私钥字节序列。
raw-seed
未格式化的私钥种子字节序列。
raw-secret
未格式化的秘密密钥字节序列。

对于 [webcrypto] 中所有现有的对称算法, “raw-secret”作为“raw”的别名。

对于 [webcrypto] 中所有现有的非对称算法, “raw-public”作为“raw”的别名。

在 deriveKey() 方法的导入密钥步骤中, 必须使用“raw-secret”作为格式, 而不是“raw”。

3.1.2 密钥用途

本规范将 [webcrypto] 中 KeyUsage 的定义替换为以下内容:

WebIDLenum KeyUsage { "encrypt", "decrypt", "sign", "verify", "deriveKey", "deriveBits", "wrapKey", "unwrapKey", "encapsulateKey", "encapsulateBits", "decapsulateKey", "decapsulateBits" };

本规范规定了多个新的已识别密钥用途 值:

encapsulateKey
允许将密钥用于 SubtleCrypto.encapsulateKey。
encapsulateBits
允许将密钥用于 SubtleCrypto.encapsulateBits。
decapsulateKey
允许将密钥用于 SubtleCrypto.decapsulateKey。
decapsulateBits
允许将密钥用于 SubtleCrypto.decapsulateBits。

3.2 方法和参数

3.2.1 encapsulateKey 方法

encapsulateKey(encapsulationAlgorithm, encapsulationKey, sharedKeyAlgorithm, extractable, usages) 方法封装一个密钥,并返回一个 EncapsulatedKey 对象。 其行为如下:

  1. 令 encapsulationAlgorithm、encapsulationKey、 sharedKeyAlgorithm、 extractable 和 usages 分别为传递给 encapsulateKey() 方法的 encapsulationAlgorithm、 encapsulationKey、 sharedKeyAlgorithm、extractable 和 keyUsages 参数。

  2. 令 normalizedEncapsulationAlgorithm 为规范化 算法的结果,其中 alg 设置为 encapsulationAlgorithm,op 设置为 “encapsulate”。

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

  4. 令 normalizedSharedKeyAlgorithm 为规范化 算法的结果,其中 alg 设置为 sharedKeyAlgorithm,op 设置为 “importKey”。

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

  6. 令 realm 为 this 的相关 领域。

  7. 令 promise 为一个新的 Promise。

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

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

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

  11. 如果 encapsulationKey 的 [[usages]] 内部槽不包含值为“encapsulateKey”的条目, 则抛出一个 InvalidAccessError。

  12. 令 encapsulatedBits 为使用 encapsulationKey 执行由 encapsulationKey 的 [[algorithm]] 内部槽指定的封装操作所得的结果。

  13. 令 sharedKey 为执行由 normalizedSharedKeyAlgorithm 指定的导入密钥操作所得的结果,其中使用“raw-secret”作为 format,使用 encapsulatedBits 的 sharedKey 字段作为 keyData,使用 sharedKeyAlgorithm 作为 algorithm,并使用 extractable 和 usages。

  14. 将 sharedKey 的 [[extractable]] 内部槽设置为 extractable。

  15. 将 sharedKey 的 [[usages]] 内部槽设置为 usages 的规范化值。

  16. 令 encapsulatedKey 为一个新的 EncapsulatedKey 字典, 其中将 sharedKey 设置为 sharedKey, 并将 ciphertext 设置为 encapsulatedBits 的 ciphertext 字段。

  17. 在加密任务源上, 给定 realm 的全局对象,排入 一个全局任务,以执行剩余步骤。

  18. 令 result 为按照 [WebIDL] 的定义, 在 realm 中将 encapsulatedKey 转换为 ECMAScript 对象所得的结果。

  19. 使用 result 兑现 promise。

3.2.2 encapsulateBits 方法

encapsulateBits(encapsulationAlgorithm, encapsulationKey) 方法封装一个密钥,并返回一个 EncapsulatedBits 对象。 其行为如下:

  1. 令 encapsulationAlgorithm 和 encapsulationKey 分别为传递给 encapsulateBits() 方法的 encapsulationAlgorithm 和 encapsulationKey 参数。

  2. 令 normalizedEncapsulationAlgorithm 为规范化 算法的结果,其中 alg 设置为 encapsulationAlgorithm,op 设置为 “encapsulate”。

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

  4. 令 realm 为 this 的相关 领域。

  5. 令 promise 为一个新的 Promise。

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

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

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

  9. 如果 encapsulationKey 的 [[usages]] 内部槽不包含值为 “encapsulateBits”的条目, 则抛出一个 InvalidAccessError。

  10. 令 encapsulatedBits 为使用 encapsulationKey 执行由 encapsulationKey 的 [[algorithm]] 内部槽指定的封装操作所得的结果。

  11. 在加密任务源上, 给定 realm 的全局对象,排入 一个全局任务,以执行剩余步骤。

  12. 令 result 为按照 [WebIDL] 的定义, 在 realm 中将 encapsulatedBits 转换为 ECMAScript 对象所得的结果。

  13. 使用 result 兑现 promise。

3.2.3 decapsulateKey 方法

decapsulateKey(decapsulationAlgorithm, decapsulationKey, ciphertext, sharedKeyAlgorithm, extractable, usages) 方法解封装一个密钥,并返回一个 CryptoKey 对象。 其行为如下:

  1. 令 decapsulationAlgorithm、decapsulationKey、 sharedKeyAlgorithm、 extractable 和 usages 分别为传递给 decapsulateKey() 方法的 decapsulationAlgorithm、 decapsulationKey、sharedKeyAlgorithm、extractable 和 keyUsages 参数。

  2. 令 normalizedDecapsulationAlgorithm 为规范化 算法的结果,其中 alg 设置为 decapsulationAlgorithm,op 设置为 “decapsulate”。

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

  4. 令 normalizedSharedKeyAlgorithm 为规范化 算法的结果,其中 alg 设置为 sharedKeyAlgorithm,op 设置为 “importKey”。

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

  6. 令 ciphertext 为对传递给 decapsulateKey() 方法的 ciphertext 参数所持有的字节创建副本所得的结果。

  7. 令 realm 为 this 的相关 领域。

  8. 令 promise 为一个新的 Promise。

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

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

  11. 如果 normalizedDecapsulationAlgorithm 的 name 成员不等于 decapsulationKey 的 [[algorithm]] 内部槽的 name 属性,则抛出一个 InvalidAccessError。

  12. 如果 decapsulationKey 的 [[usages]] 内部槽不包含值为“decapsulateKey”的条目, 则抛出一个 InvalidAccessError。

  13. 令 decapsulatedBits 为使用 decapsulationKey 和 ciphertext 执行由 decapsulationKey 的 [[algorithm]] 内部槽指定的解封装操作所得的结果。

  14. 令 sharedKey 为执行由 normalizedSharedKeyAlgorithm 指定的导入密钥操作所得的结果,其中使用“raw-secret”作为 format,使用 decapsulatedBits 作为 keyData, 使用 sharedKeyAlgorithm 作为 algorithm,并使用 extractable 和 usages。

  15. 将 sharedKey 的 [[extractable]] 内部槽设置为 extractable。

  16. 将 sharedKey 的 [[usages]] 内部槽设置为 usages 的规范化值。

  17. 在加密任务源上, 给定 realm 的全局对象,排入 一个全局任务,以执行剩余步骤。

  18. 令 result 为按照 [WebIDL] 的定义, 在 realm 中将 sharedKey 转换为 ECMAScript 对象所得的结果。

  19. 使用 result 兑现 promise。

3.2.4 decapsulateBits 方法

decapsulateBits(decapsulationAlgorithm, decapsulationKey, ciphertext) 方法解封装一个密钥,并返回一个 ArrayBuffer 对象。 其行为如下:

  1. 令 decapsulationAlgorithm 和 decapsulationKey 分别为传递给 decapsulateBits() 方法的 decapsulationAlgorithm 和 decapsulationKey 参数。

  2. 令 normalizedDecapsulationAlgorithm 为规范化 算法的结果,其中 alg 设置为 decapsulationAlgorithm,op 设置为 “decapsulate”。

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

  4. 令 ciphertext 为对传递给 decapsulateBits() 方法的 ciphertext 参数所持有的字节创建副本所得的结果。

  5. 令 realm 为 this 的相关 领域。

  6. 令 promise 为一个新的 Promise。

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

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

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

  10. 如果 decapsulationKey 的 [[usages]] 内部槽不包含值为 “decapsulateBits”的条目, 则抛出一个 InvalidAccessError。

  11. 令 decapsulatedBits 为使用 decapsulationKey 和 ciphertext 执行由 decapsulationKey 的 [[algorithm]] 内部槽指定的解封装操作所得的结果。

  12. 在加密任务源上, 给定 realm 的全局对象,排入 一个全局任务,以执行剩余步骤。

  13. 令 result 为在 realm 中创建一个 包含 decapsulatedBits 的 ArrayBuffer 所得的结果。

  14. 使用 result 兑现 promise。

3.2.5 getPublicKey 方法

getPublicKey(key, usages) 方法返回与给定私钥对应的公钥。 其行为如下:

  1. 令 key 和 usages 分别为传递给 getPublicKey() 方法的 key 和 keyUsages 参数。

  2. 令 algorithm 为 key 的 [[algorithm]] 内部槽。

  3. 如果由 algorithm 标识的密码算法 不支持从私钥派生公钥, 则返回一个以 NotSupportedError 拒绝的 Promise。

  4. 令 realm 为 this 的相关 领域。

  5. 令 promise 为一个新的 Promise。

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

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

  8. 如果 key 的 [[type]] 内部槽不是“private”, 则抛出一个 InvalidAccessError。

  9. 如果 usages 包含由 algorithm 标识的算法 不支持用于公钥的条目, 则抛出一个 SyntaxError。

  10. 令 publicKey 为一个新的 CryptoKey, 它表示与 key 的 [[handle]] 内部槽所表示的私钥对应的公钥。

  11. 如果发生错误,则抛出一个 OperationError。

  12. 将 publicKey 的 [[type]] 内部槽设置为“public”。

  13. 将 publicKey 的 [[algorithm]] 内部槽设置为 algorithm。

  14. 将 publicKey 的 [[extractable]] 内部槽设置为 true。

  15. 将 publicKey 的 [[usages]] 内部槽设置为 usages。

  16. 在加密任务源上, 给定 realm 的全局对象,排入 一个全局任务,以执行剩余步骤。

  17. 令 result 为按照 [WebIDL] 的定义, 在 realm 中将 publicKey 转换为 ECMAScript 对象所得的结果。

  18. 使用 result 兑现 promise。

3.2.6 supports 方法

supports(operation, algorithm, length) 方法返回一个布尔值,指示实现是否 支持使用指定的 AlgorithmIdentifier 执行给定操作,并可通过可选的 length 参数指示当 operation 为 "deriveBits" 时要派生的位数。 其行为如下:

  1. 如果 operation 不是以下值之一: "encrypt"、"decrypt"、"sign"、"verify"、 "digest"、"generateKey"、"deriveKey"、 "deriveBits"、 "importKey"、"exportKey"、"wrapKey"、 "unwrapKey"、 "encapsulateKey"、"encapsulateBits"、 "decapsulateKey"、"decapsulateBits" 或 "getPublicKey", 返回 false。

  2. 返回检查算法支持情况的结果, 其中将 op 设置为 operation,将 alg 设置为 algorithm, 并将 length 设置为 length。

supports(operation, algorithm, additionalAlgorithm) 方法返回一个布尔值,指示实现是否 支持使用指定的 AlgorithmIdentifier 执行给定操作。 当 operation 为 "deriveKey" 时,附加算法指示要派生的密钥类型; 当 operation 为 "wrapKey" 时,指示包装前要导出的密钥类型; 当 operation 为 "unwrapKey" 时,指示解包后要导入的密钥类型。 其行为如下:

  1. 如果 operation 不是以下值之一: "encrypt"、"decrypt"、"sign"、"verify"、 "digest"、"generateKey"、"deriveKey"、 "deriveBits"、 "importKey"、"exportKey"、"wrapKey"、 "unwrapKey"、 "encapsulateKey"、"encapsulateBits"、 "decapsulateKey"、"decapsulateBits" 或 "getPublicKey", 返回 false。

  2. 如果 operation 为 "deriveKey" 或 "unwrapKey":

    如果检查 算法支持情况的结果 (其中将 op 设置为 "importKey" 并将 alg 设置为 additionalAlgorithm) 为 false, 则返回 false。

    如果 operation 为 "wrapKey":

    如果检查 算法支持情况的结果 (其中将 op 设置为 "exportKey" 并将 alg 设置为 additionalAlgorithm) 为 false, 则返回 false。

  3. 如果 operation 为 "encapsulateKey" 或 "decapsulateKey":
    1. 令 normalizedAlgorithm 为 规范化 算法的结果,其中 将 alg 设置为 algorithm,并将 op 设置为 "get shared key length"。

    2. 如果发生错误,则返回 false。

    3. 令 sharedKeyLength 为执行由 normalizedAlgorithm 指定的获取共享 密钥长度 算法并使用 algorithm 所得到的结果。

    4. 令 normalizedAdditionalAlgorithm 为 规范化 算法的结果,其中 将 alg 设置为 additionalAlgorithm,并将 op 设置为 "importKey"。

    5. 如果发生错误,则返回 false。

    6. 如果根据操作步骤确定 支持情况的结果 (其中将 op 设置为 "importKey",将 normalizedAlgorithm 设置为 normalizedAdditionalAlgorithm,并将 length 设置为 null)为 false, 则返回 false。

    7. 如果由 normalizedAdditionalAlgorithm 指定的导入密钥操作,对于每个满足以下条件的 keyData 值都会 抛出错误: 该值是 一个字节序列, 其以位为单位的长度为 sharedKeyLength,且 format 为 "raw-secret", 则返回 false。

  4. 令 length 为 null。

  5. 如果 operation 为 "deriveKey":
    1. 如果检查算法 支持情况的结果 (其中将 op 设置为 "get key length" 并将 alg 设置为 additionalAlgorithm) 为 false, 则返回 false。

    2. 令 normalizedAdditionalAlgorithm 为 规范化 算法的结果,其中 将 alg 设置为 additionalAlgorithm,并将 op 设置为 "get key length"。

    3. 令 length 为执行由 additionalAlgorithm 指定的获取密钥长度 算法并使用 normalizedAdditionalAlgorithm 所得到的结果。

    4. 将 operation 设置为 "deriveBits"。

  6. 返回检查算法支持情况的结果, 其中将 op 设置为 operation,将 alg 设置为 algorithm, 并将 length 设置为 length。

3.3 检查对 算法的支持

检查算法支持情况算法 定义了检查给定算法是否支持给定操作的过程。 其输入为操作名称 op、一个 AlgorithmIdentifier alg 和一个 length 参数。其输出为布尔值。 其行为如下:

  1. 如果 op 为 "encapsulateKey" 或 "encapsulateBits",将 op 设置为 "encapsulate"。

  2. 如果 op 为 "decapsulateKey" 或 "decapsulateBits",将 op 设置为 "decapsulate"。

  3. 如果 op 为 "getPublicKey":
    1. 令 normalizedAlgorithm 为 规范化 算法的结果,其中 将 alg 设置为 alg,并将 op 设置为 "exportKey"。

    2. 如果发生错误,则返回 false。

    3. 如果由 normalizedAlgorithm 标识的密码算法 不支持从私钥派生公钥, 则返回 false。

    4. 否则,返回 true。

  4. 令 normalizedAlgorithm 为 规范化 算法的结果,其中 将 alg 设置为 alg,并将 op 设置为 op。

  5. 如果发生错误:
    1. 如果 op 为 "wrapKey", 返回检查算法 支持情况的结果, 其中将 op 设置为 "encrypt" 并将 alg 设置为 alg。

    2. 如果 op 为 "unwrapKey", 返回检查算法 支持情况的结果, 其中将 op 设置为 "decrypt" 并将 alg 设置为 alg。

    3. 否则,返回 false。

  6. 返回根据操作 步骤确定支持情况的结果, 其中将 op 设置为 op,将 normalizedAlgorithm 设置为 normalizedAlgorithm, 并将 length 设置为 length。

根据操作步骤确定支持情况算法 确定规范化算法的操作步骤是否表明支持该操作。 其输入为操作名称 op、一个 Algorithm normalizedAlgorithm 和一个 length 参数。其输出为布尔值。 其行为如下:

  1. 如果指定的操作或规范化算法(或其某个参数值) 预期会由于实现特定的原因而失败(对于任意密钥和/或数据) (例如已知不符合规范),则返回 false。

  2. 如果 op 为 "generateKey" 或 "importKey",令 usages 为空列表。

  3. 对于由 normalizedAlgorithm 指定的算法中 由 op 指定的操作的每个步骤:

    如果该步骤要求抛出错误:
    返回 false。
    如果该步骤要求生成密钥:
    返回 true。
    如果该步骤依赖不可用的参数,例如 key、 plaintext 或 ciphertext:
    返回 true。
    如果该步骤要求返回一个值:
    返回 true。
    否则:
    执行该步骤。
    注

    所引用算法中的步骤可以访问此上下文中的 normalizedAlgorithm、 length 和 usages 变量。

  4. 断言:永远不会 到达此步骤, 因为该操作的某个步骤必然会要求 返回一个值或抛出错误,从而分别使我们返回 true 或 false。

4. 封装字典

WebIDLdictionary EncapsulatedKey {
  CryptoKey sharedKey;
  ArrayBuffer ciphertext;
};

dictionary EncapsulatedBits {
  ArrayBuffer sharedKey;
  ArrayBuffer ciphertext;
};

EncapsulatedKey 字典表示一个 由 sharedKey 和一个 ciphertext 组成的封装密钥。

EncapsulatedBits 字典表示 由 sharedKey 和一个 ciphertext 组成的封装密钥比特。

5. 部分 JsonWebKey 字典

WebIDLpartial dictionary JsonWebKey {
  // 以下字段在 RFC 9964 中定义
  DOMString pub;
  DOMString priv;
};

[webcrypto] 中定义的 JsonWebKey 字典的此扩展, 提供了一种表示具有 [RFC9964] 中定义的“AKP”密钥类型的密钥的方法。

6. ML-KEM

6.1 描述

本节为非规范性内容。

本节描述如何使用 ML-KEM 进行密钥封装和解封装, 如 [FIPS-203] 中所规定。

6.2 注册

此算法的已识别算法 名称为 "ML-KEM-512"、"ML-KEM-768" 和 "ML-KEM-1024"。

操作 参数 结果
封装 无 EncapsulatedBits
解封装 无 字节 序列
获取共享密钥长度 无 整数
generateKey 无 CryptoKeyPair
importKey 无 CryptoKey
exportKey 无 对象

6.3 JSON Web Key 表示形式

ML-KEM 密钥使用 [RFC9964] 中定义的 "AKP"(算法密钥对)密钥类型来表示 JWK。"alg"(算法)参数标识具体的 ML-KEM 参数集。 公钥包含在 "pub" 参数中。如果包含私钥,则使用 "priv" 参数表示。以 JWK 表示时,所有密钥参数均采用 base64url 编码。

6.4 操作

6.4.1 封装

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

  2. 使用由 algorithm 的 name 成员所指示的参数集, 执行 [FIPS-203] 第 7.2 节所述的封装密钥检查, 使用 key 的 [[handle]] 内部槽所表示的密钥作为 ek 输入参数。

    注

    如果为了提高性能而有需要,可以为该 CryptoKey 对象缓存或预计算此检查的结果。

  3. 如果封装密钥检查失败,则返回一个 OperationError。

  4. 令 sharedKey 和 ciphertext 为执行 [FIPS-203] 第 7.2 节所述 ML-KEM.Encaps 函数所得的输出, 使用由 algorithm 的 name 成员所指示的参数集, 并使用 key 的 [[handle]] 内部槽所表示的密钥作为 ek 输入参数。

  5. 如果 ML-KEM.Encaps 函数返回错误,则返回一个 OperationError。

  6. 令 result 为一个新的 EncapsulatedBits 字典。

  7. 将 result 的 sharedKey 属性 设置为创建一个 包含 sharedKey 的 ArrayBuffer 所得的结果。

  8. 将 result 的 ciphertext 属性 设置为创建一个 包含 ciphertext 的 ArrayBuffer 所得的结果。

  9. 返回 result。

6.4.2 解封装

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

  2. 使用由 algorithm 的 name 成员所指示的参数集, 执行 [FIPS-203] 第 7.3 节所述的解封装输入检查, 使用 key 的 [[handle]] 内部槽所表示的密钥作为 dk 输入参数,并将 ciphertext 作为 c 输入参数。

    注

    如果为了提高性能而有需要,可以为该 CryptoKey 对象缓存或预计算解封装密钥类型检查和哈希检查的结果。

  3. 如果解封装密钥检查失败,则返回一个 OperationError。

  4. 令 sharedKey 为执行 [FIPS-203] 第 7.3 节所述 ML-KEM.Decaps 函数所得的输出, 使用由 algorithm 的 name 成员所指示的参数集, 并使用 key 的 [[handle]] 内部槽所表示的密钥作为 dk 输入参数,并将 ciphertext 作为 c 输入参数。

  5. 返回 sharedKey。

6.4.3 获取共享密钥长度

  1. 返回 256。

6.4.4 生成密钥

  1. 如果 usages 包含不是 "encapsulateKey"、"encapsulateBits"、 "decapsulateKey" 或 "decapsulateBits" 之一的条目, 则抛出一个 SyntaxError。

  2. 按照 [FIPS-203] 第 7.1 节所述生成一个 ML-KEM 密钥对, 使用由 normalizedAlgorithm 的 name 成员所指示的参数集。

    注

    为了能够导出种子 (d, z), 需要将 d 和 z 作为所生成密钥材料的一部分存储。

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

  4. 令 algorithm 为一个新的 KeyAlgorithm 对象。

  5. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

  6. 令 publicKey 为一个新的 CryptoKey, 表示所生成密钥对的封装密钥。

  7. 将 publicKey 的 [[type]] 内部槽设置为 "public"。

  8. 将 publicKey 的 [[algorithm]] 内部 槽设置为 algorithm。

  9. 将 publicKey 的 [[extractable]] 内部 槽设置为 true。

  10. 将 publicKey 的 [[usages]] 内部槽设置为 usages 与 [ "encapsulateKey", "encapsulateBits" ] 的 用途 交集。

  11. 令 privateKey 为一个新的 CryptoKey, 表示所生成密钥对的解封装密钥。

  12. 将 privateKey 的 [[type]] 内部槽设置为 "private"。

  13. 将 privateKey 的 [[algorithm]] 内部 槽设置为 algorithm。

  14. 将 privateKey 的 [[extractable]] 内部 槽设置为 extractable。

  15. 将 privateKey 的 [[usages]] 内部槽设置为 usages 与 [ "decapsulateKey", "decapsulateBits" ] 的 用途 交集。

  16. 令 result 为一个新的 CryptoKeyPair 字典。

  17. 将 result 的 publicKey 属性 设置为 publicKey。

  18. 将 result 的 privateKey 属性 设置为 privateKey。

  19. 返回 result。

6.4.5 导入密钥

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

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

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

    3. 如果解析时发生错误, 则抛出一个 DataError。

    4. 如果 normalizedAlgorithm 的 name 成员是 "ML-KEM-512":

      令 expectedOid 为 id-alg-ml-kem-512 (2.16.840.1.101.3.4.4.1)。

      如果 normalizedAlgorithm 的 name 成员是 "ML-KEM-768":

      令 expectedOid 为 id-alg-ml-kem-768 (2.16.840.1.101.3.4.4.2)。

      如果 normalizedAlgorithm 的 name 成员是 "ML-KEM-1024":

      令 expectedOid 为 id-alg-ml-kem-1024 (2.16.840.1.101.3.4.4.3)。

      否则:

      抛出一个 NotSupportedError。

    5. 如果 spki 的 algorithm AlgorithmIdentifier 字段中的 algorithm 对象标识符字段 不等于 expectedOid, 则抛出一个 DataError。

    6. 如果 spki 的 algorithm AlgorithmIdentifier 字段中存在 parameters 字段, 则抛出一个 DataError。

    7. 令 publicKey 为由 spki 的 subjectPublicKey 字段标识的 ML-KEM 公钥。

    8. 令 key 为一个新的 CryptoKey, 表示 publicKey。

    9. 将 key 的 [[type]] 内部槽 设置为 "public"

    10. 令 algorithm 为一个新的 KeyAlgorithm。

    11. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

    12. 将 key 的 [[algorithm]] 内部槽设置为 algorithm。

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

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

    3. 如果解析时发生错误, 则抛出一个 DataError。

    4. 如果 normalizedAlgorithm 的 name 成员是 "ML-KEM-512":

      令 expectedOid 为 id-alg-ml-kem-512 (2.16.840.1.101.3.4.4.1)。

      令 asn1Structure 为 ASN.1 ML-KEM-512-PrivateKey 结构。

      如果 normalizedAlgorithm 的 name 成员是 "ML-KEM-768":

      令 expectedOid 为 id-alg-ml-kem-768 (2.16.840.1.101.3.4.4.2)。

      令 asn1Structure 为 ASN.1 ML-KEM-768-PrivateKey 结构。

      如果 normalizedAlgorithm 的 name 成员是 "ML-KEM-1024":

      令 expectedOid 为 id-alg-ml-kem-1024 (2.16.840.1.101.3.4.4.3)。

      令 asn1Structure 为 ASN.1 ML-KEM-1024-PrivateKey 结构。

      否则:

      抛出一个 NotSupportedError。

    5. 如果 privateKeyInfo 的 privateKeyAlgorithm PrivateKeyAlgorithm 字段中的 algorithm 对象标识符字段不等于 expectedOid, 则抛出一个 DataError。

    6. 如果 privateKeyInfo 的 privateKeyAlgorithm PrivateKeyAlgorithmIdentifier 字段中 存在 parameters 字段, 则抛出一个 DataError。

    7. 令 mlKemPrivateKey 为执行 解析 ASN.1 结构 算法所得的结果,其中将 privateKeyInfo 的 privateKey 字段作为 data,将 asn1Structure 作为 structure,并将 exactData 设置为 true。

    8. 如果解析时发生错误, 则抛出一个 DataError。

    9. 如果 mlKemPrivateKey 表示一个采用 expandedKey 格式的 ML-KEM 密钥, 或者如果 mlKemPrivateKey 表示一个采用 both 格式的 ML-KEM 密钥 且不支持 both 格式,则抛出一个 NotSupportedError。

    10. 如果 mlKemPrivateKey 表示一个采用 both 格式的 ML-KEM 密钥, 且 seed 字段与 expandedKey 字段不对应, 则抛出一个 DataError。

    11. 令 key 为一个新的 CryptoKey, 表示由 mlKemPrivateKey 标识的 ML-KEM 私钥。

    12. 将 key 的 [[type]] 内部槽 设置为 "private"

    13. 令 algorithm 为一个新的 KeyAlgorithm。

    14. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

    15. 将 key 的 [[algorithm]] 内部槽设置为 algorithm。

    如果 format 是 "raw-public":
    1. 如果 usages 包含不是 "encapsulateKey" 或 "encapsulateBits" 的条目, 则抛出一个 SyntaxError。

    2. 令 data 为 keyData。

    3. 令 key 为一个新的 CryptoKey, 表示 data 中的 ML-KEM 公钥数据。

    4. 将 key 的 [[type]] 内部槽 设置为 "public"

    5. 令 algorithm 为一个新的 KeyAlgorithm。

    6. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

    7. 将 key 的 [[algorithm]] 内部槽设置为 algorithm。

    如果 format 是 "raw-seed":
    1. 如果 usages 包含不是 "decapsulateKey" 或 "decapsulateBits" 的条目, 则抛出一个 SyntaxError。

    2. 令 data 为 keyData。

    3. 如果 data 的位长度不是 512, 则抛出一个 DataError。

    4. 令 privateKey 为执行 [FIPS-203] 第 6.1 节所述 ML-KEM.KeyGen_internal 函数所得的结果, 使用由 normalizedAlgorithm 的 name 成员所指示的参数集, 使用 data 的前 256 位作为 d,并将 data 的后 256 位作为 z。

    5. 令 key 为一个新的 CryptoKey, 表示由 privateKey 标识的 ML-KEM 私钥。

    6. 将 key 的 [[type]] 内部槽 设置为 "private"

    7. 令 algorithm 为一个新的 KeyAlgorithm。

    8. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

    9. 将 key 的 [[algorithm]] 内部槽设置为 algorithm。

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

      令 jwk 等于 keyData。

      否则:

      抛出一个 DataError。

    2. 如果 jwk 的 priv 字段存在, 且 usages 包含不是 "decapsulateKey" 或 "decapsulateBits" 的条目, 则抛出一个 SyntaxError。

    3. 如果 jwk 的 priv 字段不存在, 且 usages 包含不是 "encapsulateKey" 或 "encapsulateBits" 的条目, 则抛出一个 SyntaxError。

    4. 如果 jwk 的 kty 字段不是 "AKP", 则抛出一个 DataError。

    5. 如果 jwk 的 alg 字段不存在, 或其值未标识由 normalizedAlgorithm 的 name 成员 所指示的 ML-KEM 参数集, 则抛出一个 DataError。

      注

      在 IANA JSON Web 签名和加密算法注册表中 为本规范定义的 ML-KEM 参数集注册的 "alg" 值 为 ML-KEM-512、ML-KEM-768 和 ML-KEM-1024。 实现还应接受该注册表中标识使用相同 ML-KEM 参数集的 JWE 算法的其他值,前提是该 JWE 算法的 JWK 表示形式除 "alg" 值外与此处定义的表示形式 兼容。 示例包括 [draft-ietf-jose-hpke-pq-pqt] 中提出的值,一旦这些值完成注册。

    6. 如果 usages 非空且 jwk 的 use 字段存在 且不等于 "enc",则抛出一个 DataError。

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

    8. 如果 jwk 的 ext 字段存在且 值为 false,而 extractable 为 true, 则抛出一个 DataError。

    9. 如果 jwk 的 priv 字段 存在:
      1. 如果 jwk 的 priv 属性不包含一个有效的 base64url 编码种子, 该种子表示一个 ML-KEM 私钥, 则抛出 一个 DataError。

      2. 令 key 为一个新的 CryptoKey 对象,它表示通过将 jwk 的 priv 属性解释为 base64url 编码种子 所标识的 ML-KEM 私钥。

      3. 将 key 的 [[type]] 内部槽设置为 "private"。

      4. 如果 jwk 的 pub 属性不包含 base64url 编码的公钥, 该公钥表示与 key 对应的 ML-KEM 公钥, 则抛出 一个 DataError。

      否则:
      1. 如果 jwk 的 pub 属性不包含一个有效的 base64url 编码公钥, 该公钥表示一个 ML-KEM 公钥, 则抛出 一个 DataError。

      2. 令 key 为一个新的 CryptoKey 对象,它表示通过将 jwk 的 pub 属性解释为 base64url 编码公钥 所标识的 ML-KEM 公钥。

      3. 将 key 的 [[type]] 内部槽设置为 "public"。

    10. 令 algorithm 为一个新的 KeyAlgorithm 对象实例。

    11. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 成员。

    12. 将 key 的 [[algorithm]] 内部槽设置为 algorithm。

    否则:
    抛出一个 NotSupportedError。
  3. 返回 key。

6.4.6 导出密钥

  1. 令 key 为要导出的 CryptoKey。

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

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

    2. 令 keyAlgorithm 为 key 的 [[algorithm]] 内部槽。

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

      • 将 algorithm 字段设置为一个 AlgorithmIdentifier ASN.1 类型,并具有以下 属性:

        • 如果 keyAlgorithm 的 name 成员是 "ML-KEM-512":

          将 algorithm 对象标识符设置为 id-alg-ml-kem-512 (2.16.840.1.101.3.4.4.1) OID。

          如果 keyAlgorithm 的 name 成员是 "ML-KEM-768":

          将 algorithm 对象标识符设置为 id-alg-ml-kem-768 (2.16.840.1.101.3.4.4.2) OID。

          如果 keyAlgorithm 的 name 成员是 "ML-KEM-1024":

          将 algorithm 对象标识符设置为 id-alg-ml-kem-1024 (2.16.840.1.101.3.4.4.3) OID。

          否则:

          抛出 一个 NotSupportedError。

      • 将 subjectPublicKey 字段设置为 keyData。

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

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

    2. 令 keyAlgorithm 为 key 的 [[algorithm]] 内部槽。

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

      • 将 version 字段设置为 0。

      • 将 privateKeyAlgorithm 字段设置为一个 PrivateKeyAlgorithmIdentifier ASN.1 类型,并具有以下 属性:

        • 如果 keyAlgorithm 的 name 成员是 "ML-KEM-512":

          将 algorithm 对象标识符设置为 id-alg-ml-kem-512 (2.16.840.1.101.3.4.4.1) OID。

          如果 keyAlgorithm 的 name 成员是 "ML-KEM-768":

          将 algorithm 对象标识符设置为 id-alg-ml-kem-768 (2.16.840.1.101.3.4.4.2) OID。

          如果 keyAlgorithm 的 name 成员是 "ML-KEM-1024":

          将 algorithm 对象标识符设置为 id-alg-ml-kem-1024 (2.16.840.1.101.3.4.4.3) OID。

          否则:

          抛出 一个 NotSupportedError。

      • 按如下方式设置 privateKey 字段:

        • 如果 keyAlgorithm 的 name 成员是 "ML-KEM-512":

          将 privateKey 字段设置为对 一个 ML-KEM-512-PrivateKey ASN.1 类型进行 DER 编码所得的结果,该类型表示由 key 的 [[handle]] 内部槽所表示的 ML-KEM 私钥种子,并采用仅种子格式 (使用上下文特定的 [0] 原始标签, 以及 OCTET STRING 的隐式编码)。

          如果 keyAlgorithm 的 name 成员是 "ML-KEM-768":

          将 privateKey 字段设置为对 一个 ML-KEM-768-PrivateKey ASN.1 类型进行 DER 编码所得的结果,该类型表示由 key 的 [[handle]] 内部槽所表示的 ML-KEM 私钥种子,并采用仅种子格式 (使用上下文特定的 [0] 原始标签, 以及 OCTET STRING 的隐式编码)。

          如果 keyAlgorithm 的 name 成员是 "ML-KEM-1024":

          将 privateKey 字段设置为对 一个 ML-KEM-1024-PrivateKey ASN.1 类型 进行 DER 编码所得的结果,该类型表示由 key 的 [[handle]] 内部槽所表示的 ML-KEM 私钥种子,并采用仅种子格式 (使用上下文特定的 [0] 原始标签, 以及 OCTET STRING 的隐式编码)。

          否则:

          抛出 一个 NotSupportedError。

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

    如果 format 是 "raw-public":
    1. 如果 key 的 [[type]] 内部槽 不是 "public", 则抛出一个 InvalidAccessError。

    2. 令 data 为一个字节序列, 其中包含 由 key 的 [[handle]] 内部槽所表示的密钥的原始八位组。

    3. 令 result 为 data。

    如果 format 是 "raw-seed":
    1. 如果 key 的 [[type]] 内部槽 不是 "private", 则抛出一个 InvalidAccessError。

    2. 令 data 为一个字节序列, 其中包含由 key 的 [[handle]] 内部槽所表示的密钥的 d 和 z 种子变量的串联。

      注

      d 和 z 种子变量是在 ML-KEM.KeyGen 函数中按照 [FIPS-203] 第 7.1 节所述进行采样的。

    3. 令 result 为 data。

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

    2. 令 keyAlgorithm 为 key 的 [[algorithm]] 内部槽。

    3. 将 jwk 的 kty 属性设置为 "AKP"。

    4. 将 jwk 的 alg 属性设置为 keyAlgorithm 的 name 成员。

    5. 将 jwk 的 pub 属性 设置为与 key 的 [[handle]] 内部槽相对应的 base64url 编码公钥。

    6. 如果 key 的 [[type]] 内部槽 是 "private":
      将 jwk 的 priv 属性 设置为由 key 的 [[handle]] 内部槽所表示的 base64url 编码种子。
    7. 将 jwk 的 key_ops 属性设置为 key 的 usages 属性。

    8. 将 jwk 的 ext 属性设置为 key 的 [[extractable]] 内部槽。

    9. 令 result 为 jwk。

    否则:

    抛出一个 NotSupportedError。

  4. 返回 result。

7. 混合 KEM

7.1 描述

本节为非规范性内容。

本节描述如何使用混合后量子/传统密钥 封装机制进行密钥封装和解封装, 如 [draft-irtf-cfrg-concrete-hybrid-kems-04] 中所规定。

7.2 注册

此算法的已识别算法 名称为 "MLKEM768-P256"、"MLKEM768-X25519" 和 "MLKEM1024-P384"。

操作 参数 结果
封装 无 EncapsulatedBits
解封装 无 字节 序列
获取共享密钥长度 无 整数
生成密钥 无 CryptoKeyPair
导入密钥 无 CryptoKey
导出密钥 无 对象

7.3 JSON Web 密钥表示

混合 KEM 密钥使用 [RFC9964] 中定义的 "AKP"(算法密钥对)密钥类型进行 JWK 表示。"alg"(算法)参数标识特定的混合 KEM 实例。 公钥存放在 "pub" 参数中。如果包含私钥,则使用 "priv" 参数表示。以 JWK 表示时,所有密钥参数均使用 base64url 编码。

7.4 操作

7.4.1 封装

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

  2. 令 sharedKey 和 ciphertext 为 对 algorithm 的 name 成员所指示的混合 KEM 实例执行 [draft-irtf-cfrg-concrete-hybrid-kems-04] 第 4 节中的 Encaps 函数所得的输出, 使用 key 的 [[handle]] 内部槽所表示的密钥作为 ek 输入参数。

  3. 如果 Encaps 函数返回错误,则返回一个 OperationError。

  4. 令 result 为一个新的 EncapsulatedBits 字典。

  5. 将 result 的 sharedKey 属性 设置为创建 一个包含 sharedKey 的 ArrayBuffer 所得的结果。

  6. 将 result 的 ciphertext 属性 设置为创建 一个包含 ciphertext 的 ArrayBuffer 所得的结果。

  7. 返回 result。

7.4.2 解封装

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

  2. 令 sharedKey 为对 algorithm 的 name 成员所指示的混合 KEM 实例执行 [draft-irtf-cfrg-concrete-hybrid-kems-04] 第 4 节中的 Decaps 函数所得的输出, 使用 key 的 [[handle]] 内部槽所表示的密钥作为 dk 输入参数,并使用 ciphertext 作为 ct 输入参数。

  3. 如果 Decaps 函数返回错误,则返回一个 OperationError。

  4. 返回 sharedKey。

7.4.3 获取共享密钥长度

  1. 返回 256。

7.4.4 生成密钥

  1. 如果 usages 包含一个不是 "encapsulateKey"、"encapsulateBits"、 "decapsulateKey" 或 "decapsulateBits" 之一的条目, 则抛出一个 SyntaxError。

  2. 通过对 normalizedAlgorithm 的 name 成员所指示的混合 KEM 实例执行 [draft-irtf-cfrg-hybrid-kems-12] 第 5.2 节中描述的 GenerateKeyPair 函数, 生成一个混合 KEM 密钥对。

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

  4. 令 algorithm 为一个新的 KeyAlgorithm 对象。

  5. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

  6. 令 publicKey 为一个新的 CryptoKey, 表示所生成密钥对的封装密钥。

  7. 将 publicKey 的 [[type]] 内部槽设置为 "public"。

  8. 将 publicKey 的 [[algorithm]] 内部 槽设置为 algorithm。

  9. 将 publicKey 的 [[extractable]] 内部 槽设置为 true。

  10. 将 publicKey 的 [[usages]] 内部槽设置为 usages 与 [ "encapsulateKey", "encapsulateBits" ] 的 用法 交集。

  11. 令 privateKey 为一个新的 CryptoKey, 表示所生成密钥对的解封装密钥。

  12. 将 privateKey 的 [[type]] 内部槽设置为 "private"。

  13. 将 privateKey 的 [[algorithm]] 内部 槽设置为 algorithm。

  14. 将 privateKey 的 [[extractable]] 内部 槽设置为 extractable。

  15. 将 privateKey 的 [[usages]] 内部槽设置为 usages 与 [ "decapsulateKey", "decapsulateBits" ] 的 用法 交集。

  16. 令 result 为一个新的 CryptoKeyPair 字典。

  17. 将 result 的 publicKey 属性 设置为 publicKey。

  18. 将 result 的 privateKey 属性 设置为 privateKey。

  19. 返回 result。

7.4.5 导入密钥

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

  2. 如果 format 是 "raw-public":
    1. 如果 usages 包含一个不是 "encapsulateKey" 或 "encapsulateBits" 的条目, 则抛出一个 SyntaxError。

    2. 令 data 为 keyData。

    3. 如果 data 的字节长度不是由 normalizedAlgorithm 的 name 成员所指示的混合 KEM 实例在 [draft-irtf-cfrg-concrete-hybrid-kems-04] 第 4 节中的原始公钥长度 Nek,则 抛出一个 DataError。

    4. 令 key 为一个新的 CryptoKey, 表示 data 中的混合 KEM 公钥数据。

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

    6. 令 algorithm 为一个新的 KeyAlgorithm。

    7. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

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

    如果 format 是 "raw-seed":
    1. 如果 usages 包含一个不是 "decapsulateKey" 或 "decapsulateBits" 的条目, 则抛出一个 SyntaxError。

    2. 令 data 为 keyData。

    3. 如果 data 的位长度不是 256, 则抛出一个 DataError。

    4. 令 keyPair 为对 normalizedAlgorithm 的 name 成员所指示的混合 KEM 实例执行 [draft-irtf-cfrg-hybrid-kems-12] 第 5.5 节中描述的 DeriveKeyPair 函数所得的结果, 使用 data 作为 seed 输入参数。

    5. 如果 DeriveKeyPair 函数返回错误, 则抛出一个 OperationError。

    6. 令 key 为一个新的 CryptoKey, 表示由 keyPair 的解封装密钥所标识的 混合 KEM 私钥。

    7. 将 key 的 [[type]] 内部槽 设置为 "private"

    8. 令 algorithm 为一个新的 KeyAlgorithm。

    9. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

    10. 将 key 的 [[algorithm]] 内部槽设置为 algorithm。

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

      令 jwk 等于 keyData。

      否则:

      抛出一个 DataError。

    2. 如果 jwk 的 priv 字段存在, 并且 usages 包含一个不是 "decapsulateKey" 或 "decapsulateBits" 的条目, 则抛出一个 SyntaxError。

    3. 如果 jwk 的 priv 字段不存在, 并且 usages 包含一个不是 "encapsulateKey" 或 "encapsulateBits" 的条目, 则抛出一个 SyntaxError。

    4. 如果 jwk 的 kty 字段不是 "AKP", 则抛出一个 DataError。

    5. 如果 jwk 的 alg 字段不存在, 或其值未标识 normalizedAlgorithm 的 name 成员所指示的混合 KEM 实例, 则抛出一个 DataError。

      注

      在 IANA JSON Web 签名和加密算法注册表中 为本规范定义的混合 KEM 实例注册的 "alg" 值 为 MLKEM768-P256、MLKEM768-X25519 和 MLKEM1024-P384。实现还应接受此注册表中标识 使用相同混合 KEM 实例的 JWE 算法的其他 值,前提是该 JWE 算法的 JWK 表示形式除 "alg" 值外与此处定义的 表示形式兼容。 示例包括 [draft-ietf-jose-hpke-pq-pqt] 中提出的值,一旦完成注册。

    6. 如果 usages 非空且 jwk 的 use 字段存在 且不等于 "enc",则抛出一个 DataError。

    7. 如果 jwk 的 key_ops 字段存在,并且 根据 JSON Web 密钥 [JWK] 的要求无效,或者其中未包含 所有指定的 usages 值, 则抛出一个 DataError。

    8. 如果 jwk 的 ext 字段存在且 值为 false,而 extractable 为 true, 则抛出一个 DataError。

    9. 如果 jwk 的 priv 字段存在:
      1. 如果 jwk 的 priv 属性不包含一个有效的 base64url 编码的 32 字节种子以表示混合 KEM 私钥, 则抛出 一个 DataError。

      2. 令 key 为一个新的 CryptoKey 对象,其表示通过将 jwk 的 priv 属性解释为 base64url 编码的种子 所标识的混合 KEM 私钥。

      3. 将 key 的 [[type]] 内部槽设置为 "private"。

      4. 如果 jwk 的 pub 属性不包含与 key 对应的 表示混合 KEM 公钥的 base64url 编码公钥, 则抛出 一个 DataError。

      否则:
      1. 如果 jwk 的 pub 属性不包含一个有效的 base64url 编码的原始 公钥,且其长度不是由 normalizedAlgorithm 的 name 成员所指示的混合 KEM 实例在 [draft-irtf-cfrg-concrete-hybrid-kems-04] 第 4 节中的 Nek, 则抛出 一个 DataError。

      2. 令 key 为一个新的 CryptoKey 对象,其表示通过将 jwk 的 pub 属性解释为 base64url 编码的公钥 所标识的混合 KEM 公钥。

      3. 将 key 的 [[type]] 内部槽设置为 "public"。

    10. 令 algorithm 为一个新的 KeyAlgorithm 对象实例。

    11. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 成员。

    12. 将 key 的 [[algorithm]] 内部槽设置为 algorithm。

    否则:
    抛出一个 NotSupportedError。
  3. 返回 key。

7.4.6 导出密钥

  1. 令 key 为要导出的 CryptoKey。

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

  3. 如果 format 是 "raw-public":
    1. 如果 key 的 [[type]] 内部槽 不是 "public", 则抛出一个 InvalidAccessError。

    2. 令 data 为一个字节序列, 其中包含由 key 的 [[handle]] 内部槽所表示的密钥的原始八位字节。

    3. 令 result 为 data。

    如果 format 是 "raw-seed":
    1. 如果 key 的 [[type]] 内部槽 不是 "private", 则抛出一个 InvalidAccessError。

    2. 令 data 为一个字节序列, 其中包含由 key 的 [[handle]] 内部槽所表示的 32 字节种子。

    3. 令 result 为 data。

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

    2. 令 keyAlgorithm 为 key 的 [[algorithm]] 内部槽。

    3. 将 jwk 的 kty 属性设置为 "AKP"。

    4. 将 jwk 的 alg 属性设置为 keyAlgorithm 的 name 成员。

    5. 将 jwk 的 pub 属性 设置为与 key 的 [[handle]] 内部槽相对应的 base64url 编码公钥。

    6. 如果 key 的 [[type]] 内部槽 是 "private":
      将 jwk 的 priv 属性 设置为由 key 的 [[handle]] 内部槽所表示的 32 字节种子的 base64url 编码形式。
    7. 将 jwk 的 key_ops 属性设置为 key 的 usages 属性。

    8. 将 jwk 的 ext 属性设置为 key 的 [[extractable]] 内部槽。

    9. 令 result 为 jwk。

    否则:

    抛出一个 NotSupportedError。

  4. 返回 result。

8. ML-DSA

8.1 描述

本节为非规范性内容。

本节描述如何使用 ML-DSA 进行签名和验证, 如 [FIPS-204] 中所规定。

8.2 注册

此算法的已识别算法 名称为 "ML-DSA-44"、"ML-DSA-65" 和 "ML-DSA-87"。

操作 参数 结果
签名 ContextParams 字节 序列
验证 ContextParams 布尔值
生成密钥 无 CryptoKeyPair
导入密钥 无 CryptoKey
导出密钥 无 对象

8.3 ContextParams 字典

WebIDLdictionary ContextParams : Algorithm {
  BufferSource context;
};

context 成员表示要与消息 关联的可选上下文数据。

注

ContextParams 字典与 [webcrypto-secure-curves] 的 Ed448Params 字典完全相同, 在合并本提案时,后者可以由前者替代。

8.4 操作

8.4.1 签名

  1. 如果 normalizedAlgorithm 的 context 成员 存在且其长度大于 255 字节,则抛出一个 OperationError。

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

  3. 令 context 为 normalizedAlgorithm 的 context 成员;如果 normalizedAlgorithm 的 context 成员不存在,则为 空八位字节字符串。

  4. 令 result 为执行 ML-DSA.Sign 签名算法所得的结果,该算法如 [FIPS-204] 第 5.2 节中所规定, 使用 normalizedAlgorithm 的 name 成员所指示的参数集, 使用与 key 关联的 ML-DSA 私钥作为 sk, message 作为 M,并使用 context 作为 ctx。

  5. 如果 ML-DSA.Sign 算法返回错误,则返回一个 OperationError。

  6. 返回 result。

8.4.2 验证

  1. 如果 normalizedAlgorithm 的 context 成员 存在且其长度大于 255 字节,则抛出一个 OperationError。

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

  3. 令 context 为 normalizedAlgorithm 的 context 成员;如果 normalizedAlgorithm 的 context 成员不存在,则为 空八位字节字符串。

  4. 令 result 为执行 ML-DSA.Verify 验证算法所得的结果,该算法如 [FIPS-204] 第 5.3 节中所规定, 使用 normalizedAlgorithm 的 name 成员所指示的参数集, 使用与 key 关联的 ML-DSA 公钥作为 pk, message 作为 M,signature 作为 σ,并使用 context 作为 ctx。

  5. 如果 ML-DSA.Verify 算法返回错误,则返回一个 OperationError。

  6. 返回 result。

8.4.3 生成密钥

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

  2. 按照 [FIPS-204] 第 5.1 节中的描述, 使用 normalizedAlgorithm 的 name 成员所指示的参数集 生成一个 ML-DSA 密钥对。

    注

    为了能够导出种子 ξ, 需要将其作为生成的 密钥材料的一部分进行存储。

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

  4. 令 algorithm 为一个新的 KeyAlgorithm 对象。

  5. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

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

  7. 将 publicKey 的 [[type]] 内部槽设置为 "public"。

  8. 将 publicKey 的 [[algorithm]] 内部 槽设置为 algorithm。

  9. 将 publicKey 的 [[extractable]] 内部 槽设置为 true。

  10. 将 publicKey 的 [[usages]] 内部槽设置为 usages 与 [ "verify" ] 的用法 交集。

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

  12. 将 privateKey 的 [[type]] 内部槽设置为 "private"。

  13. 将 privateKey 的 [[algorithm]] 内部 槽设置为 algorithm。

  14. 将 privateKey 的 [[extractable]] 内部 槽设置为 extractable。

  15. 将 privateKey 的 [[usages]] 内部槽设置为 usages 与 [ "sign" ] 的用法 交集。

  16. 令 result 为一个新的 CryptoKeyPair 字典。

  17. 将 result 的 publicKey 属性 设置为 publicKey。

  18. 将 result 的 privateKey 属性 设置为 privateKey。

  19. 返回 result。

8.4.4 导入密钥

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

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

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

    3. 如果解析时发生错误, 则抛出一个 DataError。

    4. 如果 normalizedAlgorithm 的 name 成员是 "ML-DSA-44":

      令 expectedOid 为 id-ml-dsa-44 (2.16.840.1.101.3.4.3.17)。

      如果 normalizedAlgorithm 的 name 成员是 "ML-DSA-65":

      令 expectedOid 为 id-ml-dsa-65 (2.16.840.1.101.3.4.3.18)。

      如果 normalizedAlgorithm 的 name 成员是 "ML-DSA-87":

      令 expectedOid 为 id-ml-dsa-87 (2.16.840.1.101.3.4.3.19)。

      否则:

      抛出一个 NotSupportedError。

    5. 如果 spki 的 algorithm AlgorithmIdentifier 字段的 algorithm 对象标识符字段 不等于 expectedOid, 则抛出一个 DataError。

    6. 如果 spki 的 algorithm AlgorithmIdentifier 字段的 parameters 字段存在, 则抛出一个 DataError。

    7. 令 publicKey 为由 spki 的 subjectPublicKey 字段所标识的 ML-DSA 公钥。

    8. 令 key 为一个新的 CryptoKey, 其表示 publicKey。

    9. 将 key 的 [[type]] 内部槽 设置为 "public"

    10. 令 algorithm 为一个新的 KeyAlgorithm。

    11. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

    12. 将 key 的 [[algorithm]] 内部槽设置为 algorithm。

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

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

    3. 如果解析时发生错误, 则抛出一个 DataError。

    4. 如果 normalizedAlgorithm 的 name 成员是 "ML-DSA-44":

      令 expectedOid 为 id-ml-dsa-44 (2.16.840.1.101.3.4.3.17)。

      令 asn1Structure 为 ASN.1 ML-DSA-44-PrivateKey 结构。

      如果 normalizedAlgorithm 的 name 成员是 "ML-DSA-65":

      令 expectedOid 为 id-ml-dsa-65 (2.16.840.1.101.3.4.3.18)。

      令 asn1Structure 为 ASN.1 ML-DSA-65-PrivateKey 结构。

      如果 normalizedAlgorithm 的 name 成员是 "ML-DSA-87":

      令 expectedOid 为 id-ml-dsa-87 (2.16.840.1.101.3.4.3.19)。

      令 asn1Structure 为 ASN.1 ML-DSA-87-PrivateKey 结构。

      否则:

      抛出一个 NotSupportedError。

    5. 如果 privateKeyInfo 的 privateKeyAlgorithm PrivateKeyAlgorithm 字段的 algorithm 对象标识符字段不等于 expectedOid, 则抛出一个 DataError。

    6. 如果 privateKeyInfo 的 privateKeyAlgorithm PrivateKeyAlgorithmIdentifier 字段的 parameters 字段存在, 则抛出一个 DataError。

    7. 令 mlDsaPrivateKey 为执行 解析 ASN.1 结构 算法所得的结果,其中 data 为 privateKeyInfo 的 privateKey 字段, structure 为 asn1Structure,且 exactData 设置为 true。

    8. 如果解析时发生错误, 则抛出一个 DataError。

    9. 如果 mlDsaPrivateKey 表示采用 expandedKey 格式的 ML-DSA 密钥, 或者如果 mlDsaPrivateKey 表示采用 both 格式的 ML-DSA 密钥 且不支持 both 格式,则抛出一个 NotSupportedError。

    10. 如果 mlDsaPrivateKey 表示采用 both 格式的 ML-DSA 密钥, 且 seed 字段与 expandedKey 字段不对应, 则抛出一个 DataError。

    11. 令 key 为一个新的 CryptoKey, 其表示由 mlDsaPrivateKey 所标识的 ML-DSA 私钥。

    12. 将 key 的 [[type]] 内部槽 设置为 "private"

    13. 令 algorithm 为一个新的 KeyAlgorithm。

    14. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

    15. 将 key 的 [[algorithm]] 内部槽设置为 algorithm。

    如果 format 是 "raw-public":
    1. 如果 usages 包含一个不是 "verify" 的条目, 则抛出一个 SyntaxError。

    2. 令 algorithm 为一个新的 KeyAlgorithm 对象。

    3. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

    4. 令 key 为一个新的 CryptoKey, 表示 keyData 中提供的密钥数据。

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

    6. 将 key 的 [[algorithm]] 内部槽设置为 algorithm。

    如果 format 是 "raw-seed":
    1. 如果 usages 包含一个不是 "sign" 的条目, 则抛出一个 SyntaxError。

    2. 令 data 为 keyData。

    3. 如果 data 的位长度不是 256, 则抛出一个 DataError。

    4. 令 privateKey 为执行 [FIPS-204] 第 6.1 节中描述的 ML-DSA.KeyGen_internal 函数所得的结果, 使用 normalizedAlgorithm 的 name 成员所指示的参数集, 并使用 data 作为 ξ。

    5. 令 key 为一个新的 CryptoKey, 其表示由 privateKey 所标识的 ML-DSA 私钥。

    6. 将 key 的 [[type]] 内部槽 设置为 "private"

    7. 令 algorithm 为一个新的 KeyAlgorithm。

    8. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

    9. 将 key 的 [[algorithm]] 内部槽设置为 algorithm。

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

      令 jwk 等于 keyData。

      否则:

      抛出一个 DataError。

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

    3. 如果 jwk 的 kty 字段不是 "AKP", 则抛出一个 DataError。

    4. 如果 jwk 的 alg 字段不等于 normalizedAlgorithm 的 name 成员, 则抛出一个 DataError。

    5. 如果 usages 非空且 jwk 的 use 字段存在 且不等于 "sig",则抛出一个 DataError。

    6. 如果 jwk 的 key_ops 字段存在,并且 根据 JSON Web 密钥 [JWK] 的要求无效,或者其中未包含 所有指定的 usages 值, 则抛出一个 DataError。

    7. 如果 jwk 的 ext 字段存在且 值为 false,而 extractable 为 true, 则抛出一个 DataError。

    8. 如果 jwk 的 priv 字段存在:
      1. 如果 jwk 的 priv 属性不包含一个有效的 base64url 编码种子, 以表示 ML-DSA 私钥, 则抛出 一个 DataError。

      2. 令 key 为一个新的 CryptoKey 对象,其表示通过将 jwk 的 priv 属性解释为 base64url 编码的种子 所标识的 ML-DSA 私钥。

      3. 将 key 的 [[type]] 内部槽设置为 "private"。

      4. 如果 jwk 的 pub 属性不包含与 key 对应的 表示 ML-DSA 公钥的 base64url 编码公钥, 则抛出 一个 DataError。

      否则:
      1. 如果 jwk 的 pub 属性不包含一个有效的 base64url 编码公钥, 以表示 ML-DSA 公钥, 则抛出 一个 DataError。

      2. 令 key 为一个新的 CryptoKey 对象,其表示通过将 jwk 的 pub 属性解释为 base64url 编码的公钥 所标识的 ML-DSA 公钥。

      3. 将 key 的 [[type]] 内部槽设置为 "public"。

    9. 令 algorithm 为一个新的 KeyAlgorithm 对象实例。

    10. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 成员。

    11. 将 key 的 [[algorithm]] 内部槽设置为 algorithm。

    否则:

    抛出一个 NotSupportedError。

  3. 返回 key。

8.4.5 导出密钥

  1. 令 key 为要导出的 CryptoKey。

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

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

    2. 令 keyAlgorithm 为 key 的 [[algorithm]] 内部槽。

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

      • 将 algorithm 字段设置为一个 AlgorithmIdentifier ASN.1 类型,并具有以下 属性:

        • 如果 keyAlgorithm 的 name 成员是 "ML-DSA-44":

          将 algorithm 对象标识符设置为 id-ml-dsa-44 (2.16.840.1.101.3.4.3.17) OID。

          如果 keyAlgorithm 的 name 成员是 "ML-DSA-65":

          将 algorithm 对象标识符设置为 id-ml-dsa-65 (2.16.840.1.101.3.4.3.18) OID。

          如果 keyAlgorithm 的 name 成员是 "ML-DSA-87":

          将 algorithm 对象标识符设置为 id-ml-dsa-87 (2.16.840.1.101.3.4.3.19) OID。

          否则:

          抛出 一个 NotSupportedError。

      • 将 subjectPublicKey 字段设置为 keyData。

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

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

    2. 令 keyAlgorithm 为 key 的 [[algorithm]] 内部槽。

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

      • 将 version 字段设置为 0。

      • 将 privateKeyAlgorithm 字段设置为一个 PrivateKeyAlgorithmIdentifier ASN.1 类型,并具有以下 属性:

        • 如果 keyAlgorithm 的 name 成员是 "ML-DSA-44":

          将 algorithm 对象标识符设置为 id-ml-dsa-44 (2.16.840.1.101.3.4.3.17) OID。

          如果 keyAlgorithm 的 name 成员是 "ML-DSA-65":

          将 algorithm 对象标识符设置为 id-ml-dsa-65 (2.16.840.1.101.3.4.3.18) OID。

          如果 keyAlgorithm 的 name 成员是 "ML-DSA-87":

          将 algorithm 对象标识符设置为 id-ml-dsa-87 (2.16.840.1.101.3.4.3.19) OID。

          否则:

          抛出 一个 NotSupportedError。

      • 按如下方式设置 privateKey 字段:

        • 如果 keyAlgorithm 的 name 成员是 "ML-DSA-44":

          将 privateKey 字段设置为 对一个 ML-DSA-44-PrivateKey ASN.1 类型进行 DER 编码所得的结果,该类型表示由 key 的 [[handle]] 内部槽所表示的 ML-DSA 私钥种子,并使用仅种子 格式(使用上下文特定的 [0] 原始标签, 隐式编码 OCTET STRING)。

          如果 keyAlgorithm 的 name 成员是 "ML-DSA-65":

          将 privateKey 字段设置为 对一个 ML-DSA-65-PrivateKey ASN.1 类型进行 DER 编码所得的结果,该类型表示由 key 的 [[handle]] 内部槽所表示的 ML-DSA 私钥种子,并使用仅种子 格式(使用上下文特定的 [0] 原始标签, 隐式编码 OCTET STRING)。

          如果 keyAlgorithm 的 name 成员是 "ML-DSA-87":

          将 privateKey 字段设置为 对一个 ML-DSA-87-PrivateKey ASN.1 类型进行 DER 编码所得的结果,该类型表示由 key 的 [[handle]] 内部槽所表示的 ML-DSA 私钥种子,并使用仅种子 格式(使用上下文特定的 [0] 原始标签, 隐式编码 OCTET STRING)。

          否则:

          抛出 一个 NotSupportedError。

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

    如果 format 是 "raw-public":
    1. 如果 key 的 [[type]] 内部槽 不是 "public", 则抛出一个 InvalidAccessError。

    2. 令 data 为一个字节序列, 其中包含由 key 的 [[handle]] 内部槽所表示的 ML-DSA 公钥。

    3. 令 result 为 data。

    如果 format 是 "raw-seed":
    1. 如果 key 的 [[type]] 内部槽 不是 "private", 则抛出一个 InvalidAccessError。

    2. 令 data 为一个字节序列, 其中包含由 key 的 [[handle]] 内部槽所表示的密钥的 ξ 种子变量。

      注

      ξ 种子变量是在 ML-DSA.KeyGen 函数中采样的, 如 [FIPS-204] 第 5.1 节中所述。

    3. 令 result 为 data。

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

    2. 令 keyAlgorithm 为 key 的 [[algorithm]] 内部槽。

    3. 将 jwk 的 kty 属性设置为 "AKP"。

    4. 将 jwk 的 alg 属性设置为 keyAlgorithm 的 name 成员。

    5. 将 jwk 的 pub 属性 设置为与 key 的 [[handle]] 内部槽相对应的 base64url 编码公钥。

    6. 如果 key 的 [[type]] 内部槽 是 "private":
      将 jwk 的 priv 属性 设置为由 key 的 [[handle]] 内部槽所表示的种子的 base64url 编码形式。
    7. 将 jwk 的 key_ops 属性设置为 key 的 usages 属性。

    8. 将 jwk 的 ext 属性设置为 key 的 [[extractable]] 内部槽。

    9. 令 result 为 jwk。

    否则:

    抛出一个 NotSupportedError。

  4. 返回 result。

9. SLH-DSA

9.1 描述

本节为非规范性内容。

本节描述如何使用 SLH-DSA 进行签名和验证, 如 [FIPS-205] 中所规定。

9.2 注册

此算法的已识别算法 名称为 "SLH-DSA-SHA2-128s"、"SLH-DSA-SHAKE-128s"、 "SLH-DSA-SHA2-128f"、"SLH-DSA-SHAKE-128f"、 "SLH-DSA-SHA2-192s"、"SLH-DSA-SHAKE-192s"、 "SLH-DSA-SHA2-192f"、"SLH-DSA-SHAKE-192f"、 "SLH-DSA-SHA2-256s"、"SLH-DSA-SHAKE-256s"、 "SLH-DSA-SHA2-256f" 和 "SLH-DSA-SHAKE-256f"。

操作 参数 结果
签名 ContextParams 字节 序列
验证 ContextParams 布尔值
生成密钥 无 CryptoKeyPair
导入密钥 无 CryptoKey
导出密钥 无 对象

9.3 JSON Web 密钥表示

SLH-DSA 密钥使用 [RFC9964] 中定义的 "AKP"(算法密钥对)密钥类型进行 JWK 表示。"alg"(算法)参数标识特定的 SLH-DSA 参数集。 公钥存放在 "pub" 参数中。如果包含私钥,则使用 "priv" 参数表示。以 JWK 表示时,所有密钥参数均使用 base64url 编码。

9.4 操作

9.4.1 签名

  1. 如果 normalizedAlgorithm 的 context 成员 存在且其长度大于 255 字节,则抛出一个 OperationError。

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

  3. 令 context 为 normalizedAlgorithm 的 context 成员;如果 normalizedAlgorithm 的 context 成员不存在,则为 空八位字节字符串。

  4. 令 result 为执行 slh_sign 签名算法所得的结果,该算法如 [FIPS-205] 第 10.2.1 节中所规定, 使用 normalizedAlgorithm 的 name 成员所指示的参数集, 使用与 key 关联的 SLH-DSA 私钥作为 SK, message 作为 M,并使用 context 作为 ctx。

  5. 如果 slh_sign 算法返回错误,则返回一个 OperationError。

  6. 返回 result。

9.4.2 验证

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

  2. 令 context 为 normalizedAlgorithm 的 context 成员;如果 normalizedAlgorithm 的 context 成员不存在,则为 空八位字节字符串。

  3. 令 result 为执行 slh_verify 验证算法所得的结果,该算法如 [FIPS-205] 第 10.3 节中所规定, 使用 normalizedAlgorithm 的 name 成员所指示的参数集, 使用与 key 关联的 SLH-DSA 公钥作为 PK, message 作为 M,signature 作为 SIG,并使用 context 作为 ctx。

  4. 如果 slh_verify 算法返回错误,则返回一个 OperationError。

  5. 返回 result。

9.4.3 生成密钥

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

  2. 按照 [FIPS-205] 第 10.1 节中的描述, 使用 normalizedAlgorithm 的 name 成员所指示的参数集 生成一个 SLH-DSA 密钥对。

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

  4. 令 algorithm 为一个新的 KeyAlgorithm 对象。

  5. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

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

  7. 将 publicKey 的 [[type]] 内部槽设置为 "public"。

  8. 将 publicKey 的 [[algorithm]] 内部 槽设置为 algorithm。

  9. 将 publicKey 的 [[extractable]] 内部 槽设置为 true。

  10. 将 publicKey 的 [[usages]] 内部槽设置为 usages 与 [ "verify" ] 的用法 交集。

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

  12. 将 privateKey 的 [[type]] 内部槽设置为 "private"。

  13. 将 privateKey 的 [[algorithm]] 内部 槽设置为 algorithm。

  14. 将 privateKey 的 [[extractable]] 内部 槽设置为 extractable。

  15. 将 privateKey 的 [[usages]] 内部槽设置为 usages 与 [ "sign" ] 的用法 交集。

  16. 令 result 为一个新的 CryptoKeyPair 字典。

  17. 将 result 的 publicKey 属性 设置为 publicKey。

  18. 将 result 的 privateKey 属性 设置为 privateKey。

  19. 返回 result。

9.4.4 导入密钥

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

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

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

    3. 如果解析时发生错误, 则抛出一个 DataError。

    4. 如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHA2-128s":

      令 expectedOid 为 id-slh-dsa-sha2-128s (2.16.840.1.101.3.4.3.20)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHA2-128f":

      令 expectedOid 为 id-slh-dsa-sha2-128f (2.16.840.1.101.3.4.3.21)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHA2-192s":

      令 expectedOid 为 id-slh-dsa-sha2-192s (2.16.840.1.101.3.4.3.22)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHA2-192f":

      令 expectedOid 为 id-slh-dsa-sha2-192f (2.16.840.1.101.3.4.3.23)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHA2-256s":

      令 expectedOid 为 id-slh-dsa-sha2-256s (2.16.840.1.101.3.4.3.24)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHA2-256f":

      令 expectedOid 为 id-slh-dsa-sha2-256f (2.16.840.1.101.3.4.3.25)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-128s":

      令 expectedOid 为 id-slh-dsa-shake-128s (2.16.840.1.101.3.4.3.26)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-128f":

      令 expectedOid 为 id-slh-dsa-shake-128f (2.16.840.1.101.3.4.3.27)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-192s":

      令 expectedOid 为 id-slh-dsa-shake-192s (2.16.840.1.101.3.4.3.28)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-192f":

      令 expectedOid 为 id-slh-dsa-shake-192f (2.16.840.1.101.3.4.3.29)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-256s":

      令 expectedOid 为 id-slh-dsa-shake-256s (2.16.840.1.101.3.4.3.30)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-256f":

      令 expectedOid 为 id-slh-dsa-shake-256f (2.16.840.1.101.3.4.3.31)。

      否则:

      抛出一个 NotSupportedError。

    5. 如果 spki 的 algorithm AlgorithmIdentifier 字段的 algorithm 对象标识符字段 不等于 expectedOid, 则抛出一个 DataError。

    6. 如果 spki 的 algorithm AlgorithmIdentifier 字段的 parameters 字段存在, 则抛出一个 DataError。

    7. 令 publicKey 为由 spki 的 subjectPublicKey 字段所标识的 SLH-DSA 公钥。

    8. 令 key 为一个新的 CryptoKey, 其表示 publicKey。

    9. 将 key 的 [[type]] 内部槽 设置为 "public"

    10. 令 algorithm 为一个新的 KeyAlgorithm。

    11. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

    12. 将 key 的 [[algorithm]] 内部槽设置为 algorithm。

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

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

    3. 如果解析时发生错误, 则抛出一个 DataError。

    4. 如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHA2-128s":

      令 expectedOid 为 id-slh-dsa-sha2-128s (2.16.840.1.101.3.4.3.20)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHA2-128f":

      令 expectedOid 为 id-slh-dsa-sha2-128f (2.16.840.1.101.3.4.3.21)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHA2-192s":

      令 expectedOid 为 id-slh-dsa-sha2-192s (2.16.840.1.101.3.4.3.22)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHA2-192f":

      令 expectedOid 为 id-slh-dsa-sha2-192f (2.16.840.1.101.3.4.3.23)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHA2-256s":

      令 expectedOid 为 id-slh-dsa-sha2-256s (2.16.840.1.101.3.4.3.24)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHA2-256f":

      令 expectedOid 为 id-slh-dsa-sha2-256f (2.16.840.1.101.3.4.3.25)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-128s":

      令 expectedOid 为 id-slh-dsa-shake-128s (2.16.840.1.101.3.4.3.26)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-128f":

      令 expectedOid 为 id-slh-dsa-shake-128f (2.16.840.1.101.3.4.3.27)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-192s":

      令 expectedOid 为 id-slh-dsa-shake-192s (2.16.840.1.101.3.4.3.28)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-192f":

      令 expectedOid 为 id-slh-dsa-shake-192f (2.16.840.1.101.3.4.3.29)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-256s":

      令 expectedOid 为 id-slh-dsa-shake-256s (2.16.840.1.101.3.4.3.30)。

      如果 normalizedAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-256f":

      令 expectedOid 为 id-slh-dsa-shake-256f (2.16.840.1.101.3.4.3.31)。

      否则:

      抛出一个 NotSupportedError。

    5. 如果 privateKeyInfo 的 privateKeyAlgorithm PrivateKeyAlgorithm 字段的 algorithm 对象标识符字段不等于 expectedOid, 则抛出一个 DataError。

    6. 如果 privateKeyInfo 的 privateKeyAlgorithm PrivateKeyAlgorithmIdentifier 字段的 parameters 字段存在, 则抛出一个 DataError。

    7. 令 slhDsaPrivateKey 为执行 解析 ASN.1 结构 算法所得的结果,其中 data 为 privateKeyInfo 的 privateKey 字段, structure 为 OCTET STRING,并且 exactData 设置为 true。

    8. 如果解析时发生错误, 则抛出一个 DataError。

    9. 令 key 为一个新的 CryptoKey, 其表示由 slhDsaPrivateKey 所标识的 SLH-DSA 私钥。

    10. 将 key 的 [[type]] 内部槽 设置为 "private"

    11. 令 algorithm 为一个新的 KeyAlgorithm。

    12. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

    13. 将 key 的 [[algorithm]] 内部槽设置为 algorithm。

    如果 format 是 "raw-public":
    1. 如果 usages 包含一个不是 "verify" 的条目, 则抛出一个 SyntaxError。

    2. 令 algorithm 为一个新的 KeyAlgorithm 对象。

    3. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

    4. 如果 keyData 的长度不是 [FIPS-205] 表 2 为 normalizedAlgorithm 的 name 成员所指示的参数集规定的 pk length, 则抛出一个 DataError。

    5. 令 key 为一个新的 CryptoKey, 表示 keyData 中提供的密钥数据。

    6. 将 key 的 [[type]] 内部槽 设置为 "public"

    7. 将 key 的 [[algorithm]] 内部槽设置为 algorithm。

    如果 format 是 "raw-private":
    1. 如果 usages 包含一个不是 "sign" 的条目, 则抛出一个 SyntaxError。

    2. 如果 keyData 的长度不是 [FIPS-205] 表 2 为 normalizedAlgorithm 的 name 成员所指示的参数集规定的 pk length 的 2 倍, 则抛出一个 DataError。

    3. 令 key 为一个新的 CryptoKey, 表示 keyData 中提供的密钥数据。

    4. 将 key 的 [[type]] 内部槽 设置为 "private"。

    5. 令 algorithm 为一个新的 KeyAlgorithm。

    6. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 属性。

    7. 将 key 的 [[algorithm]] 内部槽设置为 algorithm。

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

      令 jwk 等于 keyData。

      否则:

      抛出一个 DataError。

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

    3. 如果 jwk 的 kty 字段不是 "AKP", 则抛出一个 DataError。

    4. 如果 jwk 的 alg 字段不等于 normalizedAlgorithm 的 name 成员, 则抛出一个 DataError。

    5. 如果 usages 非空且 jwk 的 use 字段存在 且不等于 "sig",则抛出一个 DataError。

    6. 如果 jwk 的 key_ops 字段存在,并且 根据 JSON Web 密钥 [JWK] 的要求无效,或者其中未包含 所有指定的 usages 值, 则抛出一个 DataError。

    7. 如果 jwk 的 ext 字段存在且 值为 false,而 extractable 为 true, 则抛出一个 DataError。

    8. 如果 jwk 的 priv 字段存在:
      1. 如果 jwk 的 priv 属性不包含一个有效的 base64url 编码值 以表示 SLH-DSA 私钥, 则抛出 一个 DataError。

      2. 令 key 为一个新的 CryptoKey 对象,其表示通过将 jwk 的 priv 属性解释为 base64url 编码的私钥 所标识的 SLH-DSA 私钥。

      3. 将 key 的 [[type]] 内部槽设置为 "private"。

      4. 如果 jwk 的 pub 属性不包含与 key 对应的 表示 SLH-DSA 公钥的 base64url 编码公钥, 则抛出 一个 DataError。

      否则:
      1. 如果 jwk 的 pub 属性不包含一个有效的 base64url 编码公钥 以表示 SLH-DSA 公钥, 则抛出 一个 DataError。

      2. 令 key 为一个新的 CryptoKey 对象,其表示通过将 jwk 的 pub 属性解释为 base64url 编码的公钥 所标识的 SLH-DSA 公钥。

      3. 将 key 的 [[type]] 内部槽设置为 "public"。

    9. 令 algorithm 为一个新的 KeyAlgorithm 对象实例。

    10. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 成员。

    11. 将 key 的 [[algorithm]] 内部槽设置为 algorithm。

    否则:

    抛出一个 NotSupportedError。

  3. 返回 key。

9.4.5 导出密钥

  1. 令 key 为要导出的 CryptoKey。

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

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

    2. 令 keyAlgorithm 为 key 的 [[algorithm]] 内部槽。

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

      • 将 algorithm 字段设置为一个 AlgorithmIdentifier ASN.1 类型,并具有以下 属性:

        • 如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHA2-128s":

          将 algorithm 对象标识符设置为 id-slh-dsa-sha2-128s (2.16.840.1.101.3.4.3.20) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHA2-128f":

          将 algorithm 对象标识符设置为 id-slh-dsa-sha2-128f (2.16.840.1.101.3.4.3.21) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHA2-192s":

          将 algorithm 对象标识符设置为 id-slh-dsa-sha2-192s (2.16.840.1.101.3.4.3.22) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHA2-192f":

          将 algorithm 对象标识符设置为 id-slh-dsa-sha2-192f (2.16.840.1.101.3.4.3.23) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHA2-256s":

          将 algorithm 对象标识符设置为 id-slh-dsa-sha2-256s (2.16.840.1.101.3.4.3.24) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHA2-256f":

          将 algorithm 对象标识符设置为 id-slh-dsa-sha2-256f (2.16.840.1.101.3.4.3.25) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-128s":

          将 algorithm 对象标识符设置为 id-slh-dsa-shake-128s (2.16.840.1.101.3.4.3.26) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-128f":

          将 algorithm 对象标识符设置为 id-slh-dsa-shake-128f (2.16.840.1.101.3.4.3.27) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-192s":

          将 algorithm 对象标识符设置为 id-slh-dsa-shake-192s (2.16.840.1.101.3.4.3.28) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-192f":

          将 algorithm 对象标识符设置为 id-slh-dsa-shake-192f (2.16.840.1.101.3.4.3.29) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-256s":

          将 algorithm 对象标识符设置为 id-slh-dsa-shake-256s (2.16.840.1.101.3.4.3.30) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-256f":

          将 algorithm 对象标识符设置为 id-slh-dsa-shake-256f (2.16.840.1.101.3.4.3.31) OID。

          否则:

          抛出 一个 NotSupportedError。

      • 将 subjectPublicKey 字段设置为 keyData。

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

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

    2. 令 keyAlgorithm 为 key 的 [[algorithm]] 内部槽。

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

      • 将 version 字段设置为 0。

      • 将 privateKeyAlgorithm 字段设置为一个 PrivateKeyAlgorithmIdentifier ASN.1 类型,并具有以下 属性:

        • 如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHA2-128s":

          将 algorithm 对象标识符设置为 id-slh-dsa-sha2-128s (2.16.840.1.101.3.4.3.20) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHA2-128f":

          将 algorithm 对象标识符设置为 id-slh-dsa-sha2-128f (2.16.840.1.101.3.4.3.21) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHA2-192s":

          将 algorithm 对象标识符设置为 id-slh-dsa-sha2-192s (2.16.840.1.101.3.4.3.22) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHA2-192f":

          将 algorithm 对象标识符设置为 id-slh-dsa-sha2-192f (2.16.840.1.101.3.4.3.23) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHA2-256s":

          将 algorithm 对象标识符设置为 id-slh-dsa-sha2-256s (2.16.840.1.101.3.4.3.24) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHA2-256f":

          将 algorithm 对象标识符设置为 id-slh-dsa-sha2-256f (2.16.840.1.101.3.4.3.25) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-128s":

          将 algorithm 对象标识符设置为 id-slh-dsa-shake-128s (2.16.840.1.101.3.4.3.26) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-128f":

          将 algorithm 对象标识符设置为 id-slh-dsa-shake-128f (2.16.840.1.101.3.4.3.27) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-192s":

          将 algorithm 对象标识符设置为 id-slh-dsa-shake-192s (2.16.840.1.101.3.4.3.28) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-192f":

          将 algorithm 对象标识符设置为 id-slh-dsa-shake-192f (2.16.840.1.101.3.4.3.29) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-256s":

          将 algorithm 对象标识符设置为 id-slh-dsa-shake-256s (2.16.840.1.101.3.4.3.30) OID。

          如果 keyAlgorithm 的 name 成员是 "SLH-DSA-SHAKE-256f":

          将 algorithm 对象标识符设置为 id-slh-dsa-shake-256f (2.16.840.1.101.3.4.3.31) OID。

          否则:

          抛出 一个 NotSupportedError。

      • 将 privateKey 字段设置为对 一个表示由 key 的 [[handle]] 内部槽所表示的 SLH-DSA 私钥的 OCTET STRING ASN.1 类型进行 DER 编码所得的结果。

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

    如果 format 是 "raw-public":
    1. 如果 key 的 [[type]] 内部槽 不是 "public", 则抛出一个 InvalidAccessError。

    2. 令 data 为一个字节序列, 其中包含由 key 的 [[handle]] 内部槽所表示的 SLH-DSA 公钥。

    3. 令 result 为 data。

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

    2. 令 data 为一个字节序列, 其中包含由 key 的 [[handle]] 内部槽所表示的 SLH-DSA 私钥。

    3. 令 result 为 data。

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

    2. 令 keyAlgorithm 为 key 的 [[algorithm]] 内部槽。

    3. 将 jwk 的 kty 属性设置为 "AKP"。

    4. 将 jwk 的 alg 属性设置为 keyAlgorithm 的 name 成员。

    5. 将 jwk 的 pub 属性 设置为与 key 的 [[handle]] 内部槽相对应的 base64url 编码公钥。

    6. 如果 key 的 [[type]] 内部槽 是 "private":
      将 jwk 的 priv 属性 设置为由 key 的 [[handle]] 内部槽所表示的私钥的 base64url 编码形式。
    7. 将 jwk 的 key_ops 属性设置为 key 的 usages 属性。

    8. 将 jwk 的 ext 属性设置为 key 的 [[extractable]] 内部槽。

    9. 令 result 为 jwk。

    否则:

    抛出一个 NotSupportedError。

  4. 返回 result。

10. AES-OCB

10.1 描述

本节为非规范性内容。

"AES-OCB" 算法标识符用于使用 OCB 模式的 AES 执行认证加密和解密, 如 [RFC7253] 中所述。

10.2 注册

此算法的已识别算法名称 为 "AES-OCB"。

操作 参数 结果
加密 AeadParams 字节 序列
解密 AeadParams 字节 序列
生成密钥 AesKeyGenParams CryptoKey
导入密钥 无 CryptoKey
导出密钥 无 对象
获取密钥长度 AesDerivedKeyParams 整数

10.3 AeadParams 字典

WebIDLdictionary AeadParams : Algorithm {
  required BufferSource iv;
  BufferSource additionalData;
  [EnforceRange] octet tagLength;
};

iv 成员表示要使用的初始化向量。

additionalData 成员表示要包含的 附加认证数据。

tagLength 成员表示所需的 认证标签长度。

注

AeadParams 字典与 [webcrypto] 的 AesGcmParams 字典完全相同, 在合并本提案时,后者可以由前者替代。

10.4 操作

10.4.1 加密

  1. 如果 normalizedAlgorithm 的 iv 成员的长度大于 15 字节, 则抛出一个 OperationError。

  2. 如果 normalizedAlgorithm 的 tagLength 成员不存在:
    令 tagLength 为 128。
    如果 normalizedAlgorithm 的 tagLength 成员是 64、96 或 128 之一:
    令 tagLength 等于 normalizedAlgorithm 的 tagLength 成员
    否则:
    抛出一个 OperationError。
  3. 如果 normalizedAlgorithm 的 additionalData 成员存在, 则令 additionalData 为该成员,否则为 空八位字节字符串。

  4. 令 C 为执行 [RFC7253] 第 4.2 节中描述的 OCB-ENCRYPT 函数所得的输出,其中使用 AES 作为 分组密码,使用由 key 的 [[handle]] 内部槽所表示的密钥作为 K 输入参数, 使用 normalizedAlgorithm 的 iv 成员作为 N 输入参数, additionalData 作为 A 输入参数, plaintext 作为 P 输入参数,并且 tagLength 作为 TAGLEN 全局参数。

  5. 返回 C。

10.4.2 解密

  1. 如果 normalizedAlgorithm 的 iv 成员的长度大于 15 字节, 则抛出一个 OperationError。

  2. 如果 normalizedAlgorithm 的 tagLength 成员不存在:
    令 tagLength 为 128。
    如果 normalizedAlgorithm 的 tagLength 成员是 64、96 或 128 之一:
    令 tagLength 等于 normalizedAlgorithm 的 tagLength 成员
    否则:
    抛出一个 OperationError。
  3. 如果 ciphertext 的长度小于 tagLength 位, 则抛出一个 OperationError。

  4. 如果 normalizedAlgorithm 的 additionalData 成员存在, 则令 additionalData 为该成员,否则为 空八位字节字符串。

  5. 执行 [RFC7253] 第 4.3 节中描述的 OCB-DECRYPT 函数,其中使用 AES 作为 分组密码,使用由 key 的 [[handle]] 内部槽所表示的密钥作为 K 输入参数, 使用 normalizedAlgorithm 的 iv 成员作为 N 输入参数, additionalData 作为 A 输入参数, ciphertext 作为 C 输入参数,并且 tagLength 作为 TAGLEN 全局参数。

    如果算法的结果是认证失败指示 "INVALID":
    抛出一个 OperationError
    否则:
    令 plaintext 为 OCB-DECRYPT 的输出 P。
  6. 返回 plaintext。

10.4.3 生成密钥

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

  2. 如果 normalizedAlgorithm 的 length 成员不等于 128、192 或 256 之一, 则抛出一个 OperationError。

  3. 生成一个长度 等于 normalizedAlgorithm 的 length 成员的 AES 密钥。

  4. 如果密钥生成步骤失败, 则抛出一个 OperationError。

  5. 令 key 为一个新的 CryptoKey 对象,其表示 生成的 AES 密钥。

  6. 将 key 的 [[type]] 内部槽设置为 "secret"。

  7. 令 algorithm 为一个新的 AesKeyAlgorithm。

  8. 将 algorithm 的 name 属性设置为 "AES-OCB"。

  9. 将 algorithm 的 length 属性设置为等于 normalizedAlgorithm 的 length 成员。

  10. 将 key 的 [[algorithm]] 内部 槽设置为 algorithm。

  11. 将 key 的 [[extractable]] 内部 槽设置为 extractable。

  12. 将 key 的 [[usages]] 内部槽设置为 usages 的规范化值。

  13. 返回 key。

10.4.4 导入密钥

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

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

  3. 如果 format 是 "raw-secret":
    1. 令 data 为 keyData。

    2. 如果 data 的位长度不是 128、192 或 256, 则抛出一个 DataError。

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

      令 jwk 等于 keyData。

      否则:

      抛出一个 DataError。

    2. 如果 jwk 的 kty 字段不是 "oct", 则抛出一个 DataError。

    3. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.4 节的要求, 则抛出一个 DataError。

    4. 令 data 为通过解码 jwk 的 k 字段所得的字节序列。

    5. 如果 data 的长度为 128 位:
      如果 jwk 的 alg 字段存在,且不是 "A128OCB", 则抛出一个 DataError。
      如果 data 的长度为 192 位:
      如果 jwk 的 alg 字段存在,且不是 "A192OCB", 则抛出一个 DataError。
      如果 data 的长度为 256 位:
      如果 jwk 的 alg 字段存在,且不是 "A256OCB", 则抛出一个 DataError。
      否则:
      抛出一个 DataError。
    6. 如果 usages 非空且 jwk 的 use 字段存在且 不是 "enc", 则抛出一个 DataError。

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

    8. 如果 jwk 的 ext 字段存在且 值为 false,而 extractable 为 true, 则抛出一个 DataError。

    否则:
    抛出一个 NotSupportedError。
  4. 令 key 为一个新的 CryptoKey 对象,其表示值为 data 的 AES 密钥。

  5. 将 key 的 [[type]] 内部槽设置为 "secret"。

  6. 令 algorithm 为一个新的 AesKeyAlgorithm。

  7. 将 algorithm 的 name 属性设置为 "AES-OCB"。

  8. 将 algorithm 的 length 属性设置为 data 的位长度。

  9. 将 key 的 [[algorithm]] 内部 槽设置为 algorithm。

  10. 返回 key。

10.4.5 导出密钥

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

  2. 如果 format 是 "raw-secret":
    1. 令 data 为一个字节序列, 其中包含由 key 的 [[handle]] 内部槽所表示的密钥的原始八位字节。

    2. 令 result 为 data。

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

    2. 将 jwk 的 kty 属性设置为 字符串 "oct"。

    3. 将 jwk 的 k 属性设置为一个字符串, 其中包含由 key 的 [[handle]] 内部槽所表示的密钥的原始八位字节,并按照 JSON Web Algorithms [JWA] 第 6.4 节进行编码。

    4. 如果 key 的 length 属性为 128:
      将 jwk 的 alg 属性设置为 字符串 "A128OCB"。
      如果 key 的 length 属性为 192:
      将 jwk 的 alg 属性设置为 字符串 "A192OCB"。
      如果 key 的 length 属性为 256:
      将 jwk 的 alg 属性设置为 字符串 "A256OCB"。
    5. 将 jwk 的 key_ops 属性设置为等于 key 的 usages 属性。

    6. 将 jwk 的 ext 属性设置为等于 key 的 [[extractable]] 内部槽。

    7. 令 result 为 jwk。

    否则:

    抛出一个 NotSupportedError。

  3. 返回 result。

10.4.6 获取密钥长度

  1. 如果 normalizedDerivedKeyAlgorithm 的 length 成员不是 128、192 或 256,则抛出一个 OperationError。

  2. 返回 normalizedDerivedKeyAlgorithm 的 length 成员。

11. ChaCha20-Poly1305

11.1 描述

本节为非规范性内容。

"ChaCha20-Poly1305" 算法标识符用于使用 AEAD_CHACHA20_POLY1305 执行认证加密和解密, 如 [RFC8439] 中所述。

11.2 注册

此算法的已识别算法名称 为 "ChaCha20-Poly1305"。

操作 参数 结果
加密 AeadParams 字节 序列
解密 AeadParams 字节 序列
生成密钥 无 CryptoKey
导入密钥 无 CryptoKey
导出密钥 无 对象
获取密钥长度 无 整数

11.3 操作

11.3.1 加密

  1. 如果 normalizedAlgorithm 的 iv 成员的长度不是 12 字节, 则抛出一个 OperationError。

  2. 如果 normalizedAlgorithm 的 tagLength 成员 存在且不是 128, 则抛出一个 OperationError。

  3. 如果 normalizedAlgorithm 的 additionalData 成员存在, 则令 additionalData 为该成员,否则为 空八位字节字符串。

  4. 令 ciphertext 为执行 [RFC8439] 第 2.8 节中描述的 AEAD_CHACHA20_POLY1305 加密算法所得的输出,使用 由 key 的 [[handle]] 内部槽所表示的密钥作为密钥输入参数, 使用 normalizedAlgorithm 的 iv 成员作为 nonce 输入参数, plaintext 作为明文输入参数,并且 additionalData 作为附加认证数据(AAD)输入参数。

  5. 返回 ciphertext。

11.3.2 解密

  1. 如果 normalizedAlgorithm 的 iv 成员的长度不是 12 字节, 则抛出一个 OperationError。

  2. 如果 normalizedAlgorithm 的 tagLength 成员 存在且不是 128, 则抛出一个 OperationError。

  3. 如果 ciphertext 的长度小于 128 位, 则抛出一个 OperationError。

  4. 如果 normalizedAlgorithm 的 additionalData 成员存在, 则令 additionalData 为该成员,否则为 空八位字节字符串。

  5. 执行 [RFC8439] 第 2.8 节中描述的 AEAD_CHACHA20_POLY1305 解密算法,使用 由 key 的 [[handle]] 内部槽所表示的密钥作为密钥输入参数, 使用 normalizedAlgorithm 的 iv 成员作为 nonce 输入参数, ciphertext 作为密文输入参数,并且 additionalData 作为附加认证数据(AAD)输入参数。

    如果算法的结果是认证失败指示:
    抛出一个 OperationError
    否则:
    令 plaintext 为所得的明文。
  6. 返回 plaintext。

11.3.3 生成密钥

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

  2. 生成一个 256 位密钥。

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

  4. 令 key 为一个新的 CryptoKey 对象,其表示 生成的密钥。

  5. 将 key 的 [[type]] 内部槽设置为 "secret"。

  6. 令 algorithm 为一个新的 KeyAlgorithm。

  7. 将 algorithm 的 name 属性设置为 "ChaCha20-Poly1305"。

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

  9. 将 key 的 [[extractable]] 内部 槽设置为 extractable。

  10. 将 key 的 [[usages]] 内部槽设置为 usages 的规范化值。

  11. 返回 key。

11.3.4 导入密钥

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

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

  3. 如果 format 是 "raw-secret":
    1. 令 data 为 keyData。

    2. 如果 data 的位长度不是 256, 则抛出一个 DataError。

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

      令 jwk 等于 keyData。

      否则:

      抛出一个 DataError。

    2. 如果 jwk 的 kty 字段不是 "oct", 则抛出一个 DataError。

    3. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.4 节的要求, 则抛出一个 DataError。

    4. 令 data 为通过解码 jwk 的 k 字段所得的字节序列。

    5. 如果 jwk 的 alg 字段存在,且 不是 "C20P", 则抛出一个 DataError。

    6. 如果 usages 非空且 jwk 的 use 字段存在且 不是 "enc", 则抛出一个 DataError。

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

    8. 如果 jwk 的 ext 字段存在且 值为 false,而 extractable 为 true, 则抛出一个 DataError。

    否则:
    抛出一个 NotSupportedError。
  4. 令 key 为一个新的 CryptoKey 对象,其表示值为 data 的密钥。

  5. 将 key 的 [[type]] 内部槽设置为 "secret"。

  6. 令 algorithm 为一个新的 KeyAlgorithm。

  7. 将 algorithm 的 name 属性设置为 "ChaCha20-Poly1305"。

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

  9. 返回 key。

11.3.5 导出密钥

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

  2. 如果 format 是 "raw-secret":
    1. 令 data 为一个字节序列, 其中包含由 key 的 [[handle]] 内部槽所表示的密钥的原始八位字节。

    2. 令 result 为 data。

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

    2. 将 jwk 的 kty 属性设置为 字符串 "oct"。

    3. 将 jwk 的 k 属性设置为一个字符串, 其中包含由 key 的 [[handle]] 内部槽所表示的密钥的原始八位字节,并按照 JSON Web Algorithms [JWA] 第 6.4 节进行编码。

    4. 将 jwk 的 alg 属性设置为 字符串 "C20P"。

    5. 将 jwk 的 key_ops 属性设置为等于 key 的 usages 属性。

    6. 将 jwk 的 ext 属性设置为等于 key 的 [[extractable]] 内部槽。

    7. 令 result 为 jwk。

    否则:

    抛出一个 NotSupportedError。

  3. 返回 result。

11.3.6 获取密钥长度

  1. 返回 256。

12. SHA-3

12.1 描述

本节为非规范性内容。

本节描述 SHA-3 哈希函数系列,如 [FIPS-202] 中所规定。

12.2 注册

对应各个 SHA-3 算法的已识别算法 名称为 "SHA3-256"、 "SHA3-384" 和 "SHA3-512"。

操作 参数 结果
摘要 无 字节 序列

12.3 操作

12.3.1 摘要

  1. 如果 normalizedAlgorithm 的 name 成员与 "SHA3-256" 进行区分大小写的字符串匹配:
    令 result 为执行 [FIPS-202] 第 6.1 节中定义的 SHA3-256 哈希函数所得的结果,其中使用 message 作为输入消息 M。
    如果 normalizedAlgorithm 的 name 成员与 "SHA3-384" 进行区分大小写的字符串匹配:
    令 result 为执行 [FIPS-202] 第 6.1 节中定义的 SHA3-384 哈希函数所得的结果,其中使用 message 作为输入消息 M。
    如果 normalizedAlgorithm 的 name 成员与 "SHA3-512" 进行区分大小写的字符串匹配:
    令 result 为执行 [FIPS-202] 第 6.1 节中定义的 SHA3-512 哈希函数所得的结果,其中使用 message 作为输入消息 M。
  2. 如果执行操作导致错误,则抛出一个 OperationError。

  3. 返回 result。

13. cSHAKE

13.1 描述

本节为非规范性内容。

本节描述 cSHAKE128 和 cSHAKE256,如 [NIST-SP800-185] 中所规定。

当 functionName 和 customization 参数均为空(或未提供)时,cSHAKE 在功能上等同于 [FIPS-202] 第 6.2 节中定义的 SHAKE。

注

虽然从技术上可以实现,但在 digest() 之外将 cSHAKE 用作其他算法的一部分 (例如作为 HMAC 的 hash 参数) 不太可能有用,也不预期会得到支持。 supports() 的结果应 反映是否支持此类用法。

13.2 注册

已识别算法 名称为 "cSHAKE128" 和 "cSHAKE256"。

操作 参数 结果
摘要 CShakeParams 字节 序列

13.3 CShakeParams 字典

WebIDLdictionary CShakeParams : Algorithm {
  required [EnforceRange] unsigned long outputLength;
  BufferSource functionName;
  BufferSource customization;
};

outputLength 成员表示所请求的 输出位长度。

functionName 成员表示函数 名称,NIST 使用该名称定义基于 cSHAKE 的函数。使用时,其值应仅设置为 NIST 定义的值。

customization 成员表示 自定义字符串。应用程序选择该字符串以定义函数的一个变体。

13.4 操作

13.4.1 摘要

  1. 令 outputLength 为 normalizedAlgorithm 的 outputLength 成员。

  2. 如果 normalizedAlgorithm 的 functionName 成员存在, 则令 functionName 为该成员,否则为 空八位字节字符串。

  3. 如果 normalizedAlgorithm 的 customization 成员存在, 则令 customization 为该成员,否则为 空八位字节字符串。

  4. 如果 normalizedAlgorithm 的 name 成员与 "cSHAKE128" 进行区分大小写的字符串匹配:
    令 result 为执行 [NIST-SP800-185] 第 3 节中定义的 cSHAKE128 函数所得的结果,其中使用 message 作为 X 输入参数, outputLength 作为 L 输入参数, functionName 作为 N 输入参数,并且 customization 作为 S 输入参数。
    如果 normalizedAlgorithm 的 name 成员与 "cSHAKE256" 进行区分大小写的字符串匹配:
    令 result 为执行 [NIST-SP800-185] 第 3 节中定义的 cSHAKE256 函数所得的结果,其中使用 message 作为 X 输入参数, outputLength 作为 L 输入参数, functionName 作为 N 输入参数,并且 customization 作为 S 输入参数。
  5. 如果执行操作导致错误,则抛出一个 OperationError。

  6. 返回一个包含 result 的字节序列。

14. TurboSHAKE

14.1 描述

本节为非规范性内容。

本节描述 TurboSHAKE128 和 TurboSHAKE256,如 [RFC9861] 中所规定。

TurboSHAKE 是基于 SHA-3 所使用的 Keccak 置换之 减少轮数版本的一系列可扩展输出函数(XOF),因此它 在保持相同安全强度的同时,速度大约是 SHAKE 函数的两倍。

注

对于 128 位碰撞安全性,TurboSHAKE128 的输出应至少为 256 位。 对于 256 位碰撞安全性,TurboSHAKE256 的输出应至少为 512 位。 这些输出长度也超过了相应的原像和第二原像安全性 要求(后者只要求输出长度等于目标安全级别)。 当输出长度达到这些阈值时,TurboSHAKE128 达到 NIST 后量子 安全级别 2,而 TurboSHAKE256 达到级别 5。 参见 [RFC9861] 第 7 节。

注

虽然从技术上可以实现,但在 digest() 之外将 TurboSHAKE 用作其他算法的一部分 (例如作为 HMAC 的 hash 参数) 不太可能有用,也不预期会得到支持。 supports() 的结果应 反映是否支持此类用法。

14.2 注册

已识别算法 名称为 "TurboSHAKE128" 和 "TurboSHAKE256"。

操作 参数 结果
摘要 TurboShakeParams 字节 序列

14.3 TurboShakeParams 字典

WebIDLdictionary TurboShakeParams : Algorithm {
  required [EnforceRange] unsigned long outputLength;
  [EnforceRange] octet domainSeparation;
};

outputLength 成员表示所请求的 输出位长度。

domainSeparation 成员表示域 分离字节。如果未指定,则默认为 0x1F。有效值范围为 0x01 到 0x7F。

注

同时使用 KangarooTwelve 和 TurboSHAKE 的协议应避免将 0x06、0x07 和 0x0B 用于域分离, 因为这些值由 KangarooTwelve 在内部使用。

14.4 操作

14.4.1 摘要

  1. 令 outputLength 为 normalizedAlgorithm 的 outputLength 成员。

  2. 如果 outputLength 为零或不是 8 的倍数, 则抛出一个 OperationError。

  3. 如果 normalizedAlgorithm 的 domainSeparation 成员存在,则令 domainSeparation 为该成员,否则为 0x1F。

  4. 如果 domainSeparation 小于 0x01 或大于 0x7F, 则抛出一个 OperationError。

  5. 如果 normalizedAlgorithm 的 name 成员与 "TurboSHAKE128" 进行区分大小写的字符串匹配:
    令 result 为执行 [RFC9861] 第 2 节中定义的 TurboSHAKE128 函数所得的结果,其中使用 message 作为 M 输入参数, domainSeparation 作为 D 输入参数,并且 outputLength 除以 8 作为 L 输入参数。
    如果 normalizedAlgorithm 的 name 成员与 "TurboSHAKE256" 进行区分大小写的字符串匹配:
    令 result 为执行 [RFC9861] 第 2 节中定义的 TurboSHAKE256 函数所得的结果,其中使用 message 作为 M 输入参数, domainSeparation 作为 D 输入参数,并且 outputLength 除以 8 作为 L 输入参数。
  6. 如果执行操作导致错误,则抛出一个 OperationError。

  7. 返回 result。

15. KangarooTwelve

15.1 描述

本节为非规范性内容。

本节描述 KT128 和 KT256,如 [RFC9861] 中所规定。

KangarooTwelve 是一系列可扩展输出函数(XOF),其在 TurboSHAKE 之上应用树哈希,从而支持对输入数据进行并行处理。 KT128 内部使用 TurboSHAKE128,而 KT256 使用 TurboSHAKE256。

注

对于 128 位碰撞安全性,KT128 的输出应至少为 256 位。 对于 256 位碰撞安全性,KT256 的输出应至少为 512 位。 这些输出长度也超过了相应的原像和第二原像安全性 要求(后者只要求输出长度等于目标安全级别)。 当输出长度达到这些阈值时,KT128 达到 NIST 后量子 安全级别 2,而 KT256 达到级别 5。 参见 [RFC9861] 第 7 节。

注

虽然从技术上可以实现,但在 digest() 之外将 KangarooTwelve 用作其他算法的一部分 (例如作为 HMAC 的 hash 参数) 不太可能有用,也不预期会得到支持。 supports() 的结果应 反映是否支持此类用法。

15.2 注册

已识别算法 名称为 "KT128" 和 "KT256"。

操作 参数 结果
摘要 KangarooTwelveParams 字节 序列

15.3 KangarooTwelveParams 字典

WebIDLdictionary KangarooTwelveParams : Algorithm {
  required [EnforceRange] unsigned long outputLength;
  BufferSource customization;
};

outputLength 成员表示所请求的 输出位长度。

customization 成员表示 自定义字符串。应用程序选择该字符串以定义函数的一个变体。如果未 指定,则默认为空字符串。

15.4 操作

15.4.1 摘要

  1. 令 outputLength 为 normalizedAlgorithm 的 outputLength 成员。

  2. 如果 outputLength 为零或不是 8 的倍数, 则抛出一个 OperationError。

  3. 如果 normalizedAlgorithm 的 customization 成员存在,则令 customization 为该成员,否则为 空八位字节字符串。

  4. 如果 normalizedAlgorithm 的 name 成员与 "KT128" 进行区分大小写的字符串匹配:
    令 result 为执行 [RFC9861] 第 3 节中定义的 KT128 函数所得的结果,其中使用 message 作为 M 输入参数, customization 作为 C 输入参数,并且 outputLength 除以 8 作为 L 输入参数。
    如果 normalizedAlgorithm 的 name 成员与 "KT256" 进行区分大小写的字符串匹配:
    令 result 为执行 [RFC9861] 第 3 节中定义的 KT256 函数所得的结果,其中使用 message 作为 M 输入参数, customization 作为 C 输入参数,并且 outputLength 除以 8 作为 L 输入参数。
  5. 如果执行操作导致错误,则抛出一个 OperationError。

  6. 返回 result。

16. KMAC

16.1 描述

本节为非规范性内容。

本节描述 KMAC128 和 KMAC256,如 [NIST-SP800-185] 中所规定。

16.2 注册

已识别算法 名称为 "KMAC128" 和 "KMAC256"。

操作 参数 结果
签名 KmacParams 字节 序列
验证 KmacParams 布尔值
生成密钥 KmacKeyGenParams CryptoKey
导入密钥 KmacImportParams CryptoKey
导出密钥 无 对象
获取密钥长度 KmacImportParams 整数

16.3 KmacKeyGenParams 字典

WebIDLdictionary KmacKeyGenParams : Algorithm {
  [EnforceRange] unsigned long length;
};

length 成员表示要生成的密钥长度(以位为单位)。 如果未指定,则使用推荐长度,即 KMAC128 为 128, KMAC256 为 256。

16.4 KmacImportParams 字典

WebIDLdictionary KmacImportParams : Algorithm {
  [EnforceRange] unsigned long length;
};

length 成员表示密钥长度(以位为单位)。

16.5 KmacKeyAlgorithm 字典

WebIDLdictionary KmacKeyAlgorithm : KeyAlgorithm {
  required [EnforceRange] unsigned long length;
};

length 成员表示密钥长度(以位为单位)。

16.6 KmacParams 字典

WebIDLdictionary KmacParams : Algorithm {
  required [EnforceRange] unsigned long outputLength;
  BufferSource customization;
};

outputLength 成员表示所请求的 输出位长度。

customization 成员表示 自定义字符串。应用程序选择该字符串以定义函数的一个变体。

16.7 操作

16.7.1 签名

  1. 如果 normalizedAlgorithm 的 customization 成员存在, 则令 customization 为该成员,否则为 空八位字节字符串。

  2. 如果 normalizedAlgorithm 的 name 成员与 "KMAC128" 进行区分大小写的字符串匹配:
    令 mac 为执行 [NIST-SP800-185] 第 4 节中定义的 KMAC128 函数所得的结果,其中使用 由 key 的 [[handle]] 内部槽所表示的密钥作为 K 输入参数, message 作为 X 输入参数, normalizedAlgorithm 的 outputLength 成员作为 L 输入参数,并且 customization 作为 S 输入参数。
    如果 normalizedAlgorithm 的 name 成员与 "KMAC256" 进行区分大小写的字符串匹配:
    令 mac 为执行 [NIST-SP800-185] 第 4 节中定义的 KMAC256 函数所得的结果,其中使用 由 key 的 [[handle]] 内部槽所表示的密钥作为 K 输入参数, message 作为 X 输入参数, normalizedAlgorithm 的 outputLength 成员作为 L 输入参数,并且 customization 作为 S 输入参数。
  3. 返回一个包含 mac 的字节序列。

16.7.2 验证

  1. 如果 normalizedAlgorithm 的 customization 成员存在, 则令 customization 为该成员,否则为 空八位字节字符串。

  2. 如果 normalizedAlgorithm 的 name 成员与 "KMAC128" 进行区分大小写的字符串匹配:
    令 mac 为执行 [NIST-SP800-185] 第 4 节中定义的 KMAC128 函数所得的结果,其中使用 由 key 的 [[handle]] 内部槽所表示的密钥作为 K 输入参数, message 作为 X 输入参数, normalizedAlgorithm 的 outputLength 成员作为 L 输入参数,并且 customization 作为 S 输入参数。
    如果 normalizedAlgorithm 的 name 成员与 "KMAC256" 进行区分大小写的字符串匹配:
    令 mac 为执行 [NIST-SP800-185] 第 4 节中定义的 KMAC256 函数所得的结果,其中使用 由 key 的 [[handle]] 内部槽所表示的密钥作为 K 输入参数, message 作为 X 输入参数, normalizedAlgorithm 的 outputLength 成员作为 L 输入参数,并且 customization 作为 S 输入参数。
  3. 令 computedMac 为一个包含 mac 的字节序列。

  4. 如果 computedMac 等于 signature,则返回 true,否则返回 false。 此比较必须以恒定时间执行。

16.7.3 生成密钥

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

  2. 如果 normalizedAlgorithm 的 length 成员存在:
    令 length 等于 normalizedAlgorithm 的 length 成员。
    否则,如果 normalizedAlgorithm 的 name 成员与 "KMAC128" 进行区分大小写的字符串匹配:
    令 length 为 128。
    否则,如果 normalizedAlgorithm 的 name 成员与 "KMAC256" 进行区分大小写的字符串匹配:
    令 length 为 256。
  3. 生成一个长度为 length 位的密钥。

  4. 如果密钥生成步骤失败, 则抛出一个 OperationError。

  5. 令 key 为一个新的 CryptoKey 对象,其表示 生成的密钥。

  6. 将 key 的 [[type]] 内部槽设置为 "secret"。

  7. 令 algorithm 为一个新的 KmacKeyAlgorithm。

  8. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 成员。

  9. 将 algorithm 的 length 属性设置为 length。

  10. 将 key 的 [[algorithm]] 内部 槽设置为 algorithm。

  11. 将 key 的 [[extractable]] 内部 槽设置为 extractable。

  12. 将 key 的 [[usages]] 内部槽设置为 usages 的规范化值。

  13. 返回 key。

16.7.4 导入密钥

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

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

  3. 如果 format 是 "raw-secret":
    1. 令 data 为 keyData。

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

      令 jwk 等于 keyData。

      否则:

      抛出一个 DataError。

    2. 如果 jwk 的 kty 字段不是 "oct", 则抛出一个 DataError。

    3. 如果 jwk 不满足 JSON Web Algorithms [JWA] 第 6.4 节的要求, 则抛出一个 DataError。

    4. 令 data 为通过解码 jwk 的 k 字段所得的字节序列。

    5. 如果 normalizedAlgorithm 的 name 成员与 "KMAC128" 进行区分大小写的字符串匹配:
      如果 jwk 的 alg 字段存在 且不是 "K128", 则抛出一个 DataError。
      如果 normalizedAlgorithm 的 name 成员与 "KMAC256" 进行区分大小写的字符串匹配:
      如果 jwk 的 alg 字段存在 且不是 "K256", 则抛出一个 DataError。
    6. 如果 usages 非空且 jwk 的 use 字段存在且 不是 "sig", 则抛出一个 DataError。

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

    8. 如果 jwk 的 ext 字段存在且 值为 false,而 extractable 为 true, 则抛出一个 DataError。

    否则:
    抛出一个 NotSupportedError。
  4. 令 length 为 data 的位长度。

  5. 如果 normalizedAlgorithm 的 length 成员存在:
    如果 normalizedAlgorithm 的 length 成员 大于 length:
    抛出一个 DataError。
    如果 normalizedAlgorithm 的 length 成员 小于或等于 length 减 8:
    抛出一个 DataError。
    否则:
    将 length 设置为等于 normalizedAlgorithm 的 length 成员。
  6. 令 key 为一个新的 CryptoKey 对象,其表示由 data 的前 length 位组成的 KMAC 密钥。

  7. 将 key 的 [[type]] 内部槽设置为 "secret"。

  8. 令 algorithm 为一个新的 KmacKeyAlgorithm。

  9. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 成员。

  10. 将 algorithm 的 length 属性设置为 length。

  11. 将 key 的 [[algorithm]] 内部 槽设置为 algorithm。

  12. 返回 key。

16.7.5 导出密钥

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

  2. 令 bits 为由 key 的 [[handle]] 内部槽所表示的密钥的原始位。

  3. 令 data 为一个包含 bits 的字节序列。

  4. 如果 format 是 "raw-secret":
    1. 令 result 为 data。

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

    2. 将 jwk 的 kty 属性设置为 字符串 "oct"。

    3. 将 jwk 的 k 属性设置为一个包含 data 的字符串, 并按照 JSON Web Algorithms [JWA] 第 6.4 节进行编码。

    4. 令 keyAlgorithm 为 key 的 [[algorithm]] 内部槽。

    5. 如果 keyAlgorithm 的 name 成员是 "KMAC128":
      将 jwk 的 alg 属性设置为 字符串 "K128"。
      如果 keyAlgorithm 的 name 成员是 "KMAC256":
      将 jwk 的 alg 属性设置为 字符串 "K256"。
    6. 将 jwk 的 key_ops 属性设置为等于 key 的 usages 属性。

    7. 将 jwk 的 ext 属性设置为等于 key 的 [[extractable]] 内部槽。

    8. 令 result 为 jwk。

    否则:

    抛出一个 NotSupportedError。

  5. 返回 result。

16.7.6 获取密钥长度

  1. 如果 normalizedAlgorithm 的 length 成员存在:
    令 length 等于 normalizedAlgorithm 的 length 成员。
    否则,如果 normalizedAlgorithm 的 name 成员与 "KMAC128" 进行区分大小写的字符串匹配:
    令 length 为 128。
    否则,如果 normalizedAlgorithm 的 name 成员与 "KMAC256" 进行区分大小写的字符串匹配:
    令 length 为 256。
  2. 返回 length。

17. Argon2

17.1 描述

本节为非规范性内容。

本节描述用于密码哈希和密钥派生的 Argon2 函数, 如 [RFC9106] 中所定义。

17.2 注册

对应各个 Argon2 类型的已识别算法 名称为 "Argon2d"、 "Argon2i" 和 "Argon2id"。

操作 参数 结果
派生位 Argon2Params 字节 序列
导入密钥 无 CryptoKey
获取密钥长度 无 null

17.3 Argon2Params 字典

WebIDLdictionary Argon2Params : Algorithm {
  required BufferSource nonce;
  required [EnforceRange] unsigned long parallelism;
  required [EnforceRange] unsigned long memory;
  required [EnforceRange] unsigned long passes;
  [EnforceRange] octet version;
  BufferSource secretValue;
  BufferSource associatedData;
};

nonce 成员表示 nonce,在 密码哈希应用中其作为盐值。

parallelism 成员表示 并行度。

memory 成员表示以 kibibyte 为单位的内存大小。它必须至少为并行度的 8 倍。

passes 成员表示 遍数。

version 成员表示版本号。默认 且当前唯一已定义的版本为 19 (0x13)。

secretValue 成员表示可选的 秘密值。

associatedData 成员表示可选的 关联数据。

注

有关参数的推荐值,请参见 [RFC9106] 第 4 节。

17.4 操作

17.4.1 派生位

  1. 如果 length 为 null,或小于 32 (4*8),或不是 8 的倍数, 则抛出一个 OperationError。

  2. 如果 normalizedAlgorithm 的 version 成员 存在且不是 19 (0x13), 则抛出一个 OperationError。

  3. 如果 normalizedAlgorithm 的 parallelism 成员为零, 或大于 16777215 (2^24-1), 则抛出一个 OperationError。

  4. 如果 normalizedAlgorithm 的 memory 成员小于 normalizedAlgorithm 的 parallelism 成员的 8 倍, 则抛出一个 OperationError。

  5. 如果 normalizedAlgorithm 的 passes 成员为零, 则抛出一个 OperationError。

  6. 如果 normalizedAlgorithm 的 name 成员与 "Argon2d" 进行区分大小写的字符串匹配:
    令 type 为 0。
    如果 normalizedAlgorithm 的 name 成员与 "Argon2i" 进行区分大小写的字符串匹配:
    令 type 为 1。
    如果 normalizedAlgorithm 的 name 成员与 "Argon2id" 进行区分大小写的字符串匹配:
    令 type 为 2。
  7. 如果存在,则令 secretValue 为 normalizedAlgorithm 的 secretValue 成员。

  8. 如果存在,则令 associatedData 为 normalizedAlgorithm 的 associatedData 成员。

  9. 令 result 为执行 [RFC9106] 第 3 节中定义的 Argon2 函数所得的结果,其中使用 由 key 的 [[handle]] 内部槽所表示的密码 作为消息 P, normalizedAlgorithm 的 nonce 属性作为 nonce S, normalizedAlgorithm 的 parallelism 属性的值 作为并行度 p, normalizedAlgorithm 的 memory 属性的值 作为内存大小 m, normalizedAlgorithm 的 passes 属性的值 作为遍数 t, 0x13 作为版本号 v, secretValue(如果存在)作为秘密值 K, associatedData(如果存在)作为关联数据 X, type 作为类型 y,以及 length 除以 8 作为标签长度 T。

  10. 如果密钥派生操作失败, 则抛出一个 OperationError。

  11. 返回 result。

17.4.2 导入密钥

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

  2. 如果 format 不是 "raw-secret",则抛出一个 NotSupportedError

  3. 如果 usages 包含一个不是 "deriveKey" 或 "deriveBits" 的值,则 抛出一个 SyntaxError。

  4. 如果 extractable 不是 false, 则抛出一个 SyntaxError。

  5. 令 key 为一个新的 CryptoKey, 表示 keyData。

  6. 将 key 的 [[type]] 内部槽设置为 "secret"。

  7. 令 algorithm 为一个新的 KeyAlgorithm 对象。

  8. 将 algorithm 的 name 属性设置为 normalizedAlgorithm 的 name 成员。

  9. 将 key 的 [[algorithm]] 内部 槽设置为 algorithm。

  10. 返回 key。

17.4.3 获取密钥长度

  1. 返回 null。

18. IANA 注意事项

18.1 JSON Web 签名和加密算法注册

本节在 IANA JSON Web 签名和加密算法 注册表中注册以下算法标识符,以用于 JSON Web Key。

这些注册仅使用 "JWK" 作为算法使用位置。 它们为本规范定义的 JSON Web Key 表示形式提供稳定的 alg 值, 以便 Web Cryptography API 实现可以使用 exportKey() 和 importKey() 通过 "jwk" 来序列化和解析这些密钥。本规范不定义将 这些 标识符用作 JSON Web Signature 或 JSON Web Encryption 算法。

18.2 JSON Web 密钥操作

本节在 IANA JSON Web 密钥操作注册表中注册以下密钥操作, 供 JSON Web Key 使用。

19. 采用指南

本节为非规范性内容。

本规范定义了许多算法和操作。为了向 实现者提供指导,并加速 Web 平台的 后量子迁移,本节建议应优先实现哪些算法和 操作。

SubtleCrypto.supports 方法通过支持特性检测、优雅 回退和渐进增强,简化了本规范中所有其他算法和 操作的快速采用。

SubtleCrypto.getPublicKey 方法对于实际使用本规范和 [webcrypto] 中定义的非对称算法非常重要。它通过使应用程序能够仅存储私钥而无需存储 对应的公钥,并且无需验证私钥 和公钥确实相互对应,从而简化了密钥管理。此外,它还允许库 作者接受不可提取的私钥,作为那些 将公钥值提交到其输出中的协议的输入。

就算法而言,以下算法被认为对于后量子 迁移以及在 Web 上支持现代 密码协议具有最高优先级,按优先级排序如下:

  1. ML-KEM 是 NIST [FIPS-203] 标准化的主要后量子密钥 封装机制。 与传统密钥协商结合使用时,它可以实现混合 后量子/传统(PQ/T)密钥建立,例如 [draft-ietf-hpke-hpke] 等协议及其 PQ 和 PQ/T 算法 [draft-ietf-hpke-pq] 所采用的方式。
  2. 混合 KEM 提供 将 ML-KEM 与 P-256、X25519 或 P-384 结合的后量子/传统 KEM 实例 [draft-irtf-cfrg-concrete-hybrid-kems-04]。
  3. ML-DSA 是 NIST [FIPS-204] 标准化的主要后量子数字 签名算法。
  4. ChaCha20-Poly1305 是一种广泛 部署的 AEAD 密码 [RFC8439],用于许多协议 (TLS、SSH、WireGuard、HPKE)。
  5. SHA-3 和 cSHAKE (特别是 SHA3-256 和 cSHAKE256)用于许多后量子 构造,包括 ML-KEM 密钥派生和混合 KEM 组合器。特别是,在不带任何自定义 参数的情况下调用 cSHAKE256,其输出与 SHAKE256 完全相同,因此单个 实现即可同时满足自定义(cSHAKE256)和 非自定义(SHAKE256)用例。 但是,如果 cSHAKE 的实现不可用, SHAKE 的实现仍然可能有用,但需要确保 在 customization 参数存在 且 非空时抛出一个 NotSupportedError(并从 SubtleCrypto.supports 返回 false)。
  6. Argon2 是一种内存困难的基于密码的 密钥派生函数 [RFC9106], 可提高对 高度并行化环境 (例如 GPU 和 FPGA)中暴力破解攻击的抵抗力。

SLH-DSA 是一种由 NIST 标准化的无状态基于哈希的数字 签名算法 [FIPS-204]。 到目前为止,它的 采用程度低于 ML-DSA,但如果将来需要 ML-DSA 的替代方案,实现它可能会有用。

除此之外,AES-OCB、 TurboSHAKE、 KangarooTwelve 和 KMAC 都是有价值的补充,但对于 后量子迁移而言并没有那么迫切关键。

20. 使用示例

此示例在 Argon2 可用时使用 Argon2 从密码派生密钥,否则使用 PBKDF2; 然后在 AES-OCB 可用时使用 AES-OCB 对一些文本进行加密和解密,否则使用 AES-GCM。

示例 1:使用从密码派生的密钥加密一些 数据
const password = 'correct horse battery staple';
const derivationAlg =
  SubtleCrypto.supports?.('importKey', 'Argon2id') ?
    'Argon2id' :
    'PBKDF2';
const encryptionAlg =
  SubtleCrypto.supports?.('importKey', 'AES-OCB') ?
    'AES-OCB' :
    'AES-GCM';
const passwordKey = await crypto.subtle.importKey(
  derivationAlg === 'Argon2id' ? 'raw-secret' : 'raw',
  new TextEncoder().encode(password),
  derivationAlg,
  /* 可提取: */ false,
  ['deriveKey']
);
const nonce = crypto.getRandomValues(new Uint8Array(16));
const derivationParams =
  derivationAlg === 'Argon2id' ?
    {
      nonce,
      parallelism: 4,
      memory: 2 ** 21,
      passes: 1
    } :
    {
      salt: nonce,
      iterations: 100_000,
      hash: 'SHA-256'
    };
const key = await crypto.subtle.deriveKey(
  {
    name: derivationAlg,
    ...derivationParams
  },
  passwordKey,
  {
    name: encryptionAlg,
    length: 256
  },
  /* 可提取: */ false,
  ['encrypt', 'decrypt']
);
const plaintext = 'Hello, world!';
const iv = crypto.getRandomValues(new Uint8Array(16));
const encrypted = await crypto.subtle.encrypt(
  { name: encryptionAlg, iv },
  key,
  new TextEncoder().encode(plaintext)
);
// 存储派生和加密算法及其参数
// 以及密文(例如存储在 IndexedDB 或数据库中),
// 并在之后将其取回。然后,使用原始参数和密码
// 派生密钥。这里我们立即
// 使用同一个密钥对象再次进行解密。
const decrypted = new TextDecoder().decode(await crypto.subtle.decrypt(
  { name: encryptionAlg, iv },
  key,
  encrypted
));

A. JSON Web Key / JSON Web Algorithm 之间的映射

本节不具规范性。

有关导入和导出 JWK 的规范性要求, 请参阅特定于算法的章节。

A.1 算法映射

JSON Web 密钥 AlgorithmIdentifier
{ kty: "AKP",
alg: "MLKEM768-P256" }
{ name: "MLKEM768-P256" }
{ kty: "AKP",
alg: "MLKEM768-X25519" }
{ name: "MLKEM768-X25519" }
{ kty: "AKP",
alg: "MLKEM1024-P384" }
{ name: "MLKEM1024-P384" }
{ kty: "oct",
alg: "A128OCB" }
{ name: "AES-OCB",
length: 128 }
{ kty: "oct",
alg: "A192OCB" }
{ name: "AES-OCB",
length: 192 }
{ kty: "oct",
alg: "A256OCB" }
{ name: "AES-OCB",
length: 256 }
{ kty: "oct",
alg: "C20P" }
{ name: "ChaCha20-Poly1305" }
{ kty: "oct",
alg: "K128" }
{ name: "KMAC128" }
{ kty: "oct",
alg: "K256" }
{ name: "KMAC256" }

B. 算法与 PKCS#8 PrivateKeyInfo 之间的映射

本节不具规范性。

有关导入和导出 PKCS#8 PrivateKeyInfo 的 规范性要求,请参阅特定于算法的章节。

privateKeyAlgorithm privateKey 格式 AlgorithmIdentifier 参考文献
id-ml-dsa-44 (2.16.840.1.101.3.4.3.17) ML-DSA-44-PrivateKey "ML-DSA-44" [CSOR],[RFC9881]
id-ml-dsa-65 (2.16.840.1.101.3.4.3.18) ML-DSA-65-PrivateKey "ML-DSA-65" [CSOR],[RFC9881]
id-ml-dsa-87 (2.16.840.1.101.3.4.3.19) ML-DSA-87-PrivateKey "ML-DSA-87" [CSOR],[RFC9881]
id-alg-ml-kem-512 (2.16.840.1.101.3.4.4.1) ML-KEM-512-PrivateKey "ML-KEM-512" [CSOR],[RFC9935]
id-alg-ml-kem-768 (2.16.840.1.101.3.4.4.2) ML-KEM-768-PrivateKey "ML-KEM-768" [CSOR],[RFC9935]
id-alg-ml-kem-1024 (2.16.840.1.101.3.4.4.3) ML-KEM-1024-PrivateKey "ML-KEM-1024" [CSOR],[RFC9935]
id-slh-dsa-sha2-128s (2.16.840.1.101.3.4.3.20) OCTET STRING "SLH-DSA-SHA2-128s" [CSOR],[RFC9814]
id-slh-dsa-sha2-128f (2.16.840.1.101.3.4.3.21) OCTET STRING "SLH-DSA-SHA2-128f" [CSOR],[RFC9814]
id-slh-dsa-sha2-192s (2.16.840.1.101.3.4.3.22) OCTET STRING "SLH-DSA-SHA2-192s" [CSOR],[RFC9814]
id-slh-dsa-sha2-192f (2.16.840.1.101.3.4.3.23) OCTET STRING "SLH-DSA-SHA2-192f" [CSOR],[RFC9814]
id-slh-dsa-sha2-256s (2.16.840.1.101.3.4.3.24) OCTET STRING "SLH-DSA-SHA2-256s" [CSOR],[RFC9814]
id-slh-dsa-sha2-256f (2.16.840.1.101.3.4.3.25) OCTET STRING "SLH-DSA-SHA2-256f" [CSOR],[RFC9814]
id-slh-dsa-shake-128s (2.16.840.1.101.3.4.3.26) OCTET STRING "SLH-DSA-SHAKE-128s" [CSOR],[RFC9814]
id-slh-dsa-shake-128f (2.16.840.1.101.3.4.3.27) OCTET STRING "SLH-DSA-SHAKE-128f" [CSOR],[RFC9814]
id-slh-dsa-shake-192s (2.16.840.1.101.3.4.3.28) OCTET STRING "SLH-DSA-SHAKE-192s" [CSOR],[RFC9814]
id-slh-dsa-shake-192f (2.16.840.1.101.3.4.3.29) OCTET STRING "SLH-DSA-SHAKE-192f" [CSOR],[RFC9814]
id-slh-dsa-shake-256s (2.16.840.1.101.3.4.3.30) OCTET STRING "SLH-DSA-SHAKE-256s" [CSOR],[RFC9814]
id-slh-dsa-shake-256f (2.16.840.1.101.3.4.3.31) OCTET STRING "SLH-DSA-SHAKE-256f" [CSOR],[RFC9814]

C. 算法与 SubjectPublicKeyInfo 之间的映射

本节不具规范性。

有关导入和导出 SPKI 的 规范性要求,请参阅特定于算法的章节。

算法 OID subjectPublicKey ASN.1 结构 AlgorithmIdentifier 参考文献
id-ml-dsa-44 (2.16.840.1.101.3.4.3.17) BIT STRING "ML-DSA-44" [CSOR],[RFC9881]
id-ml-dsa-65 (2.16.840.1.101.3.4.3.18) BIT STRING "ML-DSA-65" [CSOR],[RFC9881]
id-ml-dsa-87 (2.16.840.1.101.3.4.3.19) BIT STRING "ML-DSA-87" [CSOR],[RFC9881]
id-alg-ml-kem-512 (2.16.840.1.101.3.4.4.1) BIT STRING "ML-KEM-512" [CSOR],[RFC9935]
id-alg-ml-kem-768 (2.16.840.1.101.3.4.4.2) BIT STRING "ML-KEM-768" [CSOR],[RFC9935]
id-alg-ml-kem-1024 (2.16.840.1.101.3.4.4.3) BIT STRING "ML-KEM-1024" [CSOR],[RFC9935]
id-slh-dsa-sha2-128s (2.16.840.1.101.3.4.3.20) BIT STRING "SLH-DSA-SHA2-128s" [CSOR],[RFC9814]
id-slh-dsa-sha2-128f (2.16.840.1.101.3.4.3.21) BIT STRING "SLH-DSA-SHA2-128f" [CSOR],[RFC9814]
id-slh-dsa-sha2-192s (2.16.840.1.101.3.4.3.22) BIT STRING "SLH-DSA-SHA2-192s" [CSOR],[RFC9814]
id-slh-dsa-sha2-192f (2.16.840.1.101.3.4.3.23) BIT STRING "SLH-DSA-SHA2-192f" [CSOR],[RFC9814]
id-slh-dsa-sha2-256s (2.16.840.1.101.3.4.3.24) BIT STRING "SLH-DSA-SHA2-256s" [CSOR],[RFC9814]
id-slh-dsa-sha2-256f (2.16.840.1.101.3.4.3.25) BIT STRING "SLH-DSA-SHA2-256f" [CSOR],[RFC9814]
id-slh-dsa-shake-128s (2.16.840.1.101.3.4.3.26) BIT STRING "SLH-DSA-SHAKE-128s" [CSOR],[RFC9814]
id-slh-dsa-shake-128f (2.16.840.1.101.3.4.3.27) BIT STRING "SLH-DSA-SHAKE-128f" [CSOR],[RFC9814]
id-slh-dsa-shake-192s (2.16.840.1.101.3.4.3.28) BIT STRING "SLH-DSA-SHAKE-192s" [CSOR],[RFC9814]
id-slh-dsa-shake-192f (2.16.840.1.101.3.4.3.29) BIT STRING "SLH-DSA-SHAKE-192f" [CSOR],[RFC9814]
id-slh-dsa-shake-256s (2.16.840.1.101.3.4.3.30) BIT STRING "SLH-DSA-SHAKE-256s" [CSOR],[RFC9814]
id-slh-dsa-shake-256f (2.16.840.1.101.3.4.3.31) BIT STRING "SLH-DSA-SHAKE-256f" [CSOR],[RFC9814]

D. 一致性

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

本文档中的关键词 必须 仅当像此处所示那样全部使用 大写字母时,才应按照 BCP 14 [RFC2119] [RFC8174] 中的描述进行解释。

E. 参考文献

E.1 规范性参考文献

[draft-irtf-cfrg-concrete-hybrid-kems-04]
具体的 混合 PQ/T 密钥封装机制。IETF。2026 年 7 月。URL:https://www.ietf.org/archive/id/draft-irtf-cfrg-concrete-hybrid-kems-04.html
[draft-irtf-cfrg-hybrid-kems-12]
混合 PQ/T 密钥 封装机制。IETF。2026 年 7 月。URL:https://www.ietf.org/archive/id/draft-irtf-cfrg-hybrid-kems-12.html
[FIPS-202]
SHA-3 标准: 基于置换的哈希函数和可扩展输出函数。NIST。2015 年 8 月。URL: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
[FIPS-203]
基于模块格的 密钥封装机制标准。NIST。2024 年 8 月。URL:https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf
[FIPS-204]
基于模块格的 数字签名标准。NIST。2024 年 8 月。URL:https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdf
[FIPS-205]
无状态的基于哈希的 数字签名标准。NIST。2024 年 8 月。URL:https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.205.pdf
[html]
HTML 标准。Anne van Kesteren; Domenic Denicola;Dominic Farolino;Ian Hickson;Philip Jägenstedt;Simon Pieters。WHATWG。现行 标准。URL:https://html.spec.whatwg.org/multipage/
[IANA-JOSE-Algorithms]
IANA JSON Web 签名和加密算法。IANA。URL:https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms
[infra]
Infra 标准。Anne van Kesteren;Domenic Denicola。WHATWG。现行标准。URL:https://infra.spec.whatwg.org/
[JWA]
JSON Web 算法(JWA)。M. Jones。IETF。2015 年 5 月。建议标准。URL:https://www.rfc-editor.org/info/rfc7518/
[JWK]
JSON Web Key(JWK)。M. Jones。 IETF。2015 年 5 月。建议标准。URL:https://www.rfc-editor.org/info/rfc7517/
[NIST-SP800-185]
NIST 特别出版物 800-185:SHA-3 派生函数:cSHAKE、KMAC、TupleHash 和 ParallelHash。NIST。2016 年 12 月。URL:https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf
[RFC2119]
用于 RFC 中表示 要求级别的关键词。S. Bradner。IETF。1997 年 3 月。当前最佳实践。URL:https://www.rfc-editor.org/info/rfc2119/
[RFC5208]
公钥密码标准(PKCS) #8:私钥信息语法规范 1.2 版。B. Kaliski。IETF。 2008 年 5 月。信息性文档。URL:https://www.rfc-editor.org/info/rfc5208/
[RFC5280]
Internet X.509 公钥基础设施 证书和证书吊销列表(CRL)配置文件。D. Cooper;S. Santesson;S. Farrell;S. Boeyen;R. Housley;W. Polk。IETF。2008 年 5 月。建议标准。URL:https://www.rfc-editor.org/info/rfc5280/
[RFC7253]
OCB 认证加密 算法。T. Krovetz;P. Rogaway。IETF。2014 年 5 月。信息性文档。URL:https://www.rfc-editor.org/info/rfc7253/
[RFC8174]
RFC 2119 关键词中大写与小写的歧义。B. Leiba。IETF。2017 年 5 月。当前最佳实践。URL:https://www.rfc-editor.org/info/rfc8174/
[RFC8439]
用于 IETF 协议的 ChaCha20 和 Poly1305。Y. Nir;A. Langley。IETF。2018 年 6 月。信息性文档。URL:https://www.rfc-editor.org/info/rfc8439/
[RFC9106]
用于密码 哈希和工作量证明应用的 Argon2 内存困难函数。A. Biryukov;D. Dinu;D. Khovratovich;S. Josefsson。IETF。2021 年 9 月。信息性文档。URL:https://www.rfc-editor.org/info/rfc9106/
[RFC9861]
KangarooTwelve 和 TurboSHAKE。IETF。2025 年 10 月。URL:https://www.rfc-editor.org/rfc/rfc9861.html
[RFC9964]
用于 JSON 对象签名和 加密(JOSE)及 CBOR 对象签名和加密(COSE)的 ML-DSA。M. Prorock;O. Steele。IETF。2026 年 5 月。建议标准。URL:https://www.rfc-editor.org/info/rfc9964/
[webcrypto]
Web Cryptography 第 2 级。Daniel Huigens。W3C。2025 年 4 月 22 日。首个公开工作草案。URL:https://www.w3.org/TR/webcrypto-2/
[WebIDL]
Web IDL 标准。Edgar Chen;Timothy Gu。 WHATWG。现行标准。URL:https://webidl.spec.whatwg.org/

E.2 资料性参考文献

[CSOR]
计算机 安全对象注册表。NIST。URL:https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration
[draft-ietf-hpke-hpke]
混合公钥 加密。IETF。URL:https://datatracker.ietf.org/doc/draft-ietf-hpke-hpke/
[draft-ietf-hpke-pq]
用于 HPKE 的后量子混合密钥 封装机制。IETF。URL:https://datatracker.ietf.org/doc/draft-ietf-hpke-pq/
[draft-ietf-jose-hpke-pq-pqt]
JOSE HPKE PQ 和 PQ/T 算法注册。IETF。URL:https://datatracker.ietf.org/doc/draft-ietf-jose-hpke-pq-pqt/
[RFC9814]
在 密码消息语法(CMS)中使用 SLH-DSA 签名算法。R. Housley;S. Fluhrer;P. Kampanakis;B. Westerbaan。IETF。2025 年 7 月。建议标准。URL:https://www.rfc-editor.org/info/rfc9814/
[RFC9881]
Internet X.509 公钥基础设施 — 基于模块格的数字签名算法 (ML-DSA)的算法标识符。J. Massimo;P. Kampanakis;S. Turner;B. E. Westerbaan。IETF。2025 年 10 月 。建议标准。URL:https://www.rfc-editor.org/info/rfc9881/
[RFC9935]
Internet X.509 公钥基础设施 - 基于模块格的密钥封装机制 (ML-KEM)的算法标识符。S. Turner;P. Kampanakis;J. Massimo;B. E. Westerbaan。IETF。2026 年 3 月 。建议标准。URL:https://www.rfc-editor.org/info/rfc9935/
[webcrypto-secure-curves]
Web Cryptography API 中的安全曲线。W3C。社区组报告草案。URL:https://wicg.github.io/webcrypto-secure-curves/