跳到主要内容

6. 内容密钥分发方法

  1. 内容密钥分发方法

[RFC9052] 的第 8.5 节包含了内容密钥分发方法 (content key distribution methods) 的通用说明. 本文档定义了若干内容密钥分发方法的 标识符和用法.

6.1. 直接加密

直接加密算法在 [RFC9052] 的第 8.5.1 节中定义. 该节详细说明了如何填充 COSE_Recipient 结构.

6.1.1. 直接密钥

这个接收方算法 (recipient algorithm) 是最简单的算法; 被标识的密钥会直接 用作消息中下一层的密钥. 此算法没有定义任何算法参数. 算法标识符值在 Table 11 中分配.

使用此算法时, "protected" 字段 MUST 为零长度. 密钥类型 MUST 为 "Symmetric".

  +========+=======+============================================+
| Name | Value | Description |
+========+=======+============================================+
| direct | -6 | Direct use of content encryption key (CEK) |
+--------+-------+--------------------------------------------+

Table 11: 直接密钥

6.1.1.1. 直接密钥的安全考虑

此接收方算法有若干潜在问题需要考虑:

  • 这些密钥需要有某种方法随时间定期更新. 本文档中规定的所有内容加密算法 都限制了一个密钥在不显著降低安全性的情况下可使用的次数.

  • 这些密钥需要专用于单一算法. 随着时间推移, 人们已经提出了多种针对同一 密钥被用于多个不同算法时的攻击. 一个例子是将同一密钥同时用于 CBC 加密模式和 CBC-MAC 认证模式.

  • 破解一条消息就意味着所有消息都被破解. 如果对手成功确定了一条消息的密钥, 则所有消息的密钥也被确定.

6.1.2. 带 KDF 的直接密钥

这些接收方算法取得双方之间的公共共享秘密, 并应用 HKDF 函数 (Section 5.1), 使用 Section 5.2 中定义的上下文结构将共享秘密转换为 CEK. "protected" 字段可以为非零长度. HKDF 的 "salt" 参数 (Table 9) 或上下文结构的 "PartyU nonce" 参数 (Table 10) 二者之一 MUST 存在 (如果需要也可以二者 都存在). "salt"/"nonce" 参数中的值可以随机生成, 也可以确定性生成. 要求是 对于相关共享秘密, 该值必须是唯一值.

如果 salt/nonce 值随机生成, 则建议随机值长度与 HKDF 底层哈希函数输出长度 相同. 虽然无法保证它一定唯一, 但它具有很高的唯一概率. 如果 salt/nonce 值 确定性生成, 则可以保证唯一, 因此没有长度要求.

如果使用同一密钥, 则每条消息都必须使用新的 IV. IV 可以按可预测方式, 随机 方式或不可预测方式修改 (例如, 加密计数器).

用于某个密钥的 IV 也可以使用生成该密钥时所用的同一 HKDF 功能来生成. 如果 使用 HKDF 生成 IV, 则算法标识符设置为 34 ("IV-GENERATION").

本文档中定义的算法集合见 Table 12.

+=====================+=======+==============+=====================+ | Name | Value | KDF | Description | +=====================+=======+==============+=====================+ | direct+HKDF-SHA-256 | -10 | HKDF SHA-256 | Shared secret w/ | | | | | HKDF and SHA-256 | +---------------------+-------+--------------+---------------------+ | direct+HKDF-SHA-512 | -11 | HKDF SHA-512 | Shared secret w/ | | | | | HKDF and SHA-512 | +---------------------+-------+--------------+---------------------+ | direct+HKDF-AES-128 | -12 | HKDF AES- | Shared secret w/ | | | | MAC-128 | AES-MAC 128-bit key | +---------------------+-------+--------------+---------------------+ | direct+HKDF-AES-256 | -13 | HKDF AES- | Shared secret w/ | | | | MAC-256 | AES-MAC 256-bit key | +---------------------+-------+--------------+---------------------+

                  Table 12: 带 KDF 的直接密钥

对此算法使用 COSE 密钥时, 执行以下检查:

  • "kty" 字段 MUST 存在, 且 MUST 为 "Symmetric".

  • 如果 "alg" 字段存在, 它 MUST 与正在使用的算法匹配.

  • 如果 "key_ops" 字段存在, 它 MUST 包含 "derive key" 或 "derive bits".

6.1.2.1. 带 KDF 的直接密钥的安全考虑

