| RFC 9052 | COSE 结构 | 2022 年 8 月 |
| Schaad | 标准跟踪 | [页] |
简明二进制对象表示(CBOR)是一种为小代码量和小消息量而设计的数据格式。需要能够为这种数据 格式定义基本的安全服务。本文档定义了 CBOR 对象签名与加密(COSE)协议。本规范 描述了如何使用 CBOR 进行序列化来创建和处理签名、消息认证码和加密。本规范还 描述了如何使用 CBOR 表示加密密钥。¶
本文档与 RFC 9053 一起废止 RFC 8152。¶
这是一份互联网标准跟踪文档。¶
本文档是互联网工程任务组(IETF)的产物。它代表了 IETF 社群的共识。它已经 接受公开审查,并已由互联网工程指导组(IESG)批准发布。关于 互联网标准的更多信息可参见 RFC 7841 第 2 节。¶
有关本文档当前状态、任何勘误以及如何提供反馈的信息,可在 https://www.rfc-editor.org/info/rfc9052 获取。¶
Copyright (c) 2022 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
组成物联网(IoT)的小型受限设备受到了越来越多的关注。 这一过程中产生的标准之一是“简明二进制对象表示(CBOR)”[STD94]。CBOR 扩展了 JavaScript 对象表示法(JSON)[STD90] 的数据模型,允许使用二进制数据,以及其他一些变化。CBOR 已被若干处理 IoT 世界的 IETF 工作组采纳,作为它们编码数据结构的方法。CBOR 的设计目标 专门是在传输消息和实现规模两方面都保持小巧,并具备无模式解码器。存在为 IoT 提供消息安全服务的需求,而使用 CBOR 作为消息编码格式是合理的。¶
JOSE 工作组产出了一组文档 [RFC7515] [RFC7516] [RFC7517] [RFC7518],规定了如何使用 JSON 处理加密、签名和 消息认证码(MAC)操作,以及如何编码密钥。本文档定义了 CBOR 对象签名与加密(COSE)标准,它为 CBOR 编码 格式完成同样的工作。本文档与 [RFC9053] 结合使用, 后者提供了一组初始算法。虽然强烈尝试保留原始 JSON 对象签名与加密(JOSE)文档的风格,但考虑了 两个因素:¶
本文档包含:¶
本文档不包含使用具体加密算法的规则和过程。 有关具体算法的详细信息可见 [RFC9053] 和 [RFC8230]。 预计其他算法的细节将在未来文档中定义。¶
COSE 最初是作为一种为受限 RESTful 环境(CoRE)提供安全性的解决方案的一部分而设计的,这通过 [RFC8613] 和 [CORE-GROUPCOMM] 实现。 但是,COSE 并不限于这些情形,并且可以用于任何会考虑 JOSE 或加密消息语法(CMS)[RFC5652] 来提供安全服务的地方。 COSE 与 JOSE 和 CMS 一样,仅用于存储转发或离线协议。 在需要加密的在线协议中使用 COSE,要求在来回发送对象之前 完成一个在线密钥建立过程。任何将 COSE 用于安全服务的应用 首先需要确定所需的安全服务,然后基于这些需求选择适当的 COSE 结构和加密算法。 第 10 节提供了关于 应用在使用 COSE 时需要规定哪些内容的额外信息。¶
CMS 中存在而本标准中不存在的一项特性是摘要结构。 这种省略是有意的。 让各协议自行定义该结构更好,因为不同协议希望把 不同的字段集作为结构的一部分。 虽然算法标识符和摘要值将对所有应用通用,但这两个 值并不总是相邻,因为算法可以定义一次并带有多个值。 应用还可能希望把额外数据字段定义为该结构的一部分。 一个这样的应用特定元素,是包含 URI 或其他指针,以指出 可从何处获取正在被哈希的数据。 [RFC9054] 包含一种这样的可能结构,并 定义了一组摘要算法。¶
在将 COSE 推进为互联网标准的过程中,人们注意到 对 COSE_Sign1 结构中会签安全属性的描述是不正确的。 由于所描述的安全属性——真正会签的那些属性——正是 工作组所期望的属性,因此决定从本文档中移除所有会签文本, 并创建新文档 [COSE-COUNTERSIGN],以弃用旧的会签算法 和头部参数,并定义具有所需安全属性的新算法和头部参数。¶
本文档中的关键词 “MUST”、“MUST NOT”、 “REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“NOT RECOMMENDED”、“MAY” 和 “OPTIONAL”,只有在如这里所示全部以大写形式出现时, 才应按 BCP 14 [RFC2119] [RFC8174] 中所述进行解释。¶
最初编写 COSE 时,简明数据定义 语言(CDDL)[RFC8610] 尚未作为 RFC 发布,因此不能用作数据描述 语言来规范性地描述 COSE 所采用的 CBOR 数据结构。 因此,这里定义的 CBOR 数据对象以散文形式描述。 下文所述的 CDDL 子集还提供了 COSE 数据对象的额外(非规范性)描述。¶
本文档的开发方式是先处理语法,然后开发与之配套的散文描述。 这种做法的一个产物是,散文使用了 简明数据定义语言(CDDL)[RFC8610] 定义的原始类型字符串。 本规范中使用以下原始类型:¶
本文档中出现了三种 CDDL 语法作为简写。它们是:¶
本文档还使用了 CDDL 定义的两种约束。它们是:¶
除散文描述外,还以前述 CDDL 子集给出了 CBOR 数据结构的语法。 CDDL 语法是资料性的;散文描述是规范性的。¶
可通过下面的 XPath 表达式从本文档的 XML 版本中 提取收集到的 CDDL。(取决于所使用的 XPath 求值器,可能 需要将 > 作为实体处理。)¶
//sourcecode[@type='cddl']/text()¶
CDDL 期望初始非终结符符号是 文件中的第一个符号。因此,第一个 CDDL 片段在此给出。¶
start = COSE_Messages / COSE_Key / COSE_KeySet / Internal_Types ; This is defined to make the tool quieter: Internal_Types = Sig_structure / Enc_structure / MAC_structure¶
非终结符 Internal_Types 是为处理在编写本文档期间 使用的自动化验证工具而定义的。它引用那些 用于安全计算但不为传输而发出的非终结符。¶
在 JSON 中,映射被称为对象,并且只有一种映射键: 文本字符串。在 COSE 中,我们使用文本字符串、负整数和无符号整数作为映射键。 整数用于实现编码紧凑性和易于比较。包含文本字符串也允许使用 额外范围的短编码值。由于 “key” 这个词主要用于它的另一种含义,即 加密密钥,因此我们使用术语 “label” 来表示其作为映射键的这种用法。¶
在本规范定义的 CBOR 映射中,如果存在既不是文本字符串 也不是整数的标签,则为错误。 应用可以使处理失败,或者通过忽略不正确标签来处理消息; 但是,它们MUST NOT 创建带有不正确标签的消息。¶
一个 CDDL 语法片段定义了非终结符 “label”, 如上一段所述,以及 “values”,它允许使用任何值。¶
label = int / tstr values = any¶
本文档中,我们使用以下术语:¶
“Context” 在整个文档中用于表示不属于 COSE 消息的信息。 属于上下文的信息可以来自若干不同来源,包括 协议交互、关联的密钥结构和程序配置。 要使用的上下文可以是隐式的,可以使用 [RFC8613] 中定义的 “kid context” 头部参数标识, 也可以由协议特定标识符标识。 上下文通常应包含在加密构造中;更多细节见 第 4.3 节。¶
术语 “byte string” 用于字节序列,而术语 “text string” 用于字符序列。¶
COSE 对象结构的设计使得在解析和处理 不同类型安全消息时可以存在大量通用代码。 所有消息结构都构建在 CBOR 数组类型之上。 数组的前三个元素始终包含相同的信息:¶
此后的元素依赖于具体的消息类型。¶
COSE 消息使用层的概念来构建,以分离不同类型的 加密概念。作为其工作方式的示例,考虑 COSE_Encrypt 消息(第 5.1 节)。这种消息类型分解为两层: 内容层和接收方层。内容层包含加密后的明文和 关于加密消息的信息。接收方层为每个接收方包含 加密后的内容加密密钥(CEK)以及关于其如何被加密的信息。 对于 CEK 预共享的情况,提供了加密消息的单层版本 COSE_Encrypt0(第 5.2 节)。¶
识别已呈现哪种类型的消息,可通过以下 方法完成:¶
| CBOR 标签 | cose-type | 数据项 | 语义 |
|---|---|---|---|
| 98 | cose-sign | COSE_Sign | COSE 签名数据对象 |
| 18 | cose-sign1 | COSE_Sign1 | COSE 单一签名者数据对象 |
| 96 | cose-encrypt | COSE_Encrypt | COSE 加密数据对象 |
| 16 | cose-encrypt0 | COSE_Encrypt0 | COSE 单一接收方加密数据对象 |
| 97 | cose-mac | COSE_Mac | COSE MACed 数据对象 |
| 17 | cose-mac0 | COSE_Mac0 | COSE 无接收方 MAC 对象 |
| 媒体类型 | 编码 | ID | 参考文献 |
|---|---|---|---|
| application/cose; cose-type="cose-sign" | 98 | RFC 9052 | |
| application/cose; cose-type="cose-sign1" | 18 | RFC 9052 | |
| application/cose; cose-type="cose-encrypt" | 96 | RFC 9052 | |
| application/cose; cose-type="cose-encrypt0" | 16 | RFC 9052 | |
| application/cose; cose-type="cose-mac" | 97 | RFC 9052 | |
| application/cose; cose-type="cose-mac0" | 17 | RFC 9052 | |
| application/cose-key | 101 | RFC 9052 | |
| application/cose-key-set | 102 | RFC 9052 |
下面的 CDDL 片段标识了本文档中定义的所有顶层消息。 为消息的带标签版本和无标签版本分别定义了非终结符。¶
COSE_Messages = COSE_Untagged_Message / COSE_Tagged_Message
COSE_Untagged_Message = COSE_Sign / COSE_Sign1 /
COSE_Encrypt / COSE_Encrypt0 /
COSE_Mac / COSE_Mac0
COSE_Tagged_Message = COSE_Sign_Tagged / COSE_Sign1_Tagged /
COSE_Encrypt_Tagged / COSE_Encrypt0_Tagged /
COSE_Mac_Tagged / COSE_Mac0_Tagged
¶
COSE 的结构被设计为具有两个信息桶,这些信息不 被视为负载本身的一部分,但用于保存关于内容、 算法、密钥或用于该层处理的评估提示的信息。这两个桶可 用于除密钥以外的所有结构。虽然这些桶存在,但它们并不总是 在所有实例中都可用。例如,尽管受保护桶被定义为接收方 结构的一部分,但用于接收方结构的一些算法并不提供认证数据。 如果是这种情况,受保护桶会留空。¶
两个桶都实现为 CBOR 映射。映射键是 “label”(第 1.5 节)。值部分取决于 label 的定义。两个 映射使用同一组 label/value 对。标签的整数值和文本字符串值 已被划分为若干区段,包括标准范围、私有使用范围以及 依赖于所选算法的范围。已定义的标签可见于 “COSE Header Parameters” IANA 注册表(第 11.1 节)。¶
这两个桶是:¶
包含关于当前层的、受加密保护的参数。 如果不会将此桶包含在 加密计算中,则该桶MUST 为空。 此桶在消息中被编码为二进制对象。 该值通过对受保护映射进行 CBOR 编码并将其包裹在 bstr 对象中获得。 发送方SHOULD 将零长度映射编码为零长度字节字符串, 而不是编码为零长度映射(编码为 h'a0')。 首选零长度字节字符串编码,因为它更短,并且也是 加密计算的序列化结构中使用的版本。 接收方MUST 接受零长度字节字符串以及 编码在字节字符串中的零长度映射。¶
用字节字符串包裹编码,使受保护映射在传输中有更大机会 不会被意外更改。 (行为不良的中间方可能会解码并重新编码,但这会导致验证失败, 除非重新编码的字节字符串与解码后的字节字符串完全相同。) 这避免了所有各方都需要能够对映射执行共同规范编码 以作为加密操作输入的问题。¶
只应把处理当前层的头部参数放置在该层。举例来说, “content type” 头部参数描述消息中承载的消息内容。 因此,这个头部参数只放置在内容层中,不放置在 接收方层或签名层中。原则上,应能够处理任何给定层而 无需引用其他任何层。除 COSE_Sign 结构外,唯一需要 跨层传递的数据是加密密钥。¶
这些桶存在于本文档定义的所有安全对象中。字段按顺序为 “protected” 桶(作为 CBOR “bstr” 类型),然后是 “unprotected” 桶 (作为 CBOR “map” 类型)。两个桶都必须存在。进入这些桶的 头部参数来自 IANA “COSE Header Parameters” 注册表(第 11.1 节)。 下一节定义了一些头部参数。¶
每个映射中的标签MUST 唯一。处理 消息时,如果一个标签出现多次,该消息MUST 作为 格式错误被拒绝。应用SHOULD 验证同一标签不会 同时出现在受保护和不受保护头部参数中。如果 该消息未作为格式错误被拒绝,则属性MUST 从受保护桶取得,只有在受保护桶中找不到某属性时, 才能从不受保护桶取得该属性。¶
下面的 CDDL 片段表示两个头部参数桶。CDDL 中定义了一个 组 “Headers”,表示放置属性的两个桶。该组用于在所有位置 一致地提供这两个字段。还定义了一个类型,用于表示 通用头部参数的映射。¶
Headers = (
protected : empty_or_serialized_map,
unprotected : header_map
)
header_map = {
Generic_Headers,
* label => values
}
empty_or_serialized_map = bstr .cbor header_map / bstr .size 0
¶
本节定义一组通用头部参数。这些 头部参数的摘要可见于 表 3。应查阅该表 以确定标签值和值的类型。¶
本节定义的头部参数集合如下:¶
此头部参数用于指示 处理消息的应用需要理解哪些 受保护头部参数。本文档中定义的头部 参数不需要包含在内,因为所有 实现都应理解它们。此外,为了与 遵循 [RFC8152] 并假设所有实现都会理解它的 发送方保持兼容,新实现必须理解该文档定义的 “counter signature” 头部参数(标签 7)。当存在时,“crit” 头部 参数MUST 放在 protected-header-parameters 桶中。该数组 MUST 至少有一个值。¶
并非所有头部参数标签都需要包含在 “crit” 头部参数中。 决定哪些头部参数放入数组的规则是:¶
“crit” 指示的头部参数可以由 安全库代码处理,也可以由使用安全库的应用处理;唯一要求 是该头部参数被处理。如果 “crit” 值列表包含一个标签,而 对应头部参数不在 protected-header-parameters 桶中,这就是 处理该消息时的致命错误。¶
此头部参数保存 IV 值的一部分。 使用 COSE_Encrypt0 结构时,IV 的一部分可以是与密钥 关联的上下文的一部分(Context IV),而一部分可以随每条消息 改变(Partial IV)。 此字段用于承载一个值,使 IV 对每条消息发生改变。 Partial IV 可以放在不受保护桶中,因为修改该值会 导致解密产生容易检测为乱码的明文。 “Initialization Vector” 和 “Partial Initialization Vector” 头部参数MUST NOT 同时出现在同一安全层中。¶
消息 IV 通过以下步骤生成:¶
| 名称 | 标签 | 值类型 | 值注册表 | 描述 |
|---|---|---|---|---|
| alg | 1 | int / tstr | COSE Algorithms 注册表 | 要使用的加密算法 |
| crit | 2 | [+ label] | COSE Header Parameters 注册表 | 需要被理解的关键头部 参数 |
| content type | 3 | tstr / uint | CoAP Content-Formats 或 Media Types 注册表 | 负载的内容类型 |
| kid | 4 | bstr | 密钥标识符 | |
| IV | 5 | bstr | 完整初始化向量 | |
| Partial IV | 6 | bstr | 部分初始化向量 |
下面给出了表示本节所定义头部参数集合的 CDDL 片段。每个头部参数都标记为可选,因为它们不 需要出现在每个映射中;特定映射中所需的头部参数在上文讨论。¶
Generic_Headers = (
? 1 => int / tstr, ; algorithm identifier
? 2 => [+label], ; criticality
? 3 => tstr / int, ; content type
? 4 => bstr, ; key identifier
? ( 5 => bstr // ; IV
6 => bstr ) ; Partial IV
)
¶
COSE 支持两种不同的签名结构。COSE_Sign 允许对同一内容应用一个或多个 签名。COSE_Sign1 限定为单一签名者。这些 结构不能相互转换;由于签名计算包含一个用于 标识所使用结构的参数,转换后的结构将无法通过签名验证。¶
COSE_Sign 结构允许对 消息负载应用一个或多个签名。与内容相关的头部参数以及与 签名相关的头部参数会随签名本身一起携带。这些头部参数可以由 签名认证,也可以只是存在。关于 内容的头部参数示例是内容类型头部参数。关于 签名的头部参数示例则是用于创建签名的算法和密钥。¶
当存在多个签名时,通常会把与给定签名者关联的一个签名验证成功 视为该签名者的签名成功。但是,也有一些应用环境 需要其他规则。采用并非“每个签名者一个有效签名”规则的应用 必须规定这些规则。此外,在简单匹配签名者标识符 不足以确定这些签名是否由同一签名者生成时,应用规范必须 描述如何确定哪些签名由同一签名者生成。支持不同接收方社群 是签名者选择包含多个签名的主要原因。¶
例如,COSE_Sign 结构可能包含使用 Edwards 曲线 数字签名算法(EdDSA)[RFC8032] 和椭圆曲线数字签名算法(ECDSA)[DSS] 生成的签名。这允许接收方验证 与其中一种算法关联的签名。关于多个签名评估的更多详细信息可见 [RFC5752]。¶
签名结构可以编码为带标签或无标签,具体取决于 其使用上下文。带标签的 COSE_Sign 结构由 CBOR 标签 98 标识。表示这一点的 CDDL 片段为:¶
COSE_Sign_Tagged = #6.98(COSE_Sign)¶
COSE 签名消息分为两个部分定义。携带 主体和消息相关信息的 CBOR 对象称为 COSE_Sign 结构。携带 签名以及签名相关信息的 CBOR 对象称为 COSE_Signature 结构。COSE 签名消息示例可见 附录 C.1。¶
COSE_Sign 结构是一个 CBOR 数组。数组字段按顺序 为:¶
此字段包含要签名的序列化内容。 如果消息中不存在负载,则要求应用单独提供 负载。 负载被包裹在 bstr 中,以确保其传输时不发生改变。 如果负载被单独传输(“分离内容”),则会在此位置放置一个 nil CBOR 对象, 并由应用负责确保其传输时不发生改变。¶
注:使用带消息恢复算法的签名时(第 8.1 节),可恢复的最大字节数是 原始负载的长度。 编码负载的大小会按将要恢复的字节数减少。 如果原始负载的所有字节都被消耗,则传输的负载 编码为零长度字节字符串,而不是作为不存在处理。¶
表示上述 COSE_Sign 文本的 CDDL 片段如下。¶
COSE_Sign = [
Headers,
payload : bstr / nil,
signatures : [+ COSE_Signature]
]
¶
COSE_Signature 结构是一个 CBOR 数组。数组字段 按顺序为:¶
表示上述 COSE_Signature 文本的 CDDL 片段 如下。¶
COSE_Signature = [
Headers,
signature : bstr
]
¶
当只有一个签名要放置到 消息上时,使用 COSE_Sign1 签名结构。处理内容和签名的头部参数被放在 同一对桶中,而不是像 COSE_Sign 那样分离。¶
该结构可以根据其使用上下文编码为带标签或无标签。 带标签的 COSE_Sign1 结构由 CBOR 标签 18 标识。表示这一点的 CDDL 片段为:¶
COSE_Sign1_Tagged = #6.18(COSE_Sign1)¶
携带主体、签名以及 主体和签名相关信息的 CBOR 对象称为 COSE_Sign1 结构。COSE_Sign1 消息示例可见 附录 C.2。¶
COSE_Sign1 结构是一个 CBOR 数组。数组字段按顺序 为:¶
表示上述 COSE_Sign1 文本的 CDDL 片段如下。¶
COSE_Sign1 = [
Headers,
payload : bstr / nil,
signature : bstr
]
¶
COSE 提供的一项特性是,应用能够提供需要被认证但 不作为 COSE 对象一部分携带的额外数据。 支持这一点的主要原因可通过查看 CoAP 消息结构 [RFC7252] 看出,其中存在 在负载之前携带选项的机制。 可放置在此位置的数据示例包括 CoAP 代码或 CoAP 选项。 如果数据位于 CoAP 消息的头部中,则代理可使用这些数据来帮助 执行代理操作。 例如,代理可以使用 Accept 选项来确定 代理缓存中是否存在合适的值。 发送方可以使用 additional-data 功能来检测 代理或攻击者对 Accept 值集合所做的任何更改。通过 将该字段包含在外部提供的数据中,任何后续 修改都会导致服务器处理消息时 失败。¶
本文档描述了使用外部提供的认证数据字节数组的过程; 构造该字节数组的方法是应用的函数。 使用此特性的应用需要定义如何构造外部提供的认证数据。 这种构造需要考虑以下问题:¶
为了创建签名,需要一个定义良好的字节字符串。 Sig_structure 用于创建规范形式。 此签名与验证过程接收主体信息(COSE_Sign 或 COSE_Sign1)、 签名者信息(COSE_Signature)以及应用数据(外部来源)。 Sig_structure 是一个 CBOR 数组。 Sig_structure 的字段按顺序为:¶
一个用于标识签名上下文的上下文文本字符串。上下文文本字符串 是:¶
描述上述文本的 CDDL 片段为:¶
Sig_structure = [
context : "Signature" / "Signature1",
body_protected : empty_or_serialized_map,
? sign_protected : empty_or_serialized_map,
external_aad : bstr,
payload : bstr
]
¶
如何计算签名:¶
验证签名的步骤为:¶
除执行签名验证外,应用还会执行适当检查,以确保密钥与签名身份 正确配对,并确保签名身份在执行操作之前已获得授权。¶
COSE 支持两种不同的加密结构。 当不需要接收方结构,因为要使用的密钥已隐式 知晓时,使用 COSE_Encrypt0。 其他时候使用 COSE_Encrypt。 这包括存在多个接收方,或使用直接 (即预共享秘密)以外的接收方算法的情况。¶
封装结构允许消息有一个或多个接收方。消息中 可携带关于内容的头部参数以及关于接收方 信息的头部参数。与内容关联的受保护头部参数由 内容加密算法认证。与接收方关联的受保护头部参数 (当算法支持时)由接收方算法认证。关于内容的 头部参数示例包括内容类型和内容加密算法。关于接收方的 头部参数示例包括接收方的密钥标识符和接收方的加密算法。¶
加密明文和加密密钥使用相同技术以及几乎相同的结构。 这不同于“加密消息语法(CMS)”[RFC5652] 和 “JSON Web Encryption(JWE)” [RFC7516] 所采用的方法,后者为 内容层和接收方层使用不同结构。 定义了两个结构:COSE_Encrypt 用于保存加密内容,COSE_recipient 用于 保存接收方的加密密钥。 封装消息示例可见 附录 C.3。¶
COSE_Encrypt 结构可以根据其使用上下文编码为带标签或无标签。 带标签的 COSE_Encrypt 结构由 CBOR 标签 96 标识。表示这一点的 CDDL 片段为:¶
COSE_Encrypt_Tagged = #6.96(COSE_Encrypt)¶
COSE_Encrypt 结构是一个 CBOR 数组。数组字段按顺序 为:¶
与上述文本对应的 CDDL 片段为:¶
COSE_Encrypt = [
Headers,
ciphertext : bstr / nil,
recipients : [+COSE_recipient]
]
¶
COSE_recipient 结构是一个 CBOR 数组。数组字段 按顺序为:¶
与上述 COSE_recipient 文本对应的 CDDL 片段为:¶
COSE_recipient = [
Headers,
ciphertext : bstr / nil,
? recipients : [+COSE_recipient]
]
¶
COSE_Encrypt0 加密结构无法指定 消息接收方。该结构假定对象的接收方已经 知道为解密消息要使用的密钥的身份。如果需要向 接收方标识密钥,则应使用封装结构。¶
COSE_Encrypt0 结构可以根据其使用上下文编码为带标签或无标签。 带标签的 COSE_Encrypt0 结构由 CBOR 标签 16 标识。表示这一点的 CDDL 片段为:¶
COSE_Encrypt0_Tagged = #6.16(COSE_Encrypt0)¶
COSE_Encrypt0 结构是一个 CBOR 数组。数组字段 按顺序为:¶
与上述文本对应的 COSE_Encrypt0 CDDL 片段为:¶
COSE_Encrypt0 = [
Headers,
ciphertext : bstr / nil,
]
¶
AEAD 算法的加密算法相当简单。第一步 是为认证数据结构创建一致的字节字符串。为此,我们 使用 Enc_structure。Enc_structure 是一个 CBOR 数组。Enc_structure 的字段 按顺序为:¶
一个用于标识认证 数据结构上下文的上下文文本字符串。上下文文本字符串为:¶
描述上述文本的 CDDL 片段为:¶
Enc_structure = [
context : "Encrypt" / "Encrypt0" / "Enc_Recipient" /
"Mac_Recipient" / "Rec_Recipient",
protected : empty_or_serialized_map,
external_aad : bstr
]
¶
如何加密消息:¶
确定加密密钥(K)。此步骤取决于 所使用的接收方算法类别。对于:¶
如何解密消息:¶
如何加密消息:¶
确定加密密钥。此步骤取决于 所使用的接收方算法类别。对于:¶
如何解密消息:¶
COSE 支持两种不同的 MAC 结构。 当不需要接收方结构,因为要使用的密钥已隐式 知晓时,使用 COSE_Mac0。 其他所有情况使用 COSE_Mac。 这些情况包括需要多个接收方、密钥未知,或使用 直接以外的接收方算法。¶
本节描述在 COSE 中执行 MAC 认证时要使用的结构和方法。本文档允许使用 与加密所允许的所有相同类别的接收方 算法。¶
MAC 操作可在两种模式下使用。第一种只是检查 内容自计算 MAC 以来未被更改。任何类别的接收方算法都可 用于此目的。第二种模式既检查内容自 计算 MAC 以来未被更改,又使用接收方算法来验证是谁发送了它。支持此模式的接收方 算法类别是使用预共享秘密或执行静态-静态(SS)密钥 协商(不带密钥包装步骤)的那些类别。在这两种情况下,都可以验证 创建并发送消息 MAC 的实体。(这种关于发送方的知识假定 只涉及两方,并且你没有把消息发送给自己。)通过 两种 MAC 消息结构都可以获得起源属性。¶
多接收方 MACed 消息使用两个结构:本节定义的 COSE_Mac 结构用于携带主体,而 COSE_recipient 结构(第 5.1 节)用于保存 MAC 计算所用的密钥。MACed 消息示例可见 附录 C.5。¶
MAC 结构可以根据其使用上下文编码为带标签或无标签。 带标签的 COSE_Mac 结构由 CBOR 标签 97 标识。表示这一点的 CDDL 片段为:¶
COSE_Mac_Tagged = #6.97(COSE_Mac)¶
COSE_Mac 结构是一个 CBOR 数组。数组字段按顺序 为:¶
表示上述 COSE_Mac 文本的 CDDL 片段如下。¶
COSE_Mac = [ Headers, payload : bstr / nil, tag : bstr, recipients : [+COSE_recipient] ]¶
本节描述在接收方已隐式知晓的情况下执行 MAC 认证时要使用的结构和方法。¶
MACed 消息使用本节定义的 COSE_Mac0 结构来 携带主体。带隐式密钥的 MACed 消息示例可见 附录 C.6。¶
MAC 结构可以根据其使用上下文编码为带标签或无标签。 带标签的 COSE_Mac0 结构由 CBOR 标签 17 标识。表示这一点的 CDDL 片段为:¶
COSE_Mac0_Tagged = #6.17(COSE_Mac0)¶
COSE_Mac0 结构是一个 CBOR 数组。数组字段按顺序为:¶
与上述文本对应的 CDDL 片段为:¶
COSE_Mac0 = [ Headers, payload : bstr / nil, tag : bstr, ]¶
为了获得要认证数据的一致编码, 使用 MAC_structure 来创建规范形式。MAC_structure 是一个 CBOR 数组。MAC_structure 的字段 按顺序为:¶
与上述文本对应的 CDDL 片段为:¶
MAC_structure = [
context : "MAC" / "MAC0",
protected : empty_or_serialized_map,
external_aad : bstr,
payload : bstr
]
¶
计算 MAC 的步骤为:¶
验证 MAC 的步骤为:¶
COSE Key 结构构建在 CBOR 映射之上。可 出现在 COSE Key 中的一组通用参数可见于 IANA “COSE Key Common Parameters” 注册表 [COSE.KeyParameters](见 第 11.2 节)。为 特定密钥类型定义的额外参数可见于 IANA “COSE Key Type Parameters” 注册表 [COSE.KeyTypes]。¶
COSE Key Set 使用 CBOR 数组对象作为其底层类型。数组 元素的值是 COSE Key。COSE Key Set MUST 在数组中至少有一个元素。 COSE Key Set 的示例可见 附录 C.7。¶
COSE Key Set 中的每个元素都MUST 独立处理。 如果 COSE Key Set 中的某个元素格式错误,或使用了应用无法理解的密钥, 则忽略该密钥,并正常处理其他密钥。¶
元素 “kty” 是 COSE_Key 映射中的必需元素。¶
描述 COSE_Key 和 COSE_KeySet 的 CDDL 语法为:¶
COSE_Key = {
1 => tstr / int, ; kty
? 2 => bstr, ; kid
? 3 => tstr / int, ; alg
? 4 => [+ (tstr / int) ], ; key_ops
? 5 => bstr, ; Base IV
* label => values
}
COSE_KeySet = [+COSE_Key]
¶
本文档为 COSE Key 对象定义一组通用参数。表 4 提供了本节 定义参数的摘要。也存在为特定密钥类型定义的参数。 密钥类型特定参数可见于 [RFC9053]。¶
| 名称 | 标签 | CBOR 类型 | 值注册表 | 描述 |
|---|---|---|---|---|
| kty | 1 | tstr / int | COSE Key Types | 密钥类型标识 |
| kid | 2 | bstr | 密钥标识值 -- 与消息中的 “kid” 匹配 | |
| alg | 3 | tstr / int | COSE Algorithms | 将密钥使用限制到此 算法 |
| key_ops | 4 | [+ (tstr/int)] | 限制允许操作的集合 | |
| Base IV | 5 | bstr | 要与 Partial IV 异或的 Base IV |
此参数定义为承载 IV 的基础部分。它 设计为与 第 3.1 节 中定义的 Partial IV 头部参数一起使用。 此字段提供将 Base IV 与密钥关联的能力,然后该 Base IV 会按每条消息 通过 Partial IV 进行修改。¶
在应用中使用 Base IV 时需要极其小心。 如果同一 IV 被使用两次,许多加密算法会失去安全性。¶
如果为每个发送方派生不同密钥,则从同一个 Base IV 开始很可能 满足此条件。 如果多个发送方使用同一密钥,则应用需要提供一种方法,在 发送方之间划分 IV 空间。 这可以通过提供不同的基础起点或不同的 起始 Partial IV,并限制重新换密钥前可发送的消息数量来完成。¶
| 名称 | 值 | 描述 |
|---|---|---|
| sign | 1 | 该密钥用于创建签名。 需要私钥字段。 |
| verify | 2 | 该密钥用于验证 签名。 |
| encrypt | 3 | 该密钥用于密钥传输 加密。 |
| decrypt | 4 | 该密钥用于密钥传输 解密。需要私钥字段。 |
| wrap key | 5 | 该密钥用于密钥包装 加密。 |
| unwrap key | 6 | 该密钥用于密钥包装 解密。需要私钥字段。 |
| derive key | 7 | 该密钥用于派生密钥。 需要私钥字段。 |
| derive bits | 8 | 该密钥用于派生不 作为密钥使用的比特。需要私钥字段。 |
| MAC create | 9 | 该密钥用于创建 MAC。 |
| MAC verify | 10 | 该密钥用于验证 MAC。 |
本节列出了可在 COSE 中使用的不同算法类型的分类。 不应认为该分类是穷尽性的。 将会创建无法归入此分类的新算法。¶
签名算法提供数据来源和数据完整性服务。 数据来源提供基于谁签名了数据来推断数据由谁发起的能力。 数据完整性提供验证数据自签名以来未被 修改的能力。¶
有两种通用签名算法方案。 第一种是带附录的签名。 在此方案中,对消息内容进行处理并产生一个签名;该签名称为 附录。 这是 ECDSA 和 RSA 概率签名方案 (RSASSA-PSS)等算法使用的方案。 (事实上,RSASSA-PSS 中的 SSA 代表 Signature Scheme with Appendix。)¶
此方案的签名函数为:¶
signature = Sign(message content, key) valid = Verification(message content, key, signature)¶
第二种方案是带消息恢复的签名;这类算法的一个示例是 [PVSig]。 在此方案中,对消息内容进行处理,但其中一部分会包含在签名中。 将消息内容的字节移入签名允许生成更小的签名消息;签名 大小仍然可能较大,但消息内容已缩小。 这会影响实现这些算法的系统以及使用它们的应用。 第一个影响是,在签名验证完成之前,消息内容不能完全 可用。 在此之前,签名内部包含的那部分消息无法恢复。 第二个影响是,对签名强度的安全分析可能非常 依赖于消息内容的结构。 最后,如果对消息应用多个签名,则所有签名 算法都将需要消耗消息内容中的同一组字节。 这意味着不支持在单个消息中混合使用带消息恢复签名和带附录签名 方案。¶
此方案的签名函数为:¶
signature, message sent = Sign(message content, key) valid, message content = Verification(message sent, key, signature)¶
尚未为 COSE 正式定义任何消息恢复签名算法。鉴于此方案带来的新 约束,虽然已经识别出一些问题,但在集成消息恢复签名 算法时,很可能还会出现其他问题。 第一个定义的算法将需要对这些问题作出决定,而这些 决定很可能会约束任何后续定义的算法。¶
下文使用以下术语:¶
已识别出的一些问题包括:¶
签名算法与 COSE_Signature 和 COSE_Sign1 结构一起使用。 在撰写本文时,仅定义了带附录签名可用于 COSE;但是, 由于可能实现有效的大小缩减,人们已表达出相当大的兴趣, 希望使用带消息恢复的签名算法。¶
消息认证码(MAC)提供数据认证和完整性 保护。它们不提供或仅提供非常有限的数据来源。举例来说,MAC 不能 用于向第三方证明发送方身份。¶
MAC 使用与带附录签名算法相同的方案。消息内容 被处理,并生成认证码。认证码通常称为标签。¶
MAC 函数为:¶
tag = MAC_Create(message content, key) valid = MAC_Verify(message content, key, tag)¶
MAC 算法可以基于分组密码算法(即 AES-MAC),也可以基于哈希算法 (即基于哈希的消息认证码(HMAC))。 [RFC9053] 使用这些 构造分别定义了一个 MAC 算法。¶
MAC 算法用于 COSE_Mac 和 COSE_Mac0 结构。¶
内容加密算法使用对称密钥为可能较大的 数据块提供数据机密性。它们提供对被加密数据的完整性;但是, 它们不提供或仅提供非常有限的数据来源。(例如,不能用它来向 第三方证明发送方的身份。)提供数据来源的能力与 CEK 的获得方式相关。¶
COSE 将合法内容加密算法集合限制为支持 同时认证内容和附加数据的算法。加密过程将生成某种类型 的认证值,但根据算法定义,该值可以是显式的,也可以是隐式的。 为简单起见,认证码通常定义为追加到 密文流。加密函数为:¶
ciphertext = Encrypt(message content, key, additional data) valid, message content = Decrypt(ciphertext, key, additional data)¶
大多数 AEAD 算法在逻辑上定义为仅当 解密有效时才返回消息内容。许多实现(但不是全部)会遵循这一约定。如果解密 未通过验证,则消息内容MUST NOT 被使用。¶
这些算法用于 COSE_Encrypt 和 COSE_Encrypt0。¶
KDF 用于接收某个秘密值并生成另一个值。秘密值 有三种类型:¶
通用 KDF 与第一类秘密配合良好,与第二类秘密配合尚可, 而通常不适合最后一类秘密。Argon2 [RFC9106] 等函数需要用于非随机秘密。¶
同一个 KDF 可以被设置为以不同方式处理前两类秘密。 [RFC9053] 第 5.1 节中定义的 KDF 就是这样一种 函数。 这体现在围绕基于 HMAC 的提取并扩展密钥 派生函数(HKDF)定义的一组算法中。¶
使用 KDF 时,其中包含的一个组成部分是上下文信息。上下文 信息用于允许从同一个秘密派生出不同的密钥信息。使用 基于上下文的密钥材料被认为是一种良好安全实践。¶
内容密钥分发方法(接收方算法)可以定义为若干不同 类别。 COSE 有能力支持许多类别的接收方算法。 本节列出若干类别。对于 [RFC7516] 中定义的接收方算法类别, 使用相同名称。 其他规范对接收方算法类别使用不同术语,或不支持某些 接收方算法类别。¶
直接加密类别的算法在发送方 和接收方之间共享一个秘密,该秘密直接或经处理后作为 CEK 使用。当 使用 direct-encryption 模式时,它MUST 是消息中使用的唯一模式。¶
接收方的 COSE_Recipient 结构组织如下:¶
在密钥包装模式中,CEK 随机生成,然后 该密钥由发送方与接收方之间的共享秘密加密。当前 为 COSE 定义的所有密钥包装算法都是 AE 算法。如果系统有 任何随机密钥生成能力,则密钥包装模式被认为优于 直接加密。这是因为共享密钥用于包装随机数据,而不是包装 具有某种组织程度、且实际上可能重复相同内容的数据。使用 密钥包装会失去由直接加密算法提供的弱数据来源 属性。¶
接收方的 COSE_Recipient 结构组织 如下:¶
密钥传输模式在一些标准中也称为密钥加密模式。 密钥传输模式与密钥包装模式不同,因为它使用非对称加密 算法而不是对称加密算法来保护密钥。 [RFC8230] 定义了一组密钥传输算法。¶
使用密钥传输算法时,接收方的 COSE_Recipient 结构 组织如下:¶
直接密钥协商类别的接收方算法使用密钥协商 方法创建共享秘密。随后将 KDF 应用于共享秘密,以派生用于 保护数据的密钥。该密钥通常用作 CEK 或 MAC 密钥,但如果使用 多于两层,也可以用于其他目的(见 附录 B)。¶
最常用的密钥协商算法是 Diffie-Hellman,但也存在 其他变体。由于 COSE 是为存储转发环境而不是在线 环境设计的,许多 DH 变体不能使用,因为消息接收方不能 提供任何动态密钥材料。其一个副作用是无法实现前向保密 (见 [RFC4949])。COSE 对象的接收方始终会使用 静态密钥。¶
支持的两种 DH 变体为:¶
使用直接密钥协商模式时,消息中MUST 只有一个接收方。此方法直接创建密钥, 因而难以与其他接收方混合。如果需要多个接收方,则需要使用 带密钥包装的版本。¶
接收方的 COSE_Recipient 结构组织如下:¶
带密钥包装的密钥协商使用随机生成的 CEK。随后使用 密钥包装算法以及从密钥协商算法计算出的共享秘密派生出的密钥 对 CEK 加密。其函数为:¶
encryptedKey = KeyWrap(KDF(DH-Shared, context), CEK)¶
接收方的 COSE_Recipient 结构组织 如下:¶
本文档限制其对 CBOR 编码器需要如何工作的 约束。新的编码限制与 RFC 8949 [STD94] 第 4.2.1 节中规定的核心确定性编码要求保持一致。 已缩小到以下限制:¶
本文档旨在提供一组安全服务,但不为 具体用途施加算法实现要求。互操作性要求用于说明 每项单独服务如何使用,以及算法应如何用于 互操作。哪些算法和哪些服务是必需的这些要求,被推迟给 各应用决定。¶
配置文件的一个示例可见 [RFC8613], 其中为结合 CoAP 头部承载内容开发了一个配置文件。¶
预期会创建本文档的一个配置文件,用于定义 该特定应用的互操作性要求。本节提供一组指南 和在为本文档制作配置文件时需要考虑的主题。¶
如果允许多个算法或消息结构, 应用可能需要提供某种类型的协商或发现 方法。该方法可以从简单到要求预配置 算法集合,到提供内置于协议中的发现方法。S/MIME 提供了多种 应用可以遵循的问题处理方式:¶
下列注册表和注册项由 RFC 8152 [RFC8152] 定义。 以下大多数操作用于更新引用,使其指向本文档。¶
注意,虽然 [RFC9053] 也更新了 最初由 [RFC8152] 建立的注册表 和注册项,但所请求的更新互不相同。本文档中请求的更新不会与 [RFC9053] 中请求的更新冲突或重叠,反之亦然。¶
“COSE Header Parameters” 注册表由 [RFC8152] 定义。 IANA 已更新此注册表的引用,使其指向本文档而不是 [RFC8152]。IANA 还更新了所有 引用 [RFC8152] 的条目,除了 “counter signature” 和 “CounterSignature0”,使其引用本文档。“counter signature” 和 “CounterSignature0” 的引用继续引用 [RFC8152]。¶
“COSE Key Common Parameters” 注册表 [COSE.KeyParameters] 定义于 [RFC8152]。 IANA 已更新此注册表的引用,使其指向本文档而不是 [RFC8152]。IANA 还更新了 引用 [RFC8152] 的条目,使其引用 本文档。¶
IANA 已在 “Media Types” 注册表中注册 “application/cose” 媒体类型。此媒体类型用于指示内容是 COSE 消息。¶
IANA 已在 “Media Types” 注册表中注册 “application/cose-key” 和 “application/cose-key-set” 媒体类型。这些媒体类型分别用于 指示内容是 COSE_Key 或 COSE_KeySet 对象。¶
“application/cose-key” 的模板如下:¶
注册 “application/cose-key-set” 的模板为:¶
IANA 已按 [RFC8152] 所示向 “CoAP Content-Formats” 注册表添加条目。IANA 已更新引用, 使其指向本文档而不是 [RFC8152]。¶
IANA 已按 [RFC8152] 所示向 “CBOR Tags” 注册表添加条目。IANA 已更新引用, 使其指向本文档而不是 [RFC8152]。¶
[RFC8152] 建立的所有 IANA 注册表至少部分定义为专家评审 [RFC8126]。本节给出一些通用 指南,说明专家应关注什么,但他们被指定为专家是有原因的, 因而应给予他们相当大的自由裁量权。¶
专家评审员应考虑以下事项:¶
本规范的实现者需要考虑许多安全事项。 虽然这里强调了一些考量,但额外考量可见于 参考文献中列出的文档。¶
实现需要保护所有个体的私钥材料。本文档中的一些 情况需要就此问题特别强调。¶
使用椭圆曲线 Diffie-Hellman(ECDH)以及 direct plus KDF(不带密钥包装) 不会直接导致私钥泄露;KDF 的单向函数会防止 这种情况。但是,另有一个需要解决的问题。存在两个接收方要求 CEK 在两个接收方之间共享。因此,第二个接收方拥有从 可用于弱来源证明的材料派生出的 CEK。第二个接收方可以使用 同一 CEK 创建消息并发送给第一个接收方;对于 Static-Static ECDH 或 direct plus KDF,第一个接收方会假定该 CEK 可用于来源 证明,即使它来自错误实体。如果添加密钥包装步骤,则不会暗示来源证明, 这也就不是问题。¶
虽然前面已经提到,但仍值得重申:在某些情况下,使用单个密钥用于多个 算法已被证明会泄露关于密钥的信息,从而为 攻击者伪造完整性标签或获取加密内容信息提供机会。 将密钥绑定到单个算法可防止这些问题。 强烈鼓励密钥创建者和密钥使用者不仅为每个不同算法创建新密钥, 还应在任何密钥材料分发中包含该算法选择,并严格 强制密钥结构中的算法与消息结构中的算法匹配。 除检查算法是否正确外,还需要检查密钥形式。 不要在预期 “OKP” 密钥的地方使用 “EC2” 密钥。¶
在使用密钥进行传输之前,或在根据收到的信息采取行动之前, 需要对密钥作出信任决策。与该密钥关联的实体是否有权查看 该数据或请求该操作?许多因素与此信任 决策相关。这里强调的一些因素包括:¶
一个受到关注的领域是基于消息长度对加密消息进行流量分析。 本规范没有提供统一方法,将填充作为消息结构的一部分提供。 对于 [RFC9053] 中定义的所有内容加密算法, 观察者都可以基于长度区分两个不同消息(例如 “YES” 和 “NO”)。 这意味着应用需要自行记录如何进行内容填充,以防止或抑制此类 分析。(例如,文本字符串可以定义为 “YES” 和 “NO ”。)¶
在 COSE 开发期间,要求算法标识符位于受保护 属性中的要求从必须放宽为应该。 已提出两个基本理由来支持这一立场。 首先,如果在 CoAP 环境中最常见的消息中省略算法标识符, 则生成的消息会更小。 其次,如果没有在算法标识符可放置的不同位置之间 正确进行完整检查,则可能出现潜在错误(消息本身、应用声明、 发送方拥有的密钥结构,以及接收方拥有的密钥结构)。¶
本附录说明如何进行这种变更,以及应用为了使用此选项 需要规定的细节。 这里规定了两组不同的细节:省略算法标识符所需的细节,以及 使用不包含自身属性的会签属性变体所需的细节。¶
列出了三组建议。第一组建议适用于 为 COSE 对象的单一层标识隐式算法。第二组 建议适用于为 COSE 对象的多层标识多个隐式算法。 第三组建议适用于为多个 COSE 对象构造使用隐式算法。¶
这里刻意不使用 BCP 14([RFC2119] 和 [RFC8174])中的关键词。本 规范可以提供建议,但不能强制执行这些建议。¶
这组建议适用于这样的情况:应用正在随密钥信息一起分发 固定算法,以用于单个 COSE 对象。这通常适用于 最小的 COSE 对象 -- 具体而言,COSE_Sign1、COSE_Mac0 和 COSE_Encrypt0 -- 但也可适用于 其他结构。¶
应考虑以下事项:¶
第二种情况是为多层 COSE 对象指定多个隐式算法 标识符。其工作方式的一个示例是应用指定的加密上下文, 其中包含内容加密算法、密钥包装算法、密钥标识符和 共享秘密。发送方省略发送内容层和 接收方层的算法标识符,只留下密钥标识符。接收方随后使用 密钥标识符获取隐式算法标识符。¶
还需要考虑以下附加事项:¶
第三种情况是存在多个隐式算法标识符,但目标是 可能不相关的层或不同的 COSE 对象。在许多不同场景中这可能适用。 其中一些场景包括:¶
对于这些情况,需要考虑以下附加事项:¶
当前定义的所有接收方算法类别都只使用 COSE 结构的两层。 第一层(COSE_Encrypt)是消息内容,第二层(COSE_Recipient)是 内容密钥加密。 但是,如果使用诸如 RSA 密钥封装机制(RSA-KEM)的接收方算法(见 RSA-KEM [RFC5990] 附录 A),那么使用 两层 COSE_Recipient 结构是合理的。¶
这些层为:¶
这是三层消息外观的一个示例。为了更易阅读, 它使用扩展 CBOR 诊断记法(定义于 [RFC8610])呈现,而不是作为二进制转储呈现。该消息具有以下 层:¶
实际上,此示例是使用 ECDH-ES+A128KW 算法的分解版本。¶
二进制文件大小为 183 字节¶
96(
[ / COSE_Encrypt /
/ protected h'a10101' / << {
/ alg / 1:1 / AES-GCM 128 /
} >>,
/ unprotected / {
/ iv / 5:h'02d1f7e6f26c43d4868d87ce'
},
/ ciphertext / h'64f84d913ba60a76070a9a48f26e97e863e2852948658f0
811139868826e89218a75715b',
/ recipients / [
[ / COSE_Recipient /
/ protected / h'',
/ unprotected / {
/ alg / 1:-3 / A128KW /
},
/ ciphertext / h'dbd43c4e9d719c27c6275c67d628d493f090593db82
18f11',
/ recipients / [
[ / COSE_Recipient /
/ protected h'a1013818' / << {
/ alg / 1:-25 / ECDH-ES + HKDF-256 /
} >> ,
/ unprotected / {
/ ephemeral / -1:{
/ kty / 1:2,
/ crv / -1:1,
/ x / -2:h'b2add44368ea6d641f9ca9af308b4079aeb519f11
e9b8a55a600b21233e86e68',
/ y / -3:false
},
/ kid / 4:'meriadoc.brandybuck@buckland.example'
},
/ ciphertext / h''
]
]
]
]
]
)
¶
本附录包含一组示例,展示本文档中定义的不同特性和消息 类型。为了使示例更易阅读,它们使用扩展 CBOR 诊断记法(定义于 [RFC8610])呈现,而不是作为二进制转储呈现。¶
已在 [GitHub-Examples] 创建一个 GitHub 项目,其中不仅包含本文档中给出的示例, 还包含更完整的一组测试示例。 每个示例都位于一个 JSON 文件中,该文件包含用于创建示例的输入、一些可用于 调试示例的中间值,以及以十六进制转储和 CBOR 诊断记法格式 呈现的示例输出。 该站点上的一些示例被设计为失败测试用例;这些在 JSON 文件中 有明确标记。 如果发现本文档中的示例存在错误,则会更新 GitHub 上的示例,并在 JSON 文件中放置说明此事的注记。¶
如前所述,示例使用 CBOR 的诊断记法呈现。存在一个基于 Ruby 的 工具,可在诊断记法和二进制之间进行转换。可使用 以下命令行安装该工具:¶
gem install cbor-diag¶
可使用以下命令行将诊断记法转换为二进制 文件:¶
diag2cbor.rb < inputfile > outputfile¶
可以通过 XPath 表达式从本文档的 XML 版本中提取示例,因为所有源代码都使用属性 type='cbor-diag' 标记。 (取决于所使用的 XPath 求值器,可能需要将 > 作为实体处理。)¶
//sourcecode[@type='cbor-diag']/text()¶
此示例使用以下内容:¶
二进制文件大小为 103 字节¶
98(
[
/ protected / h'',
/ unprotected / {},
/ payload / 'This is the content.',
/ signatures / [
[
/ protected h'a10126' / << {
/ alg / 1:-7 / ECDSA 256 /
} >>,
/ unprotected / {
/ kid / 4:'11'
},
/ signature / h'e2aeafd40d69d19dfe6e52077c5d7ff4e408282cbefb
5d06cbf414af2e19d982ac45ac98b8544c908b4507de1e90b717c3d34816fe926a2b
98f53afd2fa0f30a'
]
]
]
)
¶
此示例使用以下内容:¶
二进制文件大小为 277 字节¶
98(
[
/ protected / h'',
/ unprotected / {},
/ payload / 'This is the content.',
/ signatures / [
[
/ protected h'a10126' / << {
/ alg / 1:-7 / ECDSA 256 /
} >>,
/ unprotected / {
/ kid / 4:'11'
},
/ signature / h'e2aeafd40d69d19dfe6e52077c5d7ff4e408282cbefb
5d06cbf414af2e19d982ac45ac98b8544c908b4507de1e90b717c3d34816fe926a2b
98f53afd2fa0f30a'
],
[
/ protected h'a1013823' / << {
/ alg / 1:-36 / ECDSA 521 /
} >> ,
/ unprotected / {
/ kid / 4:'bilbo.baggins@hobbiton.example'
},
/ signature / h'00a2d28a7c2bdb1587877420f65adf7d0b9a06635dd1
de64bb62974c863f0b160dd2163734034e6ac003b01e8705524c5c4ca479a952f024
7ee8cb0b4fb7397ba08d009e0c8bf482270cc5771aa143966e5a469a09f613488030
c5b07ec6d722e3835adb5b2d8c44e95ffb13877dd2582866883535de3bb03d01753f
83ab87bb4f7a0297'
]
]
]
)
¶
此示例使用以下内容:¶
二进制文件大小为 125 字节¶
98(
[
/ protected h'a2687265736572766564f40281687265736572766564' /
<< {
"reserved":false,
/ crit / 2:[
"reserved"
]
} >>,
/ unprotected / {},
/ payload / 'This is the content.',
/ signatures / [
[
/ protected h'a10126' / << {
/ alg / 1:-7 / ECDSA 256 /
} >>,
/ unprotected / {
/ kid / 4:'11'
},
/ signature / h'3fc54702aa56e1b2cb20284294c9106a63f91bac658d
69351210a031d8fc7c5ff3e4be39445b1a3e83e1510d1aca2f2e8a7c081c7645042b
18aba9d1fad1bd9c'
]
]
]
)
¶
此示例使用以下内容:¶
二进制文件大小为 98 字节¶
18(
[
/ protected h'a10126' / << {
/ alg / 1:-7 / ECDSA 256 /
} >>,
/ unprotected / {
/ kid / 4:'11'
},
/ payload / 'This is the content.',
/ signature / h'8eb33e4ca31d1c465ab05aac34cc6b23d58fef5c083106c4
d25a91aef0b0117e2af9a291aa32e14ab834dc56ed2a223444547e01f11d3b0916e5
a4c345cacb36'
]
)
¶
此示例使用以下内容:¶
二进制文件大小为 151 字节¶
96(
[
/ protected h'a10101' / << {
/ alg / 1:1 / AES-GCM 128 /
} >>,
/ unprotected / {
/ iv / 5:h'c9cf4df2fe6c632bf7886413'
},
/ ciphertext / h'7adbe2709ca818fb415f1e5df66f4e1a51053ba6d65a1a0
c52a357da7a644b8070a151b0',
/ recipients / [
[
/ protected h'a1013818' / << {
/ alg / 1:-25 / ECDH-ES + HKDF-256 /
} >>,
/ unprotected / {
/ ephemeral / -1:{
/ kty / 1:2,
/ crv / -1:1,
/ x / -2:h'98f50a4ff6c05861c8860d13a638ea56c3f5ad7590bbf
bf054e1c7b4d91d6280',
/ y / -3:true
},
/ kid / 4:'meriadoc.brandybuck@buckland.example'
},
/ ciphertext / h''
]
]
]
)
¶
此示例使用以下内容:¶
二进制文件大小为 91 字节¶
96(
[
/ protected h'a1010a' / << {
/ alg / 1:10 / AES-CCM-16-64-128 /
} >>,
/ unprotected / {
/ iv / 5:h'89f52f65a1c580933b5261a76c'
},
/ ciphertext / h'753548a19b1307084ca7b2056924ed95f2e3b17006dfe93
1b687b847',
/ recipients / [
[
/ protected h'a10129' / << {
/ alg / 1:-10
} >>,
/ unprotected / {
/ salt / -20:'aabbccddeeffgghh',
/ kid / 4:'our-secret'
},
/ ciphertext / h''
]
]
]
)
¶
此示例使用以下内容:¶
二进制文件大小为 173 字节¶
96(
[
/ protected h'a10101' / << {
/ alg / 1:1 / AES-GCM 128 /
} >> ,
/ unprotected / {
/ iv / 5:h'02d1f7e6f26c43d4868d87ce'
},
/ ciphertext / h'64f84d913ba60a76070a9a48f26e97e863e28529d8f5335
e5f0165eee976b4a5f6c6f09d',
/ recipients / [
[
/ protected / h'a101381f' / {
\ alg \ 1:-32 \ ECDH-SS+A128KW \
} / ,
/ unprotected / {
/ static kid / -3:'peregrin.took@tuckborough.example',
/ kid / 4:'meriadoc.brandybuck@buckland.example',
/ U nonce / -22:h'0101'
},
/ ciphertext / h'41e0d76f579dbd0d936a662d54d8582037de2e366fd
e1c62'
]
]
]
)
¶
此示例使用以下内容:¶
二进制文件大小为 52 字节¶
16(
[
/ protected h'a1010a' / << {
/ alg / 1:10 / AES-CCM-16-64-128 /
} >> ,
/ unprotected / {
/ iv / 5:h'89f52f65a1c580933b5261a78c'
},
/ ciphertext / h'5974e1b99a3a4cc09a659aa2e9e7fff161d38ce71cb45ce
460ffb569'
]
)
¶
此示例使用以下内容:¶
二进制文件大小为 41 字节¶
16(
[
/ protected h'a1010a' / << {
/ alg / 1:10 / AES-CCM-16-64-128 /
} >> ,
/ unprotected / {
/ partial iv / 6:h'61a7'
},
/ ciphertext / h'252a8911d465c125b6764739700f0141ed09192de139e05
3bd09abca'
]
)
¶
此示例使用以下内容:¶
二进制文件大小为 57 字节¶
97(
[
/ protected h'a1010f' / << {
/ alg / 1:15 / AES-CBC-MAC-256//64 /
} >> ,
/ unprotected / {},
/ payload / 'This is the content.',
/ tag / h'9e1226ba1f81b848',
/ recipients / [
[
/ protected / h'',
/ unprotected / {
/ alg / 1:-6 / direct /,
/ kid / 4:'our-secret'
},
/ ciphertext / h''
]
]
]
)
¶
此示例使用以下内容:¶
二进制文件大小为 214 字节¶
97(
[
/ protected h'a10105' / << {
/ alg / 1:5 / HMAC 256//256 /
} >> ,
/ unprotected / {},
/ payload / 'This is the content.',
/ tag / h'81a03448acd3d305376eaa11fb3fe416a955be2cbe7ec96f012c99
4bc3f16a41',
/ recipients / [
[
/ protected h'a101381a' / << {
/ alg / 1:-27 / ECDH-SS + HKDF-256 /
} >> ,
/ unprotected / {
/ static kid / -3:'peregrin.took@tuckborough.example',
/ kid / 4:'meriadoc.brandybuck@buckland.example',
/ U nonce / -22:h'4d8553e7e74f3c6a3a9dd3ef286a8195cbf8a23d
19558ccfec7d34b824f42d92bd06bd2c7f0271f0214e141fb779ae2856abf585a583
68b017e7f2a9e5ce4db5'
},
/ ciphertext / h''
]
]
]
)
¶
此示例使用以下内容:¶
二进制文件大小为 109 字节¶
97(
[
/ protected h'a1010e' / << {
/ alg / 1:14 / AES-CBC-MAC-128//64 /
} >> ,
/ unprotected / {},
/ payload / 'This is the content.',
/ tag / h'36f5afaf0bab5d43',
/ recipients / [
[
/ protected / h'',
/ unprotected / {
/ alg / 1:-5 / A256KW /,
/ kid / 4:'018c0ae5-4d9b-471b-bfd6-eef314bc7037'
},
/ ciphertext / h'711ab0dc2fc4585dce27effa6781c8093eba906f227
b6eb0'
]
]
]
)
¶
此示例使用以下内容:¶
二进制文件大小为 309 字节¶
97(
[
/ protected h'a10105' / << {
/ alg / 1:5 / HMAC 256//256 /
} >> ,
/ unprotected / {},
/ payload / 'This is the content.',
/ tag / h'bf48235e809b5c42e995f2b7d5fa13620e7ed834e337f6aa43df16
1e49e9323e',
/ recipients / [
[
/ protected h'a101381c' / << {
/ alg / 1:-29 / ECDH-ES+A128KW /
} >> ,
/ unprotected / {
/ ephemeral / -1:{
/ kty / 1:2,
/ crv / -1:3,
/ x / -2:h'0043b12669acac3fd27898ffba0bcd2e6c366d53bc4db
71f909a759304acfb5e18cdc7ba0b13ff8c7636271a6924b1ac63c02688075b55ef2
d613574e7dc242f79c3',
/ y / -3:true
},
/ kid / 4:'bilbo.baggins@hobbiton.example'
},
/ ciphertext / h'339bc4f79984cdc6b3e6ce5f315a4c7d2b0ac466fce
a69e8c07dfbca5bb1f661bc5f8e0df9e3eff5'
],
[
/ protected / h'',
/ unprotected / {
/ alg / 1:-5 / A256KW /,
/ kid / 4:'018c0ae5-4d9b-471b-bfd6-eef314bc7037'
},
/ ciphertext / h'0b2c7cfce04e98276342d6476a7723c090dfdd15f9a
518e7736549e998370695e6d6a83b4ae507bb'
]
]
]
)
¶
这是 COSE Key Set 的一个示例。此示例包含所有先前示例的 公钥。¶
按顺序,这些密钥为:¶
二进制文件大小为 481 字节¶
[
{
-1:1,
-2:h'65eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c0
8551d',
-3:h'1e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd008
4d19c',
1:2,
2:'meriadoc.brandybuck@buckland.example'
},
{
-1:1,
-2:h'bac5b11cad8f99f9c72b05cf4b9e26d244dc189f745228255a219a86d6a
09eff',
-3:h'20138bf82dc1b6d562be0fa54ab7804a3a64b6d72ccfed6b6fb6ed28bbf
c117e',
1:2,
2:'11'
},
{
-1:3,
-2:h'0072992cb3ac08ecf3e5c63dedec0d51a8c1f79ef2f82f94f3c737bf5de
7986671eac625fe8257bbd0394644caaa3aaf8f27a4585fbbcad0f2457620085e5c8
f42ad',
-3:h'01dca6947bce88bc5790485ac97427342bc35f887d86d65a089377e247e
60baa55e4e8501e2ada5724ac51d6909008033ebc10ac999b9d7f5cc2519f3fe1ea1
d9475',
1:2,
2:'bilbo.baggins@hobbiton.example'
},
{
-1:1,
-2:h'98f50a4ff6c05861c8860d13a638ea56c3f5ad7590bbfbf054e1c7b4d91
d6280',
-3:h'f01400b089867804b8e9fc96c3932161f1934f4223069170d924b7e03bf
822bb',
1:2,
2:'peregrin.took@tuckborough.example'
}
]
¶
这是 COSE Key Set 的一个示例。此示例包含所有先前示例的 私钥。¶
按顺序,这些密钥为:¶
二进制文件大小为 816 字节¶
[
{
1:2,
2:'meriadoc.brandybuck@buckland.example',
-1:1,
-2:h'65eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c0
8551d',
-3:h'1e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd008
4d19c',
-4:h'aff907c99f9ad3aae6c4cdf21122bce2bd68b5283e6907154ad911840fa
208cf'
},
{
1:2,
2:'11',
-1:1,
-2:h'bac5b11cad8f99f9c72b05cf4b9e26d244dc189f745228255a219a86d6a
09eff',
-3:h'20138bf82dc1b6d562be0fa54ab7804a3a64b6d72ccfed6b6fb6ed28bbf
c117e',
-4:h'57c92077664146e876760c9520d054aa93c3afb04e306705db609030850
7b4d3'
},
{
1:2,
2:'bilbo.baggins@hobbiton.example',
-1:3,
-2:h'0072992cb3ac08ecf3e5c63dedec0d51a8c1f79ef2f82f94f3c737bf5de
7986671eac625fe8257bbd0394644caaa3aaf8f27a4585fbbcad0f2457620085e5c8
f42ad',
-3:h'01dca6947bce88bc5790485ac97427342bc35f887d86d65a089377e247e
60baa55e4e8501e2ada5724ac51d6909008033ebc10ac999b9d7f5cc2519f3fe1ea1
d9475',
-4:h'00085138ddabf5ca975f5860f91a08e91d6d5f9a76ad4018766a476680b
55cd339e8ab6c72b5facdb2a2a50ac25bd086647dd3e2e6e99e84ca2c3609fdf177f
eb26d'
},
{
1:4,
2:'our-secret',
-1:h'849b57219dae48de646d07dbb533566e976686457c1491be3a76dcea6c4
27188'
},
{
1:2,
-1:1,
2:'peregrin.took@tuckborough.example',
-2:h'98f50a4ff6c05861c8860d13a638ea56c3f5ad7590bbfbf054e1c7b4d91
d6280',
-3:h'f01400b089867804b8e9fc96c3932161f1934f4223069170d924b7e03bf
822bb',
-4:h'02d1f7e6f26c43d4868d87ceb2353161740aacf1f7163647984b522a848
df1c3'
},
{
1:4,
2:'our-secret2',
-1:h'849b5786457c1491be3a76dcea6c4271'
},
{
1:4,
2:'018c0ae5-4d9b-471b-bfd6-eef314bc7037',
-1:h'849b57219dae48de646d07dbb533566e976686457c1491be3a76dcea6c4
27188'
}
]
¶
本文档是 IETF COSE 工作组的产物。¶
首先要归咎于以下个人,是他们让我开始了这个项目: Richard Barnes、Matt Miller 和 Martin Thomson。¶
本规范的初始草案版本在一定程度上基于 JOSE 和 S/MIME 工作组的产出。¶
以下个人为文档的最终形式提供了输入:Carsten Bormann、John Bradley、Brian Campbell、Michael B. Jones、Ilari Liusvaara、Francesca Palombini、 Ludwig Seitz 和 Göran Selander。¶