共享秘密需要有某种方法随时间定期更新. 共享秘密构成信任基础. 尽管它不被 直接使用, 仍应进行计划内轮换.

这些方法不提供完美前向保密 (perfect forward secrecy), 因为同一共享秘密 会用于生成所有密钥; 但是, 如果任何单条消息的密钥被发现, 只有使用该派生 密钥的消息或一系列消息会受到危害. 新的密钥派生步骤将生成一个新密钥, 获取 该密钥需要同等工作量.

6.2. 密钥包装

密钥包装 (key wrap) 在 [RFC9052] 的第 8.5.2 节中定义. 该节详细说明了 如何填充 COSE_Recipient 结构.

6.2.1. AES 密钥包装

AES Key Wrap 算法在 [RFC3394] 中定义. 该算法使用 AES 密钥包装一个长度为 64 位倍数的值. 因此, 它可用于包装本文档中定义的任何内容加密算法的密钥. 该算法需要一个固定参数, 即初始值. 该值固定为 [RFC3394] 第 2.2.3.1 节中 指定的值. 没有按每次调用变化的公钥参数. 受保护头部桶 MUST 为空.

密钥可以从密钥结构或接收方结构中获得. 正在加密或解密的实现 MUST 验证密钥 类型, 密钥长度和算法对相关实体而言正确且适当.

对此算法使用 COSE 密钥时, 执行以下检查:

  • "kty" 字段 MUST 存在, 且 MUST 为 "Symmetric".

  • 如果 "alg" 字段存在, 它 MUST 与正在使用的 AES Key Wrap 算法匹配.

  • 如果 "key_ops" 字段存在, 在加密时它 MUST 包含 "encrypt" 或 "wrap key".

  • 如果 "key_ops" 字段存在, 在解密时它 MUST 包含 "decrypt" 或 "unwrap key".

    +========+=======+==========+=============================+ | Name | Value | Key Size | Description | +========+=======+==========+=============================+ | A128KW | -3 | 128 | AES Key Wrap w/ 128-bit key | +--------+-------+----------+-----------------------------+ | A192KW | -4 | 192 | AES Key Wrap w/ 192-bit key | +--------+-------+----------+-----------------------------+ | A256KW | -5 | 256 | AES Key Wrap w/ 256-bit key | +--------+-------+----------+-----------------------------+

            Table 13: AES Key Wrap 算法值

6.2.1.1. AES 密钥包装的安全考虑

共享秘密需要有某种方法随时间定期更新. 共享秘密是信任基础.

6.3. 直接密钥协商

直接密钥协商 (Direct Key Agreement) 在 [RFC9052] 的第 8.5.4 节中定义. 该节详细说明了如何填充 COSE_Recipient 结构.

6.3.1. 直接 ECDH

ECDH 的数学基础可见 [RFC6090]. 在本文档中, 该算法被扩展为可与 [RFC7748] 中定义的两条曲线一起使用.

ECDH 由以下内容参数化:

曲线类型/曲线: 所选择的曲线不仅控制共享秘密的大小, 还控制计算共享秘密的 数学方法. 所选择的曲线还控制曲线上的点如何表示, 以及曲线上的单位点会 发生什么. 在本规范中, 我们允许使用若干不同的曲线. 曲线集合在 Table 18 中定义.

  用于获得计算秘密的数学方法基于所选择的曲线, 而不是基于 ECDH 算法. 因此,
不需要为每条曲线定义一个新算法.

计算秘密到共享秘密: 一旦计算秘密已知, 结果值就需要转换为字节串以运行 KDF. 本文档中定义的所有曲线都使用 x 坐标. 对于曲线 X25519 和 X448, 结果值会直接使用, 因为它是一个已知长度的字节串. 对于 P-256, P-384 和 P-521 曲线, x 坐标会经过 [RFC8017] 中定义的整数到八位字节串原语 (Integer-to-Octet-String primitive, I2OSP) 函数处理, 对 n 使用 Section 2.1 中定义的相同计算.

临时-静态或静态-静态: 密钥协商过程可以在发送方一侧使用静态密钥或临时密钥 执行. 使用临时密钥时, 发送方 MUST 为每次密钥协商操作生成一个新的临时 密钥. 临时密钥放在 "ephemeral key" 参数中, 并且对于所有使用临时密钥的 算法标识符都 MUST 存在. 使用静态密钥时, 发送方 MUST 生成新的随机值, 或创建一个唯一值作为 KDF 输入. 对于所使用的 KDF, 这意味着 HKDF 的 "salt" 参数 (Table 9) 或上下文结构的 "PartyU nonce" 参数 (Table 10) 二者之一 MUST 存在 (如果需要也可以二者都存在). 该参数中的值 MUST 对正在 使用的密钥对唯一. 可以使用一个全局计数器, 为每次 Static-Static 操作递增 并使用所得值. 必须注意以避免复用该计数器值的方式将计数器保存到永久存储. 使用静态密钥时, 应向接收方标识该静态密钥. 可以通过提供密钥 ("static key") 或静态密钥的密钥标识符 ("static key id") 来标识静态 密钥. 这两个头部参数都在 Table 15 中定义.

密钥派生算法: ECDH 密钥协商过程的结果并不提供均匀随机的秘密. 因此, 需要 将其经过 KDF 处理, 以产生可用密钥. 通过 KDF 处理秘密还允许引入上下文 材料: 密钥将如何使用, 以及 Static-Static 密钥协商的一次性材料. 本文档 中定义的所有算法都使用 Section 5.1 中定义的 HKDF 算法之一, 并使用 Section 5.2 中定义的上下文结构.

密钥包装算法: 不使用密钥包装算法. 这在 Table 14 中表示为 "none". 上下文 结构的密钥大小是内容层加密算法的大小.

COSE 没有定义 Ephemeral-Ephemeral 版本. 原因是 COSE 本身不是在线协议, 因而没有一种方法在双方建立临时秘密. 预期做法是, 某个协议为双方建立秘密, 然后为了 COSE 的目的将这些秘密用作 Static-Static; 或者该协议生成共享秘密, 并使用直接加密.

本文档中定义的直接 ECDH 算法集合见 Table 14.

+==========+=======+=========+==================+=====+=============+ |Name | Value | KDF | Ephemeral-Static |Key |Description | | | | | |Wrap | | +==========+=======+=========+==================+=====+=============+ |ECDH-ES + | -25 | HKDF -- | yes |none |ECDH ES w/ | |HKDF-256 | | SHA-256 | | |HKDF -- | | | | | | |generate key | | | | | | |directly | +----------+-------+---------+------------------+-----+-------------+ |ECDH-ES + | -26 | HKDF -- | yes |none |ECDH ES w/ | |HKDF-512 | | SHA-512 | | |HKDF -- | | | | | | |generate key | | | | | | |directly | +----------+-------+---------+------------------+-----+-------------+ |ECDH-SS + | -27 | HKDF -- | no |none |ECDH SS w/ | |HKDF-256 | | SHA-256 | | |HKDF -- | | | | | | |generate key | | | | | | |directly | +----------+-------+---------+------------------+-----+-------------+ |ECDH-SS + | -28 | HKDF -- | no |none |ECDH SS w/ | |HKDF-512 | | SHA-512 | | |HKDF -- | | | | | | |generate key | | | | | | |directly | +----------+-------+---------+------------------+-----+-------------+

                  Table 14: ECDH 算法值

+===========+=======+==========+===================+=============+
| Name | Label | Type | Algorithm | Description |
+===========+=======+==========+===================+=============+
| ephemeral | -1 | COSE_Key | ECDH-ES+HKDF-256, | Ephemeral |
| key | | | ECDH-ES+HKDF-512, | public key |
| | | | ECDH-ES+A128KW, | for the |
| | | | ECDH-ES+A192KW, | sender |
| | | | ECDH-ES+A256KW | |
+-----------+-------+----------+-------------------+-------------+
| static | -2 | COSE_Key | ECDH-SS+HKDF-256, | Static |
| key | | | ECDH-SS+HKDF-512, | public key |
| | | | ECDH-SS+A128KW, | for the |
| | | | ECDH-SS+A192KW, | sender |
| | | | ECDH-SS+A256KW | |
+-----------+-------+----------+-------------------+-------------+
| static | -3 | bstr | ECDH-SS+HKDF-256, | Static |
| key id | | | ECDH-SS+HKDF-512, | public key |
| | | | ECDH-SS+A128KW, | identifier |
| | | | ECDH-SS+A192KW, | for the |
| | | | ECDH-SS+A256KW | sender |
+-----------+-------+----------+-------------------+-------------+

Table 15: ECDH 算法参数

本文档定义这些算法与 P-256, P-384, P-521, X25519 和 X448 曲线一起使用. 实现 MUST 验证密钥类型和曲线正确. 不同曲线受限于不同的密钥类型. 实现 MUST 验证曲线和算法对相关实体而言适当.

对此算法使用 COSE 密钥时, 执行以下检查:

  • "kty" 字段 MUST 存在, 且 MUST 为 "EC2" 或 "OKP".

  • 如果 "alg" 字段存在, 它 MUST 与正在使用的密钥协商算法匹配.

  • 如果 "key_ops" 字段存在, 对于私钥它 MUST 包含 "derive key" 或 "derive bits".

  • 如果 "key_ops" 字段存在, 对于公钥它 MUST 为空.

6.3.1.1. ECDH 的安全考虑

有一种方法可以检查外部实体提供的点是否有效. 对于 "EC2" 密钥格式, 可以通过 检查 x 和 y 值是否构成曲线上的一个点来完成. 对于 "OKP" 格式, 没有简单的 方法执行点验证.

曾经考虑过要求将两个实体的公钥都作为密钥派生过程的一部分提供 (如 [RFC7748] 第 6.1 节中所建议). 没有这样做, 因为 COSE 以存储转发格式使用, 而不是以 在线密钥交换方式使用. 要使这一点成为问题, 要么接收方公钥必须被恶意选择, 要么发送方必须是恶意的. 无论哪种情况, 所有安全性都会随之消失.

当密钥从不受信任状态转为受信任状态时 (无论由终端用户还是由负责对密钥作出 信任声明的实体完成), 建议提供与该公钥关联的私钥持有证明.

6.4. 带密钥包装的密钥协商

带密钥包装的密钥协商 (Key Agreement with Key Wrap) 在 [RFC9052] 的 第 8.5.5 节中定义. 该节详细说明了如何填充 COSE_Recipient 结构.

6.4.1. 带密钥包装的 ECDH

这些算法在 Table 16 中定义.

带密钥协商的 ECDH 使用与 ECDH 相同的头部参数进行参数化; 参见 Section 6.3.1, 但有以下修改:

密钥包装算法: 支持 Section 6.2 中定义的任一密钥包装算法. 密钥包装算法所用 密钥的大小会输入到 KDF 中. 标识符集合见 Table 16.

+=========+=====+=========+==================+========+=============+ |Name |Value| KDF | Ephemeral-Static |Key Wrap|Description | +=========+=====+=========+==================+========+=============+ |ECDH-ES +|-29 | HKDF -- | yes |A128KW |ECDH ES w/ | |A128KW | | SHA-256 | | |HKDF and AES | | | | | | |Key Wrap w/ | | | | | | |128-bit key | +---------+-----+---------+------------------+--------+-------------+ |ECDH-ES +|-30 | HKDF -- | yes |A192KW |ECDH ES w/ | |A192KW | | SHA-256 | | |HKDF and AES | | | | | | |Key Wrap w/ | | | | | | |192-bit key | +---------+-----+---------+------------------+--------+-------------+ |ECDH-ES +|-31 | HKDF -- | yes |A256KW |ECDH ES w/ | |A256KW | | SHA-256 | | |HKDF and AES | | | | | | |Key Wrap w/ | | | | | | |256-bit key | +---------+-----+---------+------------------+--------+-------------+ |ECDH-SS +|-32 | HKDF -- | no |A128KW |ECDH SS w/ | |A128KW | | SHA-256 | | |HKDF and AES | | | | | | |Key Wrap w/ | | | | | | |128-bit key | +---------+-----+---------+------------------+--------+-------------+ |ECDH-SS +|-33 | HKDF -- | no |A192KW |ECDH SS w/ | |A192KW | | SHA-256 | | |HKDF and AES | | | | | | |Key Wrap w/ | | | | | | |192-bit key | +---------+-----+---------+------------------+--------+-------------+ |ECDH-SS +|-34 | HKDF -- | no |A256KW |ECDH SS w/ | |A256KW | | SHA-256 | | |HKDF and AES | | | | | | |Key Wrap w/ | | | | | | |256-bit key | +---------+-----+---------+------------------+--------+-------------+

           Table 16: 带密钥包装的 ECDH 算法值

对此算法使用 COSE 密钥时, 执行以下检查:

  • "kty" 字段 MUST 存在, 且 MUST 为 "EC2" 或 "OKP".

  • 如果 "alg" 字段存在, 它 MUST 与正在使用的密钥协商算法匹配.

  • 如果 "key_ops" 字段存在, 对于私钥它 MUST 包含 "derive key" 或 "derive bits".

  • 如果 "key_ops" 字段存在, 对于公钥它 MUST 为空.