RFC 8152
CBOR Object Signing and Encryption (COSE)
๐ RFC 8152 ๐
CBOR Object Signing and Encryption (COSE) ๐ฆ
Part 1 of 24 ๐
Okay so, the header block first, bestie ๐ This is an IETF Standards Track doc (category: Standards Track), dated July 2017, with ISSN 2070-1721. The author is J. Schaad from August Cellars ๐ธ It doesn't list any "Obsoletes" or "Updates" lines in its title block, so it's not replacing or patching anything in this header. ๐ง
Abstract โจ
Okay, so CBOR (Concise Binary Object Representation) is a data format built for small code size and small message size ๐ Super efficient, and iconic for that. But here's the thing: CBOR needed basic security services defined for it, and that's the gap this doc fills ๐ฅ
This doc defines the CBOR Object Signing and Encryption (COSE) protocol. It explains how to create and process signatures, message authentication codes, and encryption, all with CBOR doing the serialization. It also explains how to represent cryptographic keys using CBOR ๐ The whole thing is giving "secure and tiny" and I'm obsessed ๐ญ
Status of This Memo ๐
So this is an Internet Standards Track document, which means it's a real product of the Internet Engineering Task Force (IETF) ๐ It represents the consensus of the IETF community, got public review, and was approved for publication by the Internet Engineering Steering Group (IESG). If you want more on Internet Standards, check Section 2 of RFC 7841 ๐
For the current status, any errata, and how to give feedback, go to http://www.rfc-editor.org/info/rfc8152 ๐
Copyright Notice ๐ธ
Copyright (c) 2017 IETF Trust and the persons identified as the document authors. All rights reserved. Yes, that's the legal glow-up ๐
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents, at http://trustee.ietf.org/license-info, as in effect on the publication date. Please actually read those, bestie, because they spell out your rights and restrictions for this document ๐
Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions. They're provided without warranty, as described in the Simplified BSD License. So if you're copying code out of here, keep that license text with it ๐ซถ
Table of Contents ๐ง
Here's the full map of the doc, copied exactly as the original lays it out (page numbers and all) ๐บ๏ธ
1. Introduction ....................................................4
1.1. Design Changes from JOSE ...................................5
1.2. Requirements Terminology ...................................6
1.3. CBOR Grammar ...............................................6
1.4. CBOR-Related Terminology ...................................7
1.5. Document Terminology .......................................8
2. Basic COSE Structure ............................................8
3. Header Parameters ..............................................10
3.1. Common COSE Headers Parameters ............................12
4. Signing Objects ................................................16
4.1. Signing with One or More Signers ..........................16
4.2. Signing with One Signer ...................................18
4.3. Externally Supplied Data ..................................19
4.4. Signing and Verification Process ..........................20
4.5. Computing Counter Signatures ..............................22
5. Encryption Objects .............................................22
5.1. Enveloped COSE Structure ..................................23
5.1.1. Content Key Distribution Methods ...................24
5.2. Single Recipient Encrypted ................................25
5.3. How to Encrypt and Decrypt for AEAD Algorithms ............26
5.4. How to Encrypt and Decrypt for AE Algorithms ..............28
6. MAC Objects ....................................................29
6.1. MACed Message with Recipients .............................30
6.2. MACed Messages with Implicit Key ..........................31
6.3. How to Compute and Verify a MAC ...........................32
7. Key Objects ....................................................33
7.1. COSE Key Common Parameters ................................34
8. Signature Algorithms ...........................................37
8.1. ECDSA .....................................................38
8.1.1. Security Considerations ............................40
8.2. Edwards-Curve Digital Signature Algorithms (EdDSAs) .......40
8.2.1. Security Considerations ............................41
9. Message Authentication Code (MAC) Algorithms ...................42
9.1. Hash-Based Message Authentication Codes (HMACs) ...........42
9.1.1. Security Considerations ............................44
9.2. AES Message Authentication Code (AES-CBC-MAC) .............44
9.2.1. Security Considerations ............................45
10. Content Encryption Algorithms .................................45
10.1. AES GCM ..................................................46
10.1.1. Security Considerations ...........................47
10.2. AES CCM ..................................................47
10.2.1. Security Considerations ...........................50
10.3. ChaCha20 and Poly1305 ....................................50
10.3.1. Security Considerations ...........................51
11. Key Derivation Functions (KDFs) ...............................51
11.1. HMAC-Based Extract-and-Expand Key Derivation
Function (HKDF) ..........................................52
11.2. Context Information Structure ............................54
12. Content Key Distribution Methods ..............................60
12.1. Direct Encryption ........................................60
12.1.1. Direct Key ........................................61
12.1.2. Direct Key with KDF ...............................61
12.2. Key Wrap ................................................63
12.2.1. AES Key Wrap ......................................64
12.3. Key Transport ...........................................65
12.4. Direct Key Agreement ....................................65
12.4.1. ECDH ..............................................66
12.4.2. Security Considerations ...........................69
12.5. Key Agreement with Key Wrap ..............................69
12.5.1. ECDH ..............................................70
13. Key Object Parameters .........................................72
13.1. Elliptic Curve Keys ......................................73
13.1.1. Double Coordinate Curves ..........................73
13.2. Octet Key Pair ...........................................74
13.3. Symmetric Keys ...........................................75
14. CBOR Encoder Restrictions .....................................76
15. Application Profiling Considerations ..........................76
16. IANA Considerations ...........................................78
16.1. CBOR Tag Assignment ......................................78
16.2. COSE Header Parameters Registry ..........................78
16.3. COSE Header Algorithm Parameters Registry ................79
16.4. COSE Algorithms Registry .................................79
16.5. COSE Key Common Parameters Registry ......................81
16.6. COSE Key Type Parameters Registry ........................81
16.7. COSE Key Types Registry ..................................82
16.8. COSE Elliptic Curves Registry ............................83
16.9. Media Type Registrations .................................84
16.9.1. COSE Security Message .............................84
16.9.2. COSE Key Media Type ...............................85
16.10. CoAP Content-Formats Registry ...........................87
16.11. Expert Review Instructions ..............................87
17. Security Considerations .......................................88
18. References ....................................................90
18.1. Normative References .....................................90
18.2. Informative References ...................................92
Appendix A. Guidelines for External Data Authentication of
Algorithms ............................................96
A.1. Algorithm Identification ..................................96
A.2. Counter Signature without Headers .........................99
Appendix B. Two Layers of Recipient Information ..................100
Appendix C. Examples .............................................102
C.1. Examples of Signed Messages ..............................103
C.1.1. Single Signature ..................................103
C.1.2. Multiple Signers ..................................103
C.1.3. Counter Signature .................................104
C.1.4. Signature with Criticality ........................105
C.2. Single Signer Examples ...................................106
C.2.1. Single ECDSA Signature ...........................106
C.3. Examples of Enveloped Messages ...........................107
C.3.1. Direct ECDH .......................................107
C.3.2. Direct Plus Key Derivation ........................108
C.3.3. Counter Signature on Encrypted Content ............109
C.3.4. Encrypted Content with External Data ..............111
C.4. Examples of Encrypted Messages ...........................111
C.4.1. Simple Encrypted Message ..........................111
C.4.2. Encrypted Message with a Partial IV ...............112
C.5. Examples of MACed Messages ...............................112
C.5.1. Shared Secret Direct MAC ..........................112
C.5.2. ECDH Direct MAC ...................................113
C.5.3. Wrapped MAC .......................................114
C.5.4. Multi-Recipient MACed Message .....................115
C.6. Examples of MAC0 Messages ................................117
C.6.1. Shared Secret Direct MAC ..........................117
C.7. COSE Keys ................................................117
C.7.1. Public Keys .......................................117
C.7.2. Private Keys ......................................119
Acknowledgments ..................................................121
Author's Address .................................................121
Next up: the protocol itself starts in Section 1, so stay tuned ๐๐โจ
1. Introduction โจ
Okay so bestie, there's been a huge focus on tiny, constrained devices, the whole Internet of Things (IoT) situation ๐. One of the standards that came out of this is "Concise Binary Object Representation (CBOR)" [RFC7049]. CBOR took the data model of the JavaScript Object Notation (JSON) [RFC7159] and extended it so it can hold binary data, plus a few other upgrades ๐ฆ. Lots of IoT working groups are now using CBOR as their go-to way to encode data structures, and it was built to be small on the wire, small in implementation size, and a schema-free decoder ๐ . Since IoT devices need message security too, using CBOR as the message encoding format just makes sense ๐ซถ.
The JOSE working group already made a set of documents [RFC7515] [RFC7516] [RFC7517] [RFC7518] that use JSON. They explain how to process encryption, signatures, and Message Authentication Code (MAC) operations, and how to encode keys using JSON ๐. This document defines the CBOR Object Signing and Encryption (COSE) standard, which does the exact same job but for the CBOR encoding format ๐. We really tried to keep the flavor of the original JSON Object Signing and Encryption (JOSE) documents, but two things were taken into account:
- CBOR can do things JSON can't, and those things are worth using. For example, CBOR can encode binary directly without first turning it into a base64-encoded string ๐.
- COSE is not a straight copy of JOSE. While making COSE, we re-examined the decisions JOSE made. In lots of cases we landed on different results, because the criteria weren't always the same ๐.
1.1. Design Changes from JOSE
Here's what's different from JOSE, and yes, these are the glow-ups โจ:
- There's a single top message structure, so encrypted, signed, and MACed messages are easy to spot and still share a consistent view ๐.
- Signed messages separate the protected and unprotected parameters. The ones about the content are kept apart from the ones about the signature ๐ง.
- MACed messages are split off from signed messages ๐ฆ.
- MACed messages can use the same set of recipient algorithms that enveloped messages use to get the MAC authentication key ๐.
- Binary data gets binary encodings instead of base64url encodings ๐ธ.
- The authentication tag for encryption algorithms gets combined with the ciphertext ๐.
- The set of cryptographic algorithms grew in some directions and got trimmed in others โญ.
1.2. Requirements Terminology
Okay, this part is important, so listen up ๐. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
When the words appear in lowercase, this interpretation does not apply ๐ โโ๏ธ.
1.3. CBOR Grammar
There is currently no standard CBOR grammar that specs can use, so the CBOR structures get described in prose ๐.
The document was built by working on the grammar first and then writing the prose to go with it. As a result, the prose uses the primitive type strings defined by CBOR Data Definition Language (CDDL) [CDDL]. These are the primitive types used in this specification:
any-- a non-specific value that permits all CBOR values to be placed here.bool-- a boolean value (true: major type 7, value 21; false: major type 7, value 20).bstr-- a byte string (major type 2).int-- an unsigned integer or a negative integer.nil-- a null value (major type 7, value 22).nint-- a negative integer (major type 1).tstr-- a UTF-8 text string (major type 3).uint-- an unsigned integer (major type 0).
Two CDDL syntaxes show up in this document as shorthand:
FOO / BAR-- means that either FOO or BAR can appear here.[+ FOO]-- means that the type FOO appears one or more times in an array.
On top of the prose, there's a version of a CBOR grammar written in CDDL. CDDL hasn't been published in an RFC yet, so this grammar may not work with the final version of CDDL ๐คทโโ๏ธ. The CDDL grammar is informational. The prose description is the normative one, so the prose wins ๐.
You can pull all the collected CDDL out of the XML version of this document with the XPath expression below. (Depending on which XPath evaluator you use, you might need to handle > as an entity.)
//artwork[@type='CDDL']/text()
CDDL expects the initial non-terminal symbol to be the first symbol in the file, so the first fragment of CDDL goes here:
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 /
COSE_KDF_Context
The non-terminal Internal_Types exists to help the automated validation tools used while writing this document. It references the non-terminals that are used for security computations but are not emitted for transport ๐ ๏ธ.
1.4. CBOR-Related Terminology
In JSON, maps are called objects, and they only have one kind of map key: a string ๐ฆ. In COSE, map keys can be strings, negative integers, or unsigned integers. The integers keep the encoding compact and make comparison easy ๐ข. Strings give you an extra range of short encoded values to use too. Since the word "key" is mostly used for its other meaning, a cryptographic key, we use the term "label" for this job as a map key ๐ท๏ธ.
If a COSE map has a label that isn't a string or an integer, that's an error. Applications can either fail processing or process messages with incorrect labels. Still, they MUST NOT create messages with incorrect labels ๐ซ.
A CDDL grammar fragment defines the non-terminal 'label', as mentioned in the previous paragraph, and 'values', which permits any value to be used:
label = int / tstr
values = any
1.5. Document Terminology
In this document, we use the following terminology ๐:
Byte is a synonym for octet ๐ฌ.
Constrained Application Protocol (CoAP) is a specialized web transfer protocol for use in constrained systems. It is defined in [RFC7252] ๐.
Authenticated Encryption (AE) [RFC5116] algorithms are the encryption algorithms that provide an authentication check of the contents, done together with the encryption service ๐.
Authenticated Encryption with Authenticated Data (AEAD) [RFC5116] algorithms give you the same content authentication service as AE algorithms. On top of that, they also provide authentication for data that isn't encrypted ๐ซ.
2. Basic COSE Structure
The COSE object structure is designed so there can be a big chunk of common code when parsing and processing the different types of security messages ๐งฉ. Every message structure is built on the CBOR array type. The first three elements of the array always contain the same information:
- The set of protected header parameters, wrapped in a bstr.
- The set of unprotected header parameters, as a map.
- The content of the message. The content is either the plaintext or the ciphertext, whichever is appropriate. The content may be detached, but its location is still used. When present, the content is wrapped in a bstr. When detached, it's a nil value ๐.
Elements after this point depend on the specific message type ๐.
COSE messages also use layers to separate the different types of cryptographic concepts ๐ฐ. Here's an example of how that works. Take the COSE_Encrypt message (Section 5.1). It's split into two layers: the content layer and the recipient layer. In the content layer, the plaintext gets encrypted and information about the encrypted message goes in there. In the recipient layer, the content encryption key (CEK) gets encrypted, and information about how it's encrypted for each recipient goes in there ๐. There's also a single layer version of the encryption message, COSE_Encrypt0 (Section 5.2), for when the CEK is pre-shared ๐ค.
There are four ways to figure out which type of message you've got ๐ต๏ธโโ๏ธ:
- The specific message type is known from the context. This could be defined by a marker in the containing structure, or by restrictions the application protocol puts in place.
- The message type is identified by a CBOR tag. Messages with a CBOR tag are called tagged messages, and messages without one are called untagged messages. This document defines a CBOR tag for each of the message structures. You can find these tags in Table 1 ๐ท๏ธ.
- When a COSE object is carried in a media type of 'application/cose', the optional parameter 'cose-type' can be used to identify the embedded object. The parameter is OPTIONAL if the tagged version of the structure is used. The parameter is REQUIRED if the untagged version of the structure is used. You can find the value to use with the parameter for each structure in Table 1 ๐.
- When a COSE object is carried as a CoAP payload, the CoAP Content-Format Option can be used to identify the message content. The CoAP Content-Format values are in Table 26. The CBOR tag for the message structure isn't required, because each security message is uniquely identified already ๐ธ.
+-------+---------------+---------------+---------------------------+
| CBOR | cose-type | Data Item | Semantics |
| Tag | | | |
+-------+---------------+---------------+---------------------------+
| 98 | cose-sign | COSE_Sign | COSE Signed Data Object |
| 18 | cose-sign1 | COSE_Sign1 | COSE Single Signer Data |
| | | | Object |
| 96 | cose-encrypt | COSE_Encrypt | COSE Encrypted Data |
| | | | Object |
| 16 | cose-encrypt0 | COSE_Encrypt0 | COSE Single Recipient |
| | | | Encrypted Data Object |
| 97 | cose-mac | COSE_Mac | COSE MACed Data Object |
| 17 | cose-mac0 | COSE_Mac0 | COSE Mac w/o Recipients |
| | | | Object |
+-------+---------------+---------------+---------------------------+
Table 1: COSE Message Identification ๐
The following CDDL fragment identifies all of the top messages defined in this document. Separate non-terminals are defined for the tagged and the untagged versions of the messages ๐งพ.
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
- Header Parameters
Okay so bestie, this is where COSE gets really pretty ๐ The whole format has two little buckets of info that aren't the payload itself, but they hold stuff about the content, the algorithms, the keys, or hints for how to process that layer. โจ These two buckets show up in every structure except keys ๐ Just because the buckets exist doesn't mean they're always useful though. The protected bucket lives in the recipient structure, but some recipient algorithms don't do authenticated data at all, so the protected bucket just stays empty ๐ฅบ
Both buckets are CBOR maps. The map key is a 'label' (Section 1.4), and the value depends on what that label is defined to mean. Both maps use the exact same set of label/value pairs ๐ Integer and string labels are split up into a standard range, a private range, and a range that depends on which algorithm you picked. All the defined labels live in the "COSE Header Parameters" IANA registry (Section 16.2) ๐ง
Here are the two buckets for each layer:
protected: holds parameters about the current layer that MUST be cryptographically protected ๐ If it isn't going to be part of a cryptographic computation, this bucket MUST be empty. It gets encoded in the message as a binary object. To get the value, you CBOR encode the protected map and then wrap it in a bstr. Senders SHOULD encode a zero-length map as a zero-length string instead of as a zero-length map (the one encoded as h'a0'). Why? The zero-length binary is shorter, and it's also the version used in the serialization structures for cryptographic computation, so it's literally the main character ๐ After encoding the map, you wrap the value in the binary object. Recipients MUST accept both a zero-length binary value AND a zero-length map encoded in the binary value, so both are fine on receipt ๐ซถ The wrapping makes it way more likely the protected map gets through transit unchanged. (Badly behaved intermediates could decode and re-encode it, but that breaks verification unless the re-encoded byte string is identical to the decoded one ๐.) This also means nobody has to agree on a common canonical encoding, which is iconic ๐
unprotected: holds parameters about the current layer that are NOT cryptographically protected ๐ธ
Only parameters about the current layer go in that layer. For example, 'content type' describes the content of the message being carried, so it only goes in the content layer and NOT in the recipient or signature layers ๐ In principle, you should be able to process any layer without looking at any other layer. The only data that needs to cross layers is the cryptographic key, with the exception of the COSE_Sign structure ๐ฆ
Every security object in this document has both buckets. In order, the fields are the 'protected' bucket (as a CBOR 'bstr') and then the 'unprotected' bucket (as a CBOR 'map'). Having both buckets is REQUIRED ๐ The parameters that go in the buckets come from the IANA "COSE Header Parameters" registry (Section 16.2). The next section covers some common parameters, but plenty more are defined throughout the document โจ
Labels in each map MUST be unique ๐ โโ๏ธ When processing messages, if a label shows up more than once, the message MUST be rejected as malformed ๐ Applications SHOULD check that the same label doesn't appear in both the protected and unprotected headers ๐ If the message isn't rejected as malformed, attributes MUST be pulled from the protected bucket BEFORE the unprotected bucket ๐ฅ
The CDDL fragment below represents the two header buckets. A group "Headers" is defined in CDDL to represent both buckets where attributes go, so these two fields stay consistent everywhere. There's also a type for the map of common 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.1. Common COSE Headers Parameters ๐
okay bestie, this section is where the common header parameters live ๐ Table 2 is basically the cheat sheet, so check it whenever you need a label or a value type ๐ฆ
The set of header parameters defined in this section are:
alg ๐: This is how you say which algorithm is doing the security processing. It MUST be authenticated wherever that's possible, and it's possible with AEAD algorithms or the constructions COSE_Sign, COSE_Sign0, COSE_Mac, and COSE_Mac0. You can authenticate it by putting it in the protected header bucket or by including it in the externally supplied data. The value comes from the "COSE Algorithms" registry (see Section 16.4) โจ
crit ๐ฆ: This one tells the receiver which protected header labels it has to understand, or the message gets rejected. Parameters defined in this document don't need to be listed, since every implementation should already know them ๐ When it's there, crit MUST be in the protected header bucket, and the array MUST have at least one value in it. Not every label has to show up here. These are the rules for what goes in the array:
- Integer labels in the range of 0 to 8 SHOULD be omitted.
- Integer labels in the range -1 to -128 can be omitted, since they depend on the algorithm. If an app can correctly process an algorithm, it can be assumed to correctly process all of the common parameters for that algorithm. Integer labels in the range -129 to -65536 SHOULD be included, because they're the less common parameters that might not be widely supported ๐
- Labels for parameters that an application requires MAY be omitted. Applications should have a statement saying whether the label can be omitted.
The crit values can be processed by the security library code or by an application using that library. The only real requirement is that the parameter gets processed. If the crit value list includes a value whose parameter isn't in the protected bucket, that's a fatal error in processing the message.
Not in the protected bucket and listed in crit? That's a fatal error, bestie. The message is dead ๐
content type ๐ฆ: This tells you what kind of data is sitting in the payload or ciphertext fields. Integers come from the "CoAP Content-Formats" IANA registry table [COAP.Formats]. Text values follow the syntax "<type-name>/<subtype-name>", where <type-name> and <subtype-name> are defined in Section 4.2 of [RFC6838]. Leading and trailing whitespace is dropped too. You can look up textual content values, along with their parameters and subparameters, in the IANA "Media Types" registry ๐ธ Applications SHOULD provide this parameter if the content structure could be ambiguous.
kid ๐๏ธ: This is one piece of data you can use to find the right cryptographic key. Its value gets matched against the 'kid' member of a COSE_Key structure. Other key distribution methods can define an equivalent field to match against. Applications MUST NOT assume 'kid' values are unique ๐ญ More than one key can share the same 'kid', so you might have to check every key tied to that 'kid'. The internal structure of 'kid' values isn't defined, and applications can't rely on it. Key identifiers are just hints about which key to use, not a security-critical field, so it's fine to put it in the unprotected headers bucket ๐ง
IV ๐ท: This holds the Initialization Vector (IV). For some symmetric encryption algorithms, people call it a nonce. The IV can go in the unprotected header, because changing it makes the decryption come out as obviously garbled plaintext โจ
Partial IV ๐งฉ: This holds part of the IV. When you're using the COSE_Encrypt0 structure, part of the IV can live in the context tied to the key. This field carries a value that changes the IV for every message ๐ Like the IV, it can go in the unprotected header, since tampering with it leads to plaintext that's easy to spot as garbled. The 'Initialization Vector' and 'Partial Initialization Vector' parameters MUST NOT both be present in the same security layer ๐
The message IV is generated by these steps:
- Left-pad the Partial IV with zeros to the length of IV.
- XOR the padded Partial IV with the context IV.
counter signature โ๏ธ: This holds one or more counter signature values. A counter signature is a way for a second party to sign some data. This parameter can show up as an unprotected attribute in any of these structures: COSE_Sign1, COSE_Signature, COSE_Encrypt, COSE_recipient, COSE_Encrypt0, COSE_Mac, and COSE_Mac0. All of those structures start with the same elements, which makes it possible to compute the counter signature consistently. The details on computing counter signatures are in Section 4.5 ๐ฆ
+-----------+-------+----------------+-------------+----------------+
| Name | Label | Value Type | Value | Description |
| | | | Registry | |
+-----------+-------+----------------+-------------+----------------+
| alg | 1 | int / tstr | COSE | Cryptographic |
| | | | Algorithms | algorithm to |
| | | | registry | use |
| crit | 2 | [+ label] | COSE Header | Critical |
| | | | Parameters | headers to be |
| | | | registry | understood |
| content | 3 | tstr / uint | CoAP | Content type |
| type | | | Content- | of the payload |
| | | | Formats or | |
| | | | Media Types | |
| | | | registries | |
| kid | 4 | bstr | | Key identifier |
| IV | 5 | bstr | | Full |
| | | | | Initialization |
| | | | | Vector |
| Partial | 6 | bstr | | Partial |
| IV | | | | Initialization |
| | | | | Vector |
| counter | 7 | COSE_Signature | | CBOR-encoded |
| signature | | / [+ | | signature |
| | | COSE_Signature | | structure |
| | | ] | | |
+-----------+-------+----------------+-------------+----------------+
Table 2: Common Header Parameters
The CDDL fragment for the headers in this section is below. Every header is marked optional, since they don't all need to be in every map. Headers that a specific map requires are covered above ๐
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
? 7 => COSE_Signature / [+COSE_Signature] ; Counter signature
)
4. Signing Objects โจ
okay so COSE has two signature structures ๐๏ธ COSE_Sign lets one or more signatures go on the same content, while COSE_Sign1 is limited to a single signer. You can't convert between them. The signature computation includes a parameter that identifies which structure is in use, so if you convert one to the other, the signature validation fails ๐ no shortcuts here, bestie ๐ซถ
4.1. Signing with One or More Signers โจ
okay so COSE_Sign is the structure that lets you slap one or more signatures onto a message payload ๐ . The stuff about the content (like content type) and the stuff about each signature (like the algorithm, the key, and counter signatures) all ride along together. Some of it can be covered by the signature, and some of it can just be hanging out there ๐. An example of a content parameter is the content type. Examples of signature parameters are the algorithm and key used to make the signature, plus counter signatures.
RFC 5652 indicates that:
When more than one signature is present, the successful validation of one signature associated with a given signer is usually treated as a successful signature by that signer. However, there are some application environments where other rules are needed. An application that employs a rule other than one valid signature for each signer must specify those rules. Also, where simple matching of the signer identifier is not sufficient to determine whether the signatures were generated by the same signer, the application specification must describe how to determine which signatures were generated by the same signer. Support for different communities of recipients is the primary reason that signers choose to include more than one signature.
For example, a COSE_Sign structure might include signatures made with the Edwards-curve Digital Signature Algorithm (EdDSA) [RFC8032] and with the Elliptic Curve Digital Signature Algorithm (ECDSA) [DSS]. That way recipients can verify whichever signature matches the algorithm they support ๐ฆ. More-detailed info on evaluating multiple signatures is in [RFC5752] ๐.
The signature structure can be encoded as either tagged or untagged, depending on where it's going to be used. A tagged COSE_Sign structure is identified by the CBOR tag 98. The CDDL fragment for that is:
COSE_Sign_Tagged = #6.98(COSE_Sign)
A COSE Signed Message is made of two parts ๐ง. The CBOR object that carries the body and the info about the body is called the COSE_Sign structure. The CBOR object that carries the signature and the info about the signature is called the COSE_Signature structure. Examples of COSE Signed Messages can be found in Appendix C.1.
The COSE_Sign structure is a CBOR array. The fields of the array, in order, are:
- protected: This is as described in Section 3.
- unprotected: This is as described in Section 3.
- payload: This field holds the serialized content to be signed. If the payload is not present in the message, the application is required to supply the payload separately. The payload is wrapped in a bstr so it gets transported without changes ๐. If the payload is transported separately ("detached content"), then a nil CBOR object goes in this spot, and it's the application's job to make sure it gets transported without changes.
Note: When a signature with a message recovery algorithm is used (Section 8), the maximum number of bytes that can be recovered is the length of the payload. The size of the payload is reduced by the number of bytes that will be recovered. If all of the bytes of the payload are consumed, then the payload is encoded as a zero-length binary string rather than as being absent.
- signatures: This field is an array of signatures. Each signature is represented as a COSE_Signature structure.
The CDDL fragment that represents the text above for COSE_Sign is below ๐.
COSE_Sign = [
Headers,
payload : bstr / nil,
signatures : [+ COSE_Signature]
]
The COSE_Signature structure is a CBOR array. The fields of the array, in order, are:
- protected: This is as described in Section 3.
- unprotected: This is as described in Section 3.
- signature: This field holds the computed signature value. The type of the field is a bstr. Algorithms MUST specify padding if the signature value is not a multiple of 8 bits ๐จ.
The CDDL fragment for COSE_Signature is next.
COSE_Signature = [
Headers,
signature : bstr
]
4.2. Signing with One Signer ๐ธ
The COSE_Sign1 signature structure is used when only one signature is going to be placed on a message. The content parameters and the signature parameters sit in the same pair of buckets, instead of being split up like COSE_Sign does ๐.
The structure can be encoded as either tagged or untagged, depending on the context it's used in. A tagged COSE_Sign1 structure is identified by the CBOR tag 18. The CDDL fragment for that is:
COSE_Sign1_Tagged = #6.18(COSE_Sign1)
The CBOR object that carries the body, the signature, and the info about the body and signature is called the COSE_Sign1 structure. Examples of COSE_Sign1 messages can be found in Appendix C.2.
The COSE_Sign1 structure is a CBOR array. The fields of the array, in order, are:
- protected: This is as described in Section 3.
- unprotected: This is as described in Section 3.
- payload: This is as described in Section 4.1.
- signature: This field holds the computed signature value. The type of the field is a bstr.
The CDDL fragment that represents the text above for COSE_Sign1 follows ๐ .
COSE_Sign1 = [
Headers,
payload : bstr / nil,
signature : bstr
]
4.3. Externally Supplied Data ๐ฆ
One of the features in the COSE document is that applications can provide extra data to be authenticated, even though that data isn't carried as part of the COSE object ๐. The main reason this exists is the CoAP message structure [RFC7252], where options can come before the payload. Examples of data that could go in that spot are the CoAP code or CoAP options. If the data is in the header section, proxies can use it to help with their operations. For example, a proxy can use the Accept Option to figure out whether an appropriate value is in its cache. The sender can stop a proxy from changing the set of values it will accept by including that value in the resulting authentication tag ๐. It may also be desired to protect these values, so that if they get modified in transit, that can be detected.
This document describes the process for using a byte array of externally supplied authenticated data. However, the way that byte array gets constructed is up to the application. Applications that use this feature need to define how the externally supplied authenticated data is constructed. That construction needs to take the following issues into account:
- If multiple items are included, applications need to ensure that the same byte string is not produced for different inputs. This could happen by appending the strings
'AB'and'CDE'or by appending the strings'ABC'and'DE'. This is usually handled by making fields a fixed width and/or by encoding the length of the field as part of the output. Using options from CoAP [RFC7252] as an example, those fields use a TLV structure, so they can be concatenated without any problems ๐งฉ. - If multiple items are included, an order for the items needs to be defined. Using options from CoAP as an example, an application could say the fields are ordered by option number ๐ข.
- Applications need to ensure that the byte stream will be the same on both sides. Using options from CoAP might cause a problem if the same relative numbering is kept. An intermediate node could insert or remove an option, which changes how the relative number is worked out. An application would need to specify that the relative number must be re-encoded so it's relative only to the options that are in the external data ๐.
4.4. Signing and Verification Process ๐ฅ
To create a signature, you need a well-defined byte stream ๐. The Sig_structure is used to create that canonical form. This signing and verification process takes in the body information (COSE_Sign or COSE_Sign1), the signer information (COSE_Signature), and the application data (external source). A Sig_structure is a CBOR array. The fields of the Sig_structure, in order, are:
- A text string identifying the context of the signature. The context string is:
"Signature"for signatures using the COSE_Signature structure."Signature1"for signatures using the COSE_Sign1 structure."CounterSignature"for signatures used as counter signature attributes.
- The protected attributes from the body structure, encoded in a bstr type. If there are no protected attributes, a bstr of length zero is used.
- The protected attributes from the signer structure, encoded in a bstr type. If there are no protected attributes, a bstr of length zero is used. This field is omitted for the COSE_Sign1 signature structure.
- The protected attributes from the application, encoded in a bstr type. If this field is not supplied, it defaults to a zero-length binary string. (See Section 4.3 for application guidance on constructing this field.)
- The payload to be signed, encoded in a bstr type. The payload is placed here independent of how it is transported.
The CDDL fragment that describes the text above is:
Sig_structure = [
context : "Signature" / "Signature1" / "CounterSignature",
body_protected : empty_or_serialized_map,
? sign_protected : empty_or_serialized_map,
external_aad : bstr,
payload : bstr
]
How to compute a signature ๐ง:
- Create a Sig_structure and populate it with the appropriate fields.
- Create the value ToBeSigned by encoding the Sig_structure to a byte string, using the encoding described in Section 14.
- Call the signature creation algorithm, passing in K (the key to sign with), alg (the algorithm to sign with), and ToBeSigned (the value to sign).
- Place the resulting signature value in the 'signature' field of the array.
The steps for verifying a signature are:
- Create a Sig_structure object and populate it with the appropriate fields.
- Create the value ToBeSigned by encoding the Sig_structure to a byte string, using the encoding described in Section 14.
- Call the signature verification algorithm, passing in K (the key to verify with), alg (the algorithm used sign with), ToBeSigned (the value to sign), and sig (the signature to be verified).
In addition to performing the signature verification, the application may also perform the appropriate checks to make sure the key is correctly paired with the signing identity, and that the signing identity is authorized, before performing actions ๐ก๏ธ.
4.5. Computing Counter Signatures โจ
Okay so counter signatures are basically a way to attach a different signature, made by different signers, to some piece of content ๐๏ธ The main use is putting a signature on a signature so you can prove that a signature existed at a certain time (aka a Timestamp) โฐ In this document we let counter signatures show up in a lot more places, and that's giving main character energy ๐ For example, you can drop one into the unprotected attributes of a COSE_Encrypt object ๐ That lets an intermediary either check that the encrypted byte stream hasn't been modified without being able to decrypt it (wild, right?) or say that an encrypted byte stream existed at a given time or passed through it for routing, which is the proxy signature thing ๐ฆ
An example of a counter signature on a signature is in Appendix C.1.3 ๐ง An example of a counter signature in an encryption object is in Appendix C.3.3 ๐ธ
The whole thing works because all these objects have the same shape ๐ซถ Every one of them has a set of protected attributes, a set of unprotected attributes, and a body, in that order. So the Sig_structure can be used the same way every time to get the byte stream you need for processing a signature โจ If the counter signature is going over a COSE_Encrypt structure, the body_protected and payload items get mapped into the Sig_structure exactly like they do for a COSE_Sign structure ๐
One thing to know: only a signature algorithm with appendix (see Section 8) can be used for counter signatures ๐ The reason is that the body has to be processable without evaluating the counter signature, and signature schemes with message recovery just can't do that ๐ญ
5. Encryption Objects ๐
Okay so COSE has two encryption structures ๐ COSE_Encrypt0 is for when you don't need a recipient structure because the key is already known implicitly. COSE_Encrypt is for literally everything else ๐ That includes cases with multiple recipients, or when the recipient algorithm is something other than direct.
5.1. Enveloped COSE Structure
The enveloped structure lets you have one or more recipients for a message ๐ It carries parameters about the content and parameters about the recipient info. The protected parameters about the content are authenticated by the content encryption algorithm. The protected parameters about the recipient are authenticated by the recipient algorithm, but only when that algorithm supports it ๐ซถ Examples of content parameters are the type of the content and the content encryption algorithm. Examples of recipient parameters are the recipient's key identifier and the recipient's encryption algorithm ๐
Here's the vibe: the same techniques and structures get used for encrypting both the plaintext and the keys โจ This is different from how "Cryptographic Message Syntax (CMS)" [RFC5652] and "JSON Web Encryption (JWE)" [RFC7516] do it, where they use different structures for the content layer and the recipient layer ๐ COSE only defines two structures: COSE_Encrypt holds the encrypted content, and COSE_recipient holds the encrypted keys for recipients ๐ฆ Examples of encrypted messages are in Appendix C.3 ๐
The COSE_Encrypt structure can be encoded as tagged or untagged, depending on the context you're using it in ๐ A tagged COSE_Encrypt structure is identified by the CBOR tag 96. The CDDL fragment for that is:
COSE_Encrypt_Tagged = #6.96(COSE_Encrypt)
COSE_Encrypt is a CBOR array ๐ The fields, in order, are:
protected: This is as described in Section 3.unprotected: This is as described in Section 3.ciphertext: This field holds the ciphertext encoded as a bstr. If the ciphertext is going to be transported separately from the control info about the encryption process (aka detached content), this field is encoded as a nil value ๐recipients: This field holds an array of recipient information structures. The type for each one is a COSE_recipient.
The CDDL fragment that matches the text above is:
COSE_Encrypt = [
Headers,
ciphertext : bstr / nil,
recipients : [+COSE_recipient]
]
COSE_recipient is also a CBOR array ๐ The fields, in order, are:
protected: This is as described in Section 3.unprotected: This is as described in Section 3.ciphertext: This field holds the encrypted key encoded as a bstr. Every encoded key is a symmetric key, and the binary value of the key is the content ๐ If there isn't an encrypted key, this field is encoded as a nil value.recipients: This field holds an array of recipient information structures. The type for each one is a COSE_recipient (you can see an example of this in Appendix B) ๐ง If there are no recipient information structures, this element is absent.
The CDDL fragment for COSE_recipient, matching the text above, is:
COSE_recipient = [
Headers,
ciphertext : bstr / nil,
? recipients : [+COSE_recipient]
]
5.1.1. Content Key Distribution Methods
Okay so an encrypted message is an encrypted content plus an encrypted CEK for one or more recipients ๐ The CEK gets encrypted for each recipient using a key that's specific to that recipient. How that encryption works depends on which class the recipient algorithm falls into, and you can read the details of each class in Section 12 ๐ Here's a quick rundown of the five content key distribution methods:
- direct: The CEK is the same as the previously distributed symmetric key you identified, or it's derived from a previously distributed secret. No CEK gets transported in the message ๐ซถ
- symmetric key-encryption keys (KEK): The CEK is encrypted using a previously distributed symmetric KEK. This is also known as key wrap ๐
- key agreement: The recipient's public key and a sender's private key are used to make a pairwise secret. A Key Derivation Function (KDF) is applied to derive a key, and then the CEK is either that derived key or gets encrypted by it ๐ฆ
- key transport: The CEK is encrypted with the recipient's public key. No key transport algorithms are defined in this document ๐
- passwords: The CEK is encrypted in a KEK that's derived from a password. No password algorithms are defined in this document ๐
5.2. Single Recipient Encrypted
Okay so COSE_Encrypt0 can't specify recipients for the message ๐ฅบ It assumes the recipient already knows which key to use to decrypt the message. If the key needs to be identified to the recipient, you'd want the enveloped structure instead ๐
Examples of encrypted messages are in Appendix C.3 again, because they're that good โจ
A tagged COSE_Encrypt0 structure is identified by the CBOR tag 16. The CDDL fragment for that is:
COSE_Encrypt0_Tagged = #6.16(COSE_Encrypt0)
COSE_Encrypt0 is a CBOR array, and the fields in order are:
protected: This is as described in Section 3.unprotected: This is as described in Section 3.ciphertext: This is as described in Section 5.1.
The CDDL fragment for COSE_Encrypt0, matching the text above, is:
COSE_Encrypt0 = [
Headers,
ciphertext : bstr / nil,
]
5.3. How to Encrypt and Decrypt for AEAD Algorithms โจ
okay bestie, AEAD algorithms are actually kinda simple once you see the steps ๐ The first thing you do is build a consistent byte stream for the authenticated data, and for that we use something called an Enc_structure ๐ It's a CBOR array, and the fields go in this exact order:
- A text string saying what context the authenticated data is for. The options are:
"Encrypt0" for content encryption in a COSE_Encrypt0 structure โจ
"Encrypt" for the first layer of a COSE_Encrypt structure (aka content encryption) ๐ฆ
"Enc_Recipient" for a recipient encoding that goes in a COSE_Encrypt structure ๐ธ
"Mac_Recipient" for a recipient encoding that goes in a MACed message structure ๐
"Rec_Recipient" for a recipient encoding that goes in a recipient structure ๐ง
- The protected attributes from the body structure, encoded as a bstr. If there are no protected attributes, you use a bstr of length zero ๐
- The protected attributes from the application, encoded as a bstr. If this field isn't supplied, it defaults to a zero-length bstr. (Check out Section 4.3 for application guidance on building this one ๐ซถ)
The CDDL fragment for all that is:
Enc_structure = [
context : "Encrypt" / "Encrypt0" / "Enc_Recipient" /
"Mac_Recipient" / "Rec_Recipient",
protected : empty_or_serialized_map,
external_aad : bstr
]
How to encrypt a message: ๐
- Create an Enc_structure and fill in the appropriate fields.
- Encode the Enc_structure to a byte stream (this is the Additional Authenticated Data, or AAD), using the encoding described in Section 14.
- Work out the encryption key (K). This step depends on the class of recipient algorithm being used. For:
No Recipients: the key is determined by the algorithm and key at the current layer. Examples are key transport keys (Section 12.3), key wrap keys (Section 12.2.1), or pre-shared secrets ๐ฅ
Direct Encryption and Direct Key Agreement: the key is determined by the key and algorithm in the recipient structure. The encryption algorithm and key size are inputs into the KDF used for the recipient. (For direct, the KDF is basically the identity operation ๐) Examples of these algorithms are in Sections 12.1.2 and 12.4.1 โจ
Other: the key is randomly or pseudorandomly generated ๐ฒ
- Call the encryption algorithm with K (the encryption key), P (the plaintext), and AAD. Put the returned ciphertext into the 'ciphertext' field of the structure ๐
- For recipients of the message, recursively perform the encryption algorithm for that recipient, using K (the encryption key) as the plaintext ๐
How to decrypt a message: ๐ฆ
- Create an Enc_structure and fill in the appropriate fields.
- Encode the Enc_structure to a byte stream (AAD), using the encoding described in Section 14.
- Work out the decryption key. This step depends on the class of recipient algorithm being used. For:
No Recipients: the key is determined by the algorithm and key at the current layer. Examples are key transport keys (Section 12.3), key wrap keys (Section 12.2.1), or pre-shared secrets ๐ฅ
Direct Encryption and Direct Key Agreement: the key is determined by the key and algorithm in the recipient structure. The encryption algorithm and key size are inputs into the KDF used for the recipient. (For direct, the KDF is basically the identity operation ๐) Examples of these algorithms are in Sections 12.1.2 and 12.4.1 โจ
Other: the key is determined by decoding and decrypting one of the recipient structures ๐
- Call the decryption algorithm with K (the decryption key to use), C (the ciphertext), and AAD ๐
5.4. How to Encrypt and Decrypt for AE Algorithms ๐ธ
How to encrypt a message: ๐
- Verify that the 'protected' field is empty. ๐ซถ
- Verify that there was no external additional authenticated data supplied for this operation. ๐
- Work out the encryption key. This step depends on the class of recipient algorithm being used. For:
No Recipients: the key is determined by the algorithm and key at the current layer. Examples are key transport keys (Section 12.3), key wrap keys (Section 12.2.1), or pre-shared secrets ๐ฅ
Direct Encryption and Direct Key Agreement: the key is determined by the key and algorithm in the recipient structure. The encryption algorithm and key size are inputs into the KDF used for the recipient. (For direct, the KDF is basically the identity operation ๐) Examples of these algorithms are in Sections 12.1.2 and 12.4.1 โจ
Other: the key is randomly generated ๐ฒ
- Call the encryption algorithm with K (the encryption key to use) and P (the plaintext). Put the returned ciphertext into the 'ciphertext' field of the structure ๐
- For recipients of the message, recursively perform the encryption algorithm for that recipient, using K (the encryption key) as the plaintext ๐
How to decrypt a message: ๐ฆ
- Verify that the 'protected' field is empty. ๐ซถ
- Verify that there was no external additional authenticated data supplied for this operation. ๐
- Work out the decryption key. This step depends on the class of recipient algorithm being used. For:
No Recipients: the key is determined by the algorithm and key at the current layer. Examples are key transport keys (Section 12.3), key wrap keys (Section 12.2.1), or pre-shared secrets ๐ฅ
Direct Encryption and Direct Key Agreement: the key is determined by the key and algorithm in the recipient structure. The encryption algorithm and key size are inputs into the KDF used for the recipient. (For direct, the KDF is basically the identity operation ๐) Examples of these algorithms are in Sections 12.1.2 and 12.4.1 โจ
Other: the key is determined by decoding and decrypting one of the recipient structures ๐
- Call the decryption algorithm with K (the decryption key to use) and C (the ciphertext). ๐
6. MAC Objects ๐ฆ
COSE has two MAC structures. COSE_MAC0 is used when a recipient structure isn't needed because the key is implicitly known. COSE_MAC is used for all other cases, like needing multiple recipients, the key being unknown, or a recipient algorithm other than direct ๐
This section describes the structure and methods for doing MAC authentication in COSE. This document lets you use all the same classes of recipient algorithms that are allowed for encryption โจ
MAC operations come in two modes ๐ The first just checks that the content hasn't changed since the MAC was computed, and any class of recipient algorithm can do that. The second mode checks that the content hasn't changed AND uses the recipient algorithm to verify who sent it. The classes that support this are the ones that use a pre-shared secret or do static-static (SS) key agreement (without the key wrap step) ๐ฅ In both of these cases, the entity that created and sent the MAC can be validated. (This knowledge of the sender assumes there are only two parties involved, and that you didn't send the message to yourself ๐) Both MAC message structures can get the origination property ๐
6.1. MACed Message with Recipients ๐ธ
The multiple recipient MACed message uses two structures: the COSE_Mac structure defined in this section, which carries the body, and the COSE_recipient structure (Section 5.1), which holds the key used for the MAC computation. You can find examples of MACed messages in Appendix C.5 ๐ง
The MAC structure can be encoded as tagged or untagged, depending on the context it's used in. A tagged COSE_Mac structure is identified by the CBOR tag 97. The CDDL fragment for this is:
COSE_Mac_Tagged = #6.97(COSE_Mac)
The COSE_Mac structure is a CBOR array. The fields of the array, in order, are:
protected: this is as described in Section 3. ๐ซถ
unprotected: this is as described in Section 3. ๐ซถ
payload: this field contains the serialized content to be MACed. If the payload isn't present in the message, the application is required to supply the payload separately. The payload is wrapped in a bstr so it's transported without changes. If the payload is transported separately (i.e., detached content), a nil CBOR value goes in this location, and it's the application's responsibility to make sure it gets transported without changes ๐
tag: this field contains the MAC value. ๐
recipients: this is as described in Section 5.1. ๐
The CDDL fragment that represents the text above for COSE_Mac is:
COSE_Mac = [
Headers,
payload : bstr / nil,
tag : bstr,
recipients :[+COSE_recipient]
]
6.2. MACed Messages with Implicit Key ๐ง
In this section we describe the structure and methods for doing MAC authentication when the recipient is implicitly known ๐
The MACed message uses the COSE_Mac0 structure defined in this section to carry the body. You can find examples of MACed messages with an implicit key in Appendix C.6 โจ
The MAC structure can be encoded as tagged or untagged, depending on the context it's used in. A tagged COSE_Mac0 structure is identified by the CBOR tag 17. The CDDL fragment for this is:
COSE_Mac0_Tagged = #6.17(COSE_Mac0)
The COSE_Mac0 structure is a CBOR array. The fields of the array, in order, are:
protected: this is as described in Section 3. ๐ซถ
unprotected: this is as described in Section 3. ๐ซถ
payload: this is as described in Section 6.1. ๐
tag: this field contains the MAC value. ๐
The CDDL fragment that corresponds to the text above is:
COSE_Mac0 = [
Headers,
payload : bstr / nil,
tag : bstr,
]
6.3. How to Compute and Verify a MAC
okay so bestie, to get a consistent encoding of the data we're authenticating, we use the MAC_structure ๐ It's basically a canonical form, so both sides build the exact same bytes. The MAC_structure is a CBOR array, and its fields go in this order:
- A text string that names the structure being encoded. It's
"MAC"for the COSE_Mac structure and"MAC0"for the COSE_Mac0 structure. - The protected attributes from the COSE_MAC structure. If there are no protected attributes, a zero-length bstr is used ๐ซถ
- The protected attributes from the application, encoded as a bstr type. If this field isn't supplied, it defaults to a zero-length binary string. (See Section 4.3 for application guidance on constructing this field ๐ )
- The payload to be MACed, encoded in a bstr type. The payload goes here no matter how it's transported โจ
The CDDL fragment that matches all of that is:
MAC_structure = [
context : "MAC" / "MAC0",
protected : empty_or_serialized_map,
external_aad : bstr,
payload : bstr
]
The steps to compute a MAC are:
- Create a MAC_structure and fill it with the appropriate fields.
- Create the value ToBeMaced by encoding the MAC_structure to a byte stream, using the encoding described in Section 14.
- Call the MAC creation algorithm, passing in K (the key to use), alg (the algorithm to MAC with), and ToBeMaced (the value to compute the MAC on).
- Place the resulting MAC in the
tagfield of the COSE_Mac or COSE_Mac0 structure. - Encrypt and encode the MAC key for each recipient of the message. ๐
The steps to verify a MAC are:
- Create a MAC_structure object and fill it with the appropriate fields.
- Create the value ToBeMaced by encoding the MAC_structure to a byte stream, using the encoding described in Section 14.
- Obtain the cryptographic key from one of the recipients of the message.
- Call the MAC creation algorithm, passing in K (the key to use), alg (the algorithm to MAC with), and ToBeMaced (the value to compute the MAC on).
- Compare the MAC value to the
tagfield of the COSE_Mac or COSE_Mac0 structure. ๐ง
7. Key Objects โจ
okay so a COSE Key structure is built on a CBOR map object ๐๏ธ The common parameters that can show up in a COSE Key are listed in the IANA "COSE Key Common Parameters" registry (Section 16.5). Extra parameters for specific key types live in the IANA "COSE Key Type Parameters" registry (Section 16.6). Iconic organization, honestly ๐
A COSE Key Set uses a CBOR array object as its underlying type, and its array elements are COSE Keys. A COSE Key Set MUST have at least one element in the array. Examples of COSE Key Sets can be found in Appendix C.7 ๐ธ
Each element in a COSE Key Set MUST be processed independently. If one element is either malformed or uses a key that an application doesn't understand, that key gets ignored and the other keys are processed normally. It's giving "one bad apple doesn't spoil the bunch" ๐
The element "kty" is a required element in a COSE_Key map.
The CDDL grammar describing COSE_Key and COSE_KeySet is:
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]
7.1. COSE Key Common Parameters
this document defines a set of common parameters for a COSE Key object ๐ Table 3 sums up the parameters covered in this section. There are also parameters defined for specific key types, and those can be found in Section 13 ๐ฆ
+---------+-------+----------------+------------+-------------------+
| Name | Label | CBOR Type | Value | Description |
| | | | Registry | |
+---------+-------+----------------+------------+-------------------+
| kty | 1 | tstr / int | COSE Key | Identification of |
| | | | Common | the key type |
| | | | Parameters | |
| | | | | |
| kid | 2 | bstr | | Key |
| | | | | identification |
| | | | | value -- match to |
| | | | | kid in message |
| | | | | |
| alg | 3 | tstr / int | COSE | Key usage |
| | | | Algorithms | restriction to |
| | | | | this algorithm |
| | | | | |
| key_ops | 4 | [+ (tstr/int)] | | Restrict set of |
| | | | | permissible |
| | | | | operations |
| | | | | |
| Base IV | 5 | bstr | | Base IV to be |
| | | | | xor-ed with |
| | | | | Partial IVs |
+---------+-------+----------------+------------+-------------------+
Table 3: Key Map Labels
kty: this parameter identifies the family of keys for this structure and, therefore, the set of key-type-specific parameters you'll find with it. The values defined in this document are in Table 21. This parameter MUST be present in a key object. Implementations MUST verify that the key type is appropriate for the algorithm being processed. The key type MUST be included as part of the trust decision process. Big security energy here ๐ก๏ธ
alg: this parameter restricts the algorithm used with the key. If it's present in the key structure, the application MUST verify that this algorithm matches the algorithm the key is being used for. If the algorithms don't match, this key object MUST NOT be used to perform the cryptographic operation. ngl, the same key can sit in a different key structure with a different algorithm or none at all, but this is considered a poor security practice ๐
kid: this parameter gives an identifier for a key. The identifier isn't structured and can be anything from a user-provided string to a value computed on the public portion of the key ๐ชช It's meant for matching against a 'kid' parameter in a message, so you can filter down the set of keys that need checking. Main character filtering energy โจ
key_ops: this parameter restricts the set of operations a key is used for. Its value is an array of values from Table 4. Algorithms define which key ops values are permitted to appear and which are required for specific operations. The set of values matches the ones in [RFC7517] and [W3C.WebCrypto] ๐
Base IV: this parameter carries the base portion of an IV. It's designed to be used with the Partial IV header parameter defined in Section 3.1. It lets you tie a Partial IV to a key that then gets modified per message using that Partial IV ๐ฆ
Extreme care needs to be taken when using a Base IV in an application. Many encryption algorithms lose security if the same IV is used twice. ๐ญ๐จ
If different keys are derived for each sender, using the same Base IV with Partial IVs starting at zero is likely to keep the IV from being used twice for a single key. If different keys are derived for each sender, starting at the same Base IV is likely to meet that condition too. If the same key is used for multiple senders, the application needs a way to divide up the IV space between them. That could mean starting from a different base point, or starting with a different Partial IV, and restricting how many messages get sent before rekeying ๐
Here's the Key Operation Values table, which is what key_ops draws from:
+---------+-------+-------------------------------------------------+
| Name | Value | Description |
+---------+-------+-------------------------------------------------+
| sign | 1 | The key is used to create signatures. Requires |
| | | private key fields. |
| verify | 2 | The key is used for verification of signatures. |
| encrypt | 3 | The key is used for key transport encryption. |
| decrypt | 4 | The key is used for key transport decryption. |
| | | Requires private key fields. |
| wrap | 5 | The key is used for key wrap encryption. |
| key | | |
| unwrap | 6 | The key is used for key wrap decryption. |
| key | | Requires private key fields. |
| derive | 7 | The key is used for deriving keys. Requires |
| key | | private key fields. |
| derive | 8 | The key is used for deriving bits not to be |
| bits | | used as a key. Requires private key fields. |
| MAC | 9 | The key is used for creating MACs. |
| create | | |
| MAC | 10 | The key is used for validating MACs. |
| verify | | |
+---------+-------+-------------------------------------------------+
Table 4: Key Operation Values
8. Signature Algorithms โจ
okay so there are two signature algorithm schemes ๐ The first is signature with appendix. The message content gets processed, a signature gets produced, and that signature is called the appendix ๐ This is the scheme used by algorithms like ECDSA and RSASSA-PSS. (Fun fact: the SSA in RSASSA-PSS literally stands for Signature Scheme with Appendix ๐ค)
The signature functions for this scheme are:
signature = Sign(message content, key)
valid = Verification(message content, key, signature)
The second is signature with message recovery (an example is [PVSig] ๐ฆ). Here the message content still gets processed, but part of it gets tucked inside the signature. Moving bytes of the message into the signature makes the signatures smaller ๐ The signature can still be pretty big, but the message content has shrunk. That has real consequences for systems and apps using these algorithms ๐
First, the message content isn't fully available until after a signature has been validated. Until then, the part sitting inside the signature is unrecoverable ๐ญ
Second, the security analysis of how strong the signature is depends heavily on the structure of the message content. Messages that are super predictable need extra randomness supplied as part of the signature process. In the worst case it ends up the same as a signature with appendix ๐
Last one: if multiple signatures are applied to one message, all of the signature algorithms have to consume the same number of bytes of message content ๐ So mixing different schemes in a single message isn't supported, and if a recovery scheme is used, every one of the signatures needs to consume the same amount of content.
The signature functions for this scheme are:
signature, message sent = Sign(message content, key)
valid, message content = Verification(message sent, key, signature)
Signature algorithms get used with the COSE_Signature and COSE_Sign1 structures โจ Right now, only signatures with appendixes are defined for use with COSE. BUT lots of people have shown interest in signature with message recovery algorithms because of the possible size reduction ๐คฉ Implementations will need to keep this in mind for later integration ๐ซถ
8.1. ECDSA
ECDSA [DSS] defines a signature algorithm using ECC ๐ธ Implementations SHOULD use a deterministic version of ECDSA, such as the one defined in [RFC6979] ๐ Why? A deterministic signature algorithm means systems don't have to rely on random number generators to avoid generating the same value of 'k' (the per-message random value). Biased generation of the value 'k' can be attacked, and collisions of this value lead to leaked keys ๐ It also allows for doing deterministic tests on the signature algorithm ๐ Just remember: using deterministic ECDSA doesn't lessen the need for good random number generation when you create the private key!
The ECDSA signature algorithm is parameterized with a hash function (h). If the length of the hash function output is greater than the group of the key, the leftmost bytes of the hash output are used โ๏ธ
The algorithms defined in this document can be found in Table 5 ๐
+-------+-------+---------+------------------+
| Name | Value | Hash | Description |
+-------+-------+---------+------------------+
| ES256 | -7 | SHA-256 | ECDSA w/ SHA-256 |
| ES384 | -35 | SHA-384 | ECDSA w/ SHA-384 |
| ES512 | -36 | SHA-512 | ECDSA w/ SHA-512 |
+-------+-------+---------+------------------+
Table 5: ECDSA Algorithm Values
This document defines ECDSA to work only with the curves P-256, P-384, and P-521 ๐ This document requires that the curves be encoded using the 'EC2' (2 coordinate elliptic curve) key type. Implementations need to check that the key type and curve are correct when creating and verifying a signature ๐ Other documents can define it to work with other curves and points in the future ๐ซ
In order to promote interoperability, it is suggested that SHA-256 be used only with curve P-256, SHA-384 be used only with curve P-384, and SHA-512 be used with curve P-521. This lines up with the recommendation in Section 4 of [RFC5480] ๐
The signature algorithm results in a pair of integers (R, S). These integers will be the same length as the length of the key used for the signature process. The signature is encoded by converting the integers into byte strings of the same length as the key size. The length is rounded up to the nearest byte and is left padded with zero bits to get to the correct length. The two integers are then concatenated together to form a byte string, and that's your resulting signature ๐ง
Using the function defined in [RFC8017], the signature is:
Signature = I2OSP(R, n) | I2OSP(S, n)
where n = ceiling(key_length / 8)
When using a COSE key for this algorithm, the following checks are made:
- The
ktyfield MUST be present, and it MUST be'EC2'. - If the
algfield is present, it MUST match the ECDSA signature algorithm being used. - If the
key_opsfield is present, it MUST include'sign'when creating an ECDSA signature. - If the
key_opsfield is present, it MUST include'verify'when verifying an ECDSA signature.
8.1.1. Security Considerations
The security strength of the signature is no greater than the minimum of the security strength associated with the bit length of the key and the security strength of the hash function ๐
Note: Use of this technique is a good idea even when good random number generation exists. Doing so both reduces the possibility of having the same value of 'k' in two signature operations and allows for reproducible signature values, which helps testing. ๐
There are two substitution attacks that can theoretically be mounted against the ECDSA signature algorithm ๐ณ
- Changing the curve used to validate the signature: If one changes the curve used to validate the signature, then potentially one could have two messages with the same signature, each computed under a different curve. The only requirement on the new curve is that its order be the same as the old one and it be acceptable to the client. An example would be to change from using the curve secp256r1 (aka P-256) to using secp256k1. (Both are 256-bit curves.) We currently do not have any way to deal with this version of the attack except to restrict the overall set of curves that can be used. ๐จ
- Change the hash function used to validate the signature: If one either has two different hash functions of the same length or can truncate a hash function down, then one could potentially find collisions between the hash functions rather than within a single hash function (for example, truncating SHA-512 to 256 bits might collide with a SHA-256 bit hash value). As the hash algorithm is part of the signature algorithm identifier, this attack is mitigated by including a signature algorithm identifier in the protected header. ๐ก๏ธ
8.2. Edwards-Curve Digital Signature Algorithms (EdDSAs)
[RFC8032] describes the elliptic curve signature scheme Edwards-curve Digital Signature Algorithm (EdDSA) ๐ In that document, the signature algorithm is instantiated using parameters for the edwards25519 and edwards448 curves. It also describes two variants of the EdDSA algorithm: Pure EdDSA, where no hash function is applied to the content before signing, and HashEdDSA, where a hash function is applied to the content before signing and the result of that hash function is signed. For EdDSA, the content to be signed (either the message or the pre-hash value) is processed twice inside of the signature algorithm ๐คฏ
For use with COSE, only the pure EdDSA version is used. This is because extremely large contents aren't expected to be needed, and based on how the message structure is arranged, the entire message has to be held in memory to create or verify a signature. So there doesn't appear to be a need to do block updates of the hash followed by dropping the message from memory ๐ง Applications can provide the same features by defining the content of the message as a hash value and transporting the COSE object (with the hash value) and the content as separate items ๐ฆ
The algorithms defined in this document can be found in Table 6. A single signature algorithm is defined, which can be used for multiple curves ๐
+-------+-------+-------------+
| Name | Value | Description |
+-------+-------+-------------+
| EdDSA | -8 | EdDSA |
+-------+-------+-------------+
Table 6: EdDSA Algorithm Values
[RFC8032] describes the method of encoding the signature value ๐๏ธ
When using a COSE key for this algorithm, the following checks are made:
- The
ktyfield MUST be present, and it MUST be'OKP'(Octet Key Pair). - The
crvfield MUST be present, and it MUST be a curve defined for this signature algorithm. - If the
algfield is present, it MUST match'EdDSA'. - If the
key_opsfield is present, it MUST include'sign'when creating an EdDSA signature. - If the
key_opsfield is present, it MUST include'verify'when verifying an EdDSA signature.
8.2.1. Security Considerations
How public values are computed is not the same when looking at EdDSA and Elliptic Curve Diffie-Hellman (ECDH) ๐ for this reason, they should not be used with the other algorithm.
If batch signature verification is performed, a well-seeded cryptographic random number generator is REQUIRED. Signing and non-batch signature verification are deterministic operations and do not need random numbers of any kind ๐ฒ
9. Message Authentication Code (MAC) Algorithms ๐
Message Authentication Codes (MACs) provide data authentication and integrity protection ๐ก๏ธ They provide either no or very limited data origination. A MAC, for example, can be used to prove the identity of the sender to a third party ๐ต๏ธ
MACs use the same scheme as signature with appendix algorithms. The message content is processed and an authentication code is produced. The authentication code is frequently called a tag ๐ท๏ธ
The MAC functions are:
tag = MAC_Create(message content, key)
valid = MAC_Verify(message content, key, tag)
MAC algorithms can be based on either a block cipher algorithm (i.e., AES-MAC) or a hash algorithm (i.e., a Hash-based Message Authentication Code (HMAC)). This document defines a MAC algorithm using each of these constructions ๐งฉ
MAC algorithms are used in the COSE_Mac and COSE_Mac0 structures ๐
9.1. Hash-Based Message Authentication Codes (HMACs) ๐
Okay so HMAC [RFC2104] [RFC4231] was built to handle length extension attacks ๐ โโ๏ธ. It also lets new hash algorithms get plugged in without changing the hash function itself, which is so clean. The HMAC design has held up really well over time, even though the security of hash algorithms like MD5 has dropped. Nobody has shown HMAC combined with MD5 to be compromised yet [RFC6151] โจ.
The HMAC algorithm has three main pieces: an inner and outer padding, a hash function (h), and an authentication tag value length. For this spec, the padding is locked to the values set in [RFC2104]. The tag length tells you how hard a forgery is to pull off ๐. For constrained environments, we define a set of truncated HMAC algorithms ๐ฆ.
There are no known issues with truncation, but the strength of the tag goes down along with the length. When you truncate, you keep the leftmost tag length bits and send those ๐ .
The algorithms defined in this document can be found in Table 7.
+-----------+-------+---------+----------+--------------------------+
| Name | Value | Hash | Tag | Description |
| | | | Length | |
+-----------+-------+---------+----------+--------------------------+
| HMAC | 4 | SHA-256 | 64 | HMAC w/ SHA-256 |
| 256/64 | | | | truncated to 64 bits |
| HMAC | 5 | SHA-256 | 256 | HMAC w/ SHA-256 |
| 256/256 | | | | |
| HMAC | 6 | SHA-384 | 384 | HMAC w/ SHA-384 |
| 384/384 | | | | |
| HMAC | 7 | SHA-512 | 512 | HMAC w/ SHA-512 |
| 512/512 | | | | |
+-----------+-------+---------+----------+--------------------------+
Table 7: HMAC Algorithm Values
Some recipient algorithms carry the key, and others derive a key from secret data. For the ones that carry the key (like AES Key Wrap), the size of the HMAC key SHOULD be the same size as the underlying hash function. For the ones that derive the key (like ECDH), the derived key MUST be the same size as the underlying hash function ๐ง.
When using a COSE key for this algorithm, the following checks are made:
- The
'kty'field MUST be present, and it MUST be'Symmetric'. - If the
'alg'field is present, it MUST match the HMAC algorithm being used. - If the
'key_ops'field is present, it MUST include'MAC create'when creating an HMAC authentication tag. - If the
'key_ops'field is present, it MUST include'MAC verify'when verifying an HMAC authentication tag.
Implementations creating and validating MAC values MUST validate that the key type, key length, and algorithm are correct and appropriate for the entities involved ๐ซถ.
9.1.1. Security Considerations
HMAC has proved to be resistant to attack even when used with weakened hash algorithms ๐ก๏ธ. The current best known attack is to brute force the key, which means the key size is going to be directly related to the security of an HMAC operation ๐ฅ.
9.2. AES Message Authentication Code (AES-CBC-MAC) ๐ธ
AES-CBC-MAC is defined in [MAC]. (Note that this is not the same algorithm as AES Cipher-Based Message Authentication Code (AES-CMAC) [RFC4493].)
AES-CBC-MAC is parameterized by the key length, the authentication tag length, and the IV used. For all of these algorithms, the IV is fixed to all zeros. We provide an array of algorithms for various key lengths and tag lengths. The algorithms defined in this document are found in Table 8 ๐.
+-------------+-------+----------+----------+-----------------------+
| Name | Value | Key | Tag | Description |
| | | Length | Length | |
+-------------+-------+----------+----------+-----------------------+
| AES-MAC | 14 | 128 | 64 | AES-MAC 128-bit key, |
| 128/64 | | | | 64-bit tag |
| AES-MAC | 15 | 256 | 64 | AES-MAC 256-bit key, |
| 256/64 | | | | 64-bit tag |
| AES-MAC | 25 | 128 | 128 | AES-MAC 128-bit key, |
| 128/128 | | | | 128-bit tag |
| AES-MAC | 26 | 256 | 128 | AES-MAC 256-bit key, |
| 256/128 | | | | 128-bit tag |
+-------------+-------+----------+----------+-----------------------+
Table 8: AES-MAC Algorithm Values
Keys may be obtained either from a key structure or from a recipient structure. Implementations creating and validating MAC values MUST validate that the key type, key length, and algorithm are correct and appropriate for the entities involved ๐.
When using a COSE key for this algorithm, the following checks are made:
- The
'kty'field MUST be present, and it MUST be'Symmetric'. - If the
'alg'field is present, it MUST match the AES-MAC algorithm being used. - If the
'key_ops'field is present, it MUST include'MAC create'when creating an AES-MAC authentication tag. - If the
'key_ops'field is present, it MUST include'MAC verify'when verifying an AES-MAC authentication tag.
9.2.1. Security Considerations
Okay, this part is serious bestie ๐ญ. A number of attacks exist against Cipher Block Chaining Message Authentication Code (CBC-MAC) that you need to think about.
- A single key must only be used for messages of a fixed and known length. If this is not the case, an attacker will be able to generate a message with a valid tag given two message and tag pairs. This can be addressed by using different keys for messages of different lengths. The current structure mitigates this problem, as a specific encoding structure that includes lengths is built and signed. (CMAC also addresses this issue.) ๐
- Cipher Block Chaining (CBC) mode: if the same key is used for both encryption and authentication operations, an attacker can produce messages with a valid authentication code ๐.
- If the IV can be modified, then messages can be forged. This is addressed by fixing the IV to all zeros ๐.
10. Content Encryption Algorithms ๐
Content encryption algorithms provide data confidentiality for potentially large blocks of data using a symmetric key ๐. They provide integrity on the data that was encrypted, but they provide either no or very limited data origination. (One cannot, for example, be used to prove the identity of the sender to a third party.) The ability to provide data origination is linked to how the CEK is obtained ๐.
COSE restricts the set of legal content encryption algorithms to those that support authentication of both the content and additional data. The encryption process will generate some type of authentication value, but that value may be either explicit or implicit in terms of the algorithm definition. For simplicity's sake, the authentication code will normally be defined as being appended to the ciphertext stream. The encryption functions are:
ciphertext = Encrypt(message content, key, additional data)
valid, message content = Decrypt(cipher text, key, additional data)
Most AEAD algorithms are logically defined as returning the message content only if the decryption is valid. Many but not all implementations will follow this convention. The message content MUST NOT be used if the decryption does not validate ๐ซ.
These algorithms are used in COSE_Encrypt and COSE_Encrypt0.
10.1. AES GCM โจ
The Galois/Counter Mode (GCM) is a generic authenticated encryption block cipher mode defined in [AES-GCM]. The GCM mode is combined with the AES block encryption algorithm to define an AEAD cipher ๐ฆ.
The GCM mode is parameterized by the size of the authentication tag and the size of the nonce. This document fixes the size of the nonce at 96 bits. The size of the authentication tag is limited to a small set of values. For this document, however, the size of the authentication tag is fixed at 128 bits ๐.
The set of algorithms defined in this document are in Table 9.
+---------+-------+------------------------------------------+
| Name | Value | Description |
+---------+-------+------------------------------------------+
| A128GCM | 1 | AES-GCM mode w/ 128-bit key, 128-bit tag |
| A192GCM | 2 | AES-GCM mode w/ 192-bit key, 128-bit tag |
| A256GCM | 3 | AES-GCM mode w/ 256-bit key, 128-bit tag |
+---------+-------+------------------------------------------+
Table 9: Algorithm Value for AES-GCM
Keys may be obtained either from a key structure or from a recipient structure. Implementations encrypting and decrypting MUST validate that the key type, key length, and algorithm are correct and appropriate for the entities involved ๐ซถ.
When using a COSE key for this algorithm, the following checks are made:
- The
'kty'field MUST be present, and it MUST be'Symmetric'. - If the
'alg'field is present, it MUST match the AES-GCM algorithm being used. - If the
'key_ops'field is present, it MUST include'encrypt'or'wrap key'when encrypting. - If the
'key_ops'field is present, it MUST include'decrypt'or'unwrap key'when decrypting.
10.1.1. Security Considerations
When using AES-GCM, the following restrictions MUST be enforced. This part is a big deal ๐จ.
- The key and nonce pair MUST be unique for every message encrypted.
- The total amount of data encrypted for a single key MUST NOT exceed 2^39 - 256 bits. An explicit check is required only in environments where it is expected that it might be exceeded.
Consideration was given to supporting smaller tag values, since the constrained community would desire tag sizes in the 64-bit range. Doing so drastically changes both the maximum message size (generally not an issue) and the number of times that a key can be used. Given that Counter with CBC-MAC (CCM) is the usual mode for constrained environments, restricted modes are not supported ๐.
10.2. AES CCM
Okay so CCM is a generic authenticated encryption block cipher mode, defined in [RFC3610] ๐. It gets paired with the AES block encryption algorithm to make a super common content encryption algorithm, and it's especially popular with constrained devices ๐ซถ
CCM has two parameter choices. The first is M, the size of the authentication field. Picking M is a trade-off between how much bigger your message gets from the tag and how likely an attacker is to sneakily modify a message without anyone noticing โจ The second is L, the size of the length field. L is a trade-off too, between the maximum message size you can handle and how long your Nonce is ๐ธ
Ngl, the CCM spec defines L and M as counts of bytes instead of bits, and this causes real confusion ๐ That's why you'll hear AES-CCM-8 used to mean a version where the authentication field is 64 bits, not 8 bits ๐ Traditionally these values have been written as bit counts, so this document sticks with bit counts. That makes it way easier to compare the algorithms in here ๐ฆ
We define a whole matrix of algorithms in this document, one for each combo of L and M ๐ Constrained devices usually send short messages and want to avoid doing recipient-specific crypto operations, so smaller values of both L and M are the move for them. Less-constrained devices want bigger messages and are more okay with generating new keys for every operation, so they like larger values of L and M ๐
The following values are used for L:
- 16 bits (2): This limits messages to 2^16 bytes (64 KiB) in length. That's plenty for messages in the constrained world ๐ The nonce length is 13 bytes, which allows for
2^(13*8)possible values of the nonce without repeating. - 64 bits (8): This limits messages to 2^64 bytes in length. The nonce length is 7 bytes, which allows for
2^56possible values of the nonce without repeating.
The following values are used for M:
- 64 bits (8): This produces a 64-bit authentication tag. That means there's a 1 in 2^64 chance that a modified message will authenticate ๐ญ
- 128 bits (16): This produces a 128-bit authentication tag. That means there's a 1 in 2^128 chance that a modified message will authenticate ๐ฅ
+--------------------+-------+----+-----+-----+---------------------+
| Name | Value | L | M | k | Description |
+--------------------+-------+----+-----+-----+---------------------+
| AES-CCM-16-64-128 | 10 | 16 | 64 | 128 | AES-CCM mode |
| | | | | | 128-bit key, 64-bit |
| | | | | | tag, 13-byte nonce |
| AES-CCM-16-64-256 | 11 | 16 | 64 | 256 | AES-CCM mode |
| | | | | | 256-bit key, 64-bit |
| | | | | | tag, 13-byte nonce |
| AES-CCM-64-64-128 | 12 | 64 | 64 | 128 | AES-CCM mode |
| | | | | | 128-bit key, 64-bit |
| | | | | | tag, 7-byte nonce |
| AES-CCM-64-64-256 | 13 | 64 | 64 | 256 | AES-CCM mode |
| | | | | | 256-bit key, 64-bit |
| | | | | | tag, 7-byte nonce |
| AES-CCM-16-128-128 | 30 | 16 | 128 | 128 | AES-CCM mode |
| | | | | | 128-bit key, |
| | | | | | 128-bit tag, |
| | | | | | 13-byte nonce |
| AES-CCM-16-128-256 | 31 | 16 | 128 | 256 | AES-CCM mode |
| | | | | | 256-bit key, |
| | | | | | 128-bit tag, |
| | | | | | 13-byte nonce |
| AES-CCM-64-128-128 | 32 | 64 | 128 | 128 | AES-CCM mode |
| | | | | | 128-bit key, |
| | | | | | 128-bit tag, 7-byte |
| | | | | | nonce |
| AES-CCM-64-128-256 | 33 | 64 | 128 | 256 | AES-CCM mode |
| | | | | | 256-bit key, |
| | | | | | 128-bit tag, 7-byte |
| | | | | | nonce |
+--------------------+-------+----+-----+-----+---------------------+
Table 10: Algorithm Values for AES-CCM
Keys can come from either a key structure or a recipient structure ๐ Implementations encrypting and decrypting MUST validate that the key type, key length, and algorithm are correct and appropriate for the entities involved. No skipping this, bestie ๐
When using a COSE key for this algorithm, these checks happen:
- The
'kty'field MUST be present, and it MUST be'Symmetric'. - If the
'alg'field is present, it MUST match the AES-CCM algorithm being used. - If the
'key_ops'field is present, it MUST include'encrypt'or'wrap key'when encrypting. - If the
'key_ops'field is present, it MUST include'decrypt'or'unwrap key'when decrypting.
10.2.1. Security Considerations
When using AES-CCM, the following restrictions MUST be enforced ๐จ
- The key and nonce pair MUST be unique for every message encrypted. Also, the value of L affects how many unique nonces you get, so keep that in mind ๐
- The total number of times the AES block cipher is used MUST NOT exceed 2^61 operations. This limit is the sum of the times the block cipher gets used for computing the MAC value and for doing stream encryption operations. An explicit check is required only in environments where it's expected that it might be exceeded.
[RFC3610] calls out one more thing that's worth knowing. There's a possible pre-computation attack against the algorithm when parts of the plaintext are super predictable ๐ฑ It can cut the security of the key size in half. Ways to deal with it include adding a random portion to the nonce value and/or increasing the key size. Using part of the nonce for a random value reduces how many messages a single key can be used for. Increasing the key size may need more resources on the constrained device. See Sections 5 and 10 of [RFC3610] for more information.
10.3. ChaCha20 and Poly1305
ChaCha20 and Poly1305 together form an AEAD mode defined in [RFC7539] ๐ฆ It's a cipher that is not AES, so it wouldn't suffer from any future weaknesses found in AES. Its cryptographic functions are designed to be fast in software-only implementations, which is giving speed ๐โโ๏ธ
The ChaCha20/Poly1305 AEAD construction defined in [RFC7539] has no parameterization. It takes a 256-bit key and a 96-bit nonce, plus the plaintext and additional data as inputs, and it produces the ciphertext as an output. We define one algorithm identifier for this algorithm in Table 11 ๐ง
+-------------------+-------+---------------------------------------+
| Name | Value | Description |
+-------------------+-------+---------------------------------------+
| ChaCha20/Poly1305 | 24 | ChaCha20/Poly1305 w/ 256-bit key, |
| | | 128-bit tag |
+-------------------+-------+---------------------------------------+
Table 11: Algorithm Value for AES-GCM
Keys can come from either a key structure or a recipient structure. Implementations encrypting and decrypting MUST validate that the key type, key length, and algorithm are correct and appropriate for the entities involved ๐ซถ
When using a COSE key for this algorithm, these checks happen:
- The
'kty'field MUST be present, and it MUST be'Symmetric'. - If the
'alg'field is present, it MUST match the ChaCha20/Poly1305 algorithm being used. - If the
'key_ops'field is present, it MUST include'encrypt'or'wrap key'when encrypting. - If the
'key_ops'field is present, it MUST include'decrypt'or'unwrap key'when decrypting.
10.3.1. Security Considerations
The key and nonce values MUST be a unique pair for every invocation of the algorithm ๐ Nonce counters are considered an acceptable way of making sure they're unique โจ
11. Key Derivation Functions (KDFs)
KDFs take some secret value and generate a different one ๐ The secret value comes in three flavors:
- Secrets that are uniformly random: This is the kind of secret a good random number generator creates.
- Secrets that are not uniformly random: This is the kind of secret created by operations like key agreement.
- Secrets that are not random: This is the kind of secret people come up with for things like passwords ๐
General KDFs work well with the first flavor, can do reasonably well with the second, and generally do poorly with the last one. None of the KDFs in this section are designed for password-style secrets. Functions like PBES2 [RFC8018] need to be used for that kind of secret ๐
The same KDF can be set up to handle the first two flavors of secrets in different ways. The KDF defined in Section 11.1 is one such function. This is reflected in the set of algorithms defined for the HMAC-based Extract-and-Expand Key Derivation Function (HKDF) ๐ฆ
When using KDFs, one component that gets included is context information. Context information lets you derive different keying information from the same secret, and using context-based keying material is considered a really good security practice ๐
This document defines a single context structure and a single KDF. These elements are used for all of the recipient algorithms defined in this document that require a KDF process. Those algorithms are defined in Sections 12.1.2, 12.4.1, and 12.5.1 โจ
11.1. HMAC-Based Extract-and-Expand Key Derivation Function (HKDF) ๐
okay bestie, the HKDF key derivation algorithm is defined in [RFC5869] ๐ so that's where you go for the full tea.
The HKDF algorithm takes these inputs:
- secret -- a shared value that is secret. Secrets may be either previously shared or derived from operations like a Diffie-Hellman (DH) key agreement ๐
- salt -- an optional value that is used to change the generation process. The salt value can be either public or private. If the salt is public and carried in the message, then the 'salt' algorithm header parameter defined in Table 13 is used. While [RFC5869] suggests that the length of the salt be the same as the length of the underlying hash value, any amount of salt will improve the security as different key values will be generated. This parameter is protected by being included in the key computation and does not need to be separately authenticated. The salt value does not need to be unique for every message sent โจ
- length -- the number of bytes of output that need to be generated ๐
- context information -- information that describes the context in which the resulting value will be used. Making this information specific to the context in which the material is going to be used ensures that the resulting material will always be tied to that usage. The context structure defined in Section 11.2 is used by the KDFs in this document ๐ง
- PRF -- the underlying pseudorandom function to be used in the HKDF algorithm. The PRF is encoded into the HKDF algorithm selection ๐
HKDF is defined to use HMAC as the underlying PRF. However, it is possible to use other functions in the same construct to provide a different KDF that is more appropriate in the constrained world. Specifically, one can use AES-CBC-MAC as the PRF for the expand step, but not for the extract step. When using a good random shared secret of the correct length, the extract step can be skipped. For the AES algorithm versions, the extract step is always skipped ๐ฆ
The extract step cannot be skipped if the secret is not uniformly random, for example, if it is the result of an ECDH key agreement step. This implies that the AES HKDF version cannot be used with ECDH. If the extract step is skipped, the 'salt' value is not used as part of the HKDF functionality ๐
The algorithms defined in this document are found in Table 12 ๐
+---------------+-----------------+---------------------------------+
| Name | PRF | Description |
+---------------+-----------------+---------------------------------+
| HKDF SHA-256 | HMAC with | HKDF using HMAC SHA-256 as the |
| | SHA-256 | PRF |
| HKDF SHA-512 | HMAC with | HKDF using HMAC SHA-512 as the |
| | SHA-512 | PRF |
| HKDF AES- | AES-CBC-MAC-128 | HKDF using AES-MAC as the PRF |
| MAC-128 | | w/ 128-bit key |
| HKDF AES- | AES-CBC-MAC-256 | HKDF using AES-MAC as the PRF |
| MAC-256 | | w/ 256-bit key |
+---------------+-----------------+---------------------------------+
Table 12: HKDF Algorithms
+------+-------+------+-------------------------------+-------------+
| Name | Label | Type | Algorithm | Description |
+------+-------+------+-------------------------------+-------------+
| salt | -20 | bstr | direct+HKDF-SHA-256, direct | Random salt |
| | | | +HKDF-SHA-512, direct+HKDF- | |
| | | | AES-128, direct+HKDF-AES-256, | |
| | | | ECDH-ES+HKDF-256, ECDH- | |
| | | | ES+HKDF-512, ECDH- | |
| | | | SS+HKDF-256, ECDH- | |
| | | | SS+HKDF-512, ECDH-ES+A128KW, | |
| | | | ECDH-ES+A192KW, ECDH- | |
| | | | ES+A256KW, ECDH-SS+A128KW, | |
| | | | ECDH-SS+A192KW, ECDH- | |
| | | | SS+A256KW | |
+------+-------+------+-------------------------------+-------------+
Table 13: HKDF Algorithm Parameters
11.2. Context Information Structure ๐ธ
the context information structure is how we make sure the derived keying material is "bound" to the context of the transaction ๐ it's based on the one defined in [SP800-56A], and since we're using CBOR for the encoding, we automatically get the same type and length separation of fields that you'd get with ASN.1. so there's no need to encode the lengths for the base elements, which is what the encoding in JOSE does (Section 4.6.2 of [RFC7518]) ๐
the context information structure refers to PartyU and PartyV as the two parties doing the key derivation. Unless the application protocol defines differently, we assign PartyU to the entity that is creating the message and PartyV to the entity that is receiving the message. Because of this association, different keys will be derived for each direction since the context information is different in each direction ๐ฆ
the context structure is built from information that is known to both entities. This information can be obtained from a variety of sources:
- Fields can be defined by the application. This is commonly used to assign fixed names to parties, but it can be used for other items such as nonces ๐
- Fields can be defined by usage of the output. Examples of this are the algorithm and key size that are being generated ๐
- Fields can be defined by parameters from the message. We define a set of parameters in Table 14 that can be used to carry the values associated with the context structure. Examples of this are identities and nonce values. These parameters are designed to be placed in the unprotected bucket of the recipient structure; they do not need to be in the protected bucket since they already are included in the cryptographic computation by virtue of being included in the context structure ๐งโจ
+----------+-------+------+---------------------------+-------------+
| Name | Label | Type | Algorithm | Description |
+----------+-------+------+---------------------------+-------------+
| PartyU | -21 | bstr | direct+HKDF-SHA-256, | Party U |
| identity | | | direct+HKDF-SHA-512, | identity |
| | | | direct+HKDF-AES-128, | information |
| | | | direct+HKDF-AES-256, | |
| | | | ECDH-ES+HKDF-256, ECDH- | |
| | | | ES+HKDF-512, ECDH- | |
| | | | SS+HKDF-256, ECDH- | |
| | | | SS+HKDF-512, ECDH- | |
| | | | ES+A128KW, ECDH- | |
| | | | ES+A192KW, ECDH- | |
| | | | ES+A256KW, ECDH- | |
| | | | SS+A128KW, ECDH- | |
| | | | SS+A192KW, ECDH-SS+A256KW | |
| | | | | |
| PartyU | -22 | bstr | direct+HKDF-SHA-256, | Party U |
| nonce | | / | direct+HKDF-SHA-512, | provided |
| | | int | direct+HKDF-AES-128, | nonce |
| | | | direct+HKDF-AES-256, | |
| | | | ECDH-ES+HKDF-256, ECDH- | |
| | | | ES+HKDF-512, ECDH- | |
| | | | SS+HKDF-256, ECDH- | |
| | | | SS+HKDF-512, ECDH- | |
| | | | ES+A128KW, ECDH- | |
| | | | ES+A192KW, ECDH- | |
| | | | ES+A256KW, ECDH- | |
| | | | SS+A128KW, ECDH- | |
| | | | SS+A192KW, ECDH-SS+A256KW | |
| | | | | |
| PartyU | -23 | bstr | direct+HKDF-SHA-256, | Party U |
| other | | | direct+HKDF-SHA-512, | other |
| | | | direct+HKDF-AES-128, | provided |
| | | | direct+HKDF-AES-256, | information |
| | | | ECDH-ES+HKDF-256, ECDH- | |
| | | | ES+HKDF-512, ECDH- | |
| | | | SS+HKDF-256, ECDH- | |
| | | | SS+HKDF-512, ECDH- | |
| | | | ES+A128KW, ECDH- | |
| | | | ES+A192KW, ECDH- | |
| | | | ES+A256KW, ECDH- | |
| | | | SS+A128KW, ECDH- | |
| | | | SS+A192KW, ECDH-SS+A256KW | |
| PartyV | -24 | bstr | direct+HKDF-SHA-256, | Party V |
| identity | | | direct+HKDF-SHA-512, | identity |
| | | | direct+HKDF-AES-128, | information |
| | | | direct+HKDF-AES-256, | |
| | | | ECDH-ES+HKDF-256, ECDH- | |
| | | | ES+HKDF-512, ECDH- | |
| | | | SS+HKDF-256, ECDH- | |
| | | | SS+HKDF-512, ECDH- | |
| | | | ES+A128KW, ECDH- | |
| | | | ES+A192KW, ECDH- | |
| | | | ES+A256KW, ECDH- | |
| | | | SS+A128KW, ECDH- | |
| | | | SS+A192KW, ECDH-SS+A256KW | |
| | | | | |
| PartyV | -25 | bstr | direct+HKDF-SHA-256, | Party V |
| nonce | | / | direct+HKDF-SHA-512, | provided |
| | | int | direct+HKDF-AES-128, | nonce |
| | | | direct+HKDF-AES-256, | |
| | | | ECDH-ES+HKDF-256, ECDH- | |
| | | | ES+HKDF-512, ECDH- | |
| | | | SS+HKDF-256, ECDH- | |
| | | | SS+HKDF-512, ECDH- | |
| | | | ES+A128KW, ECDH- | |
| | | | ES+A192KW, ECDH- | |
| | | | ES+A256KW, ECDH- | |
| | | | SS+A128KW, ECDH- | |
| | | | SS+A192KW, ECDH-SS+A256KW | |
| | | | | |
| PartyV | -26 | bstr | direct+HKDF-SHA-256, | Party V |
| other | | | direct+HKDF-SHA-512, | other |
| | | | direct+HKDF-AES-128, | provided |
| | | | direct+HKDF-AES-256, | information |
| | | | ECDH-ES+HKDF-256, ECDH- | |
| | | | ES+HKDF-512, ECDH- | |
| | | | SS+HKDF-256, ECDH- | |
| | | | SS+HKDF-512, ECDH- | |
| | | | ES+A128KW, ECDH- | |
| | | | ES+A192KW, ECDH- | |
| | | | ES+A256KW, ECDH- | |
| | | | SS+A128KW, ECDH- | |
| | | | SS+A192KW, ECDH-SS+A256KW | |
+----------+-------+------+---------------------------+-------------+
Table 14: Context Algorithm Parameters
Okay so this is the cheat sheet ๐ for which labels go with which algorithms, and it's giving organised. ๐ Now let's talk about the context info itself, which is literally the bit that stops keys from getting mixed up ๐. We define a CBOR object called COSE_KDF_Context to hold it. It's based on a CBOR array type, and the fields are:
- AlgorithmID: This tells you which algorithm the key material is for. It's usually a key wrap algorithm identifier or a content encryption algorithm identifier, taken from the "COSE Algorithms" registry. This field is required to be present. Why does it exist? If the same environment is used for different algorithms, completely different keys get generated for each one. So if algorithm A gets broken and is easier to find, the key derived for algorithm B won't be the same as the one derived for algorithm A. ๐ก๏ธ Main character energy for keys, honestly.
- PartyUInfo: This holds info about party U. It's encoded as a CBOR array, and its elements are encoded in the order presented. The elements are:
- identity: This is the identity info for party U. Identities can be assigned in one of two ways ๐. First, a protocol can assign identities based on roles, like "client" and "server", so each entity uses the right label for the data it sends or receives. Second, a protocol can use a name from a naming system, like DNS or X.509 names. We define an algorithm parameter 'PartyU identity' that can carry identity info in the message. But identity info is often already known from the protocol, so it can be inferred instead of spelled out. If identity info is carried in the message, applications SHOULD have a way of validating the supplied identity info. If it doesn't need to be specified, it's set to nil. ๐ฆ
- nonce: This is a nonce value. It can be implicit from the protocol, or carried as a value in the unprotected headers. We define an algorithm parameter 'PartyU nonce' that can carry it in the message, but the nonce could also be decided by the application and found somewhere else. This doesn't need to be specified either, and if it isn't, it's set to nil. ๐ธ
- other: This is other info defined by the protocol. It doesn't need to be specified, and if it isn't, it's set to nil. ๐ง
- PartyVInfo: This holds info about party V. It's the same structure as PartyUInfo, just for party V. Twins energy ๐ฏโโ๏ธ
- SuppPubInfo: This is public info that both parties already mutually know. ๐
- keyDataLength: This is set to the number of bits in the desired output value. So if algorithm A can use two different key lengths, the key derived for the longer size won't contain the key for the shorter size as a prefix. Not even a little bit ๐
- protected: This is the protected parameter field. If there are no elements in it, use a zero-length bstr. โจ
- other: This is free-form data defined by the application. For example, an app could put two different strings here so it generates different keys for a data stream versus a control stream. It's optional and only present if the application defines a structure for this info. Applications that define this SHOULD use CBOR to encode the data, so types and lengths are correctly included. ๐
- SuppPrivInfo: This is private info that both parties mutually know. A preexisting shared secret is the classic example. You could combine it with an ECDH key agreement to get a secondary proof of identity, which is so iconic ๐. It's optional and only present if the application defines a structure for it. Applications that define this SHOULD use CBOR to encode the data, so types and lengths are correctly included. ๐ฅ
The following CDDL fragment matches everything above, so you can check your work against it ๐ซถ:
PartyInfo = (
identity : bstr / nil,
nonce : bstr / int / nil,
other : bstr / nil
)
COSE_KDF_Context = [
AlgorithmID : int / tstr,
PartyUInfo : [ PartyInfo ],
PartyVInfo : [ PartyInfo ],
SuppPubInfo : [
keyDataLength : uint,
protected : empty_or_serialized_map,
? other : bstr
],
? SuppPrivInfo : bstr
]
12. Content Key Distribution Methods โจ
Okay bestie, so content key distribution methods are basically the ways you hand over the key that scrambles the message ๐๐ They're also called recipient algorithms, and COSE can handle a whole bunch of different classes of them. This section lists a few classes and then gives you a set of algorithms for each one. The class names match the ones in [RFC7516], and other specs use different terms or skip some classes entirely, so don't be surprised if the vocab changes on you ๐
12.1. Direct Encryption
Direct encryption is giving it "we share a secret and that's the whole plan" energy ๐ฆ The sender and the recipient share a secret, and it gets used either as-is or after some tweaking as the CEK. Real talk: if you're in direct encryption mode, it MUST be the only mode on the message. No mixing it with other modes, periodt ๐ โโ๏ธ
The COSE_Recipient structure for the recipient looks like this:
- The 'protected' field MUST be a zero-length item unless it is used in the computation of the content key.
- The 'alg' parameter MUST be present.
- A parameter identifying the shared secret SHOULD be present.
- The 'ciphertext' field MUST be a zero-length item.
- The 'recipients' field MUST be absent.
12.1.1. Direct Key
This one is the simplest, literally the main character of the recipient algorithms ๐ The identified key just gets used directly as the key for the next layer down in the message. There are no algorithm parameters defined for it, and the algorithm identifier value is assigned in Table 15 ๐ธ
When this algorithm is used, the protected field MUST be zero length. The key type MUST be 'Symmetric' ๐ซถ
+--------+-------+-------------------+
| Name | Value | Description |
+--------+-------+-------------------+
| direct | -6 | Direct use of CEK |
+--------+-------+-------------------+
Table 15: Direct Key
12.1.1.1. Security Considerations
Okay, this one has some potential problems you really need to think about ๐ญ Here they are:
- These keys need to have some method to be regularly updated over time. All of the content encryption algorithms specified in this document have limits on how many times a key can be used without significant loss of security.
- These keys need to be dedicated to a single algorithm. There have been a number of attacks developed over time when a single key is used for multiple different algorithms. One example of this is the use of a single key for both the CBC encryption mode and the CBC-MAC authentication mode.
- Breaking one message means all messages are broken. If an adversary succeeds in determining the key for a single message, then the key for all messages is also determined. ๐
12.1.2. Direct Key with KDF
These recipient algorithms start with a common shared secret between the two parties and run it through the HKDF function (Section 11.1), using the context structure from Section 11.2, to turn it into the CEK ๐ง The 'protected' field can be of non-zero length. Either the 'salt' parameter of HKDF or the 'PartyU nonce' parameter of the context structure MUST be present. The salt/nonce parameter can be generated randomly or deterministically. The requirement is that it be a unique value for the shared secret in question โจ
If the salt/nonce value is generated randomly, it is suggested that the random value be the same length as the hash function underlying HKDF. There's no way to guarantee it'll be unique, but there's a high probability that it will be ๐ฒ If the salt/nonce value is generated deterministically, it can be guaranteed to be unique, so there is no length requirement.
A new IV must be used for each message if the same key is used. The IV can be modified in a predictable manner, a random manner, or an unpredictable manner (i.e., encrypting a counter) ๐
The IV used for a key can also be generated from the same HKDF functionality as the key is generated. If HKDF is used for generating the IV, the algorithm identifier is set to "IV-GENERATION" ๐
When these algorithms are used, the key type MUST be 'symmetric' ๐
The set of algorithms defined in this document can be found in Table 16 ๐
+---------------------+-------+-------------+-----------------------+
| Name | Value | KDF | Description |
+---------------------+-------+-------------+-----------------------+
| direct+HKDF-SHA-256 | -10 | HKDF | Shared secret w/ HKDF |
| | | SHA-256 | and SHA-256 |
| direct+HKDF-SHA-512 | -11 | HKDF | Shared secret w/ HKDF |
| | | SHA-512 | and SHA-512 |
| direct+HKDF-AES-128 | -12 | HKDF AES- | Shared secret w/ AES- |
| | | MAC-128 | MAC 128-bit key |
| direct+HKDF-AES-256 | -13 | HKDF AES- | Shared secret w/ AES- |
| | | MAC-256 | MAC 256-bit key |
+---------------------+-------+-------------+-----------------------+
Table 16: Direct Key with KDF
When using a COSE key for this algorithm, the following checks are made:
- The 'kty' field MUST be present, and it MUST be 'Symmetric'.
- If the 'alg' field is present, it MUST match the algorithm being used.
- If the 'key_ops' field is present, it MUST include 'deriveKey' or 'deriveBits'.
12.1.2.1. Security Considerations
The shared secret needs to have some method to be regularly updated over time. The shared secret forms the basis of trust. Although it's not used directly, it should still be subject to scheduled rotation ๐
These methods don't give you perfect forward secrecy, because the same shared secret is used for all of the keys generated. If the key for any single message gets discovered, only the message (or series of messages) using that derived key is compromised. A new key derivation step will generate a new key that requires the same amount of work to get the key ๐ก๏ธ
12.2. Key Wrap
Key wrap mode is when the CEK gets randomly generated, and then that key is encrypted by a shared secret between the sender and the recipient ๐ All of the currently defined key wrap algorithms for COSE are AE algorithms. Key wrap is considered superior to direct encryption if the system can do random key generation at all. That's because the shared key wraps random data instead of data that's organized and might be repeating the same content. The tradeoff is that key wrap loses the weak data origination that the direct encryption algorithms provide ๐ค
The COSE_Encrypt structure for the recipient is organized as follows:
- The 'protected' field MUST be absent if the key wrap algorithm is an AE algorithm.
- The 'recipients' field is normally absent, but can be used. Applications MUST deal with a recipient field being present; not being able to decrypt that recipient is an acceptable way of dealing with it. Failing to process the message is not an acceptable way of dealing with it. ๐
- The plaintext to be encrypted is the key from next layer down (usually the content layer).
- At a minimum, the 'unprotected' field MUST contain the 'alg' parameter and SHOULD contain a parameter identifying the shared secret.
12.2.1. AES Key Wrap
The AES Key Wrap algorithm is defined in [RFC3394] ๐ It uses an AES key to wrap a value that's a multiple of 64 bits, so it works for wrapping a key for any of the content encryption algorithms defined in this document. The algorithm needs a single fixed parameter, the initial value, which is fixed to the value specified in Section 2.2.3.1 of [RFC3394]. There are no public parameters that change on a per-invocation basis. The protected header field MUST be empty.
Keys can be obtained either from a key structure or from a recipient structure. Implementations encrypting and decrypting MUST validate that the key type, key length, and algorithm are correct and appropriate for the entities involved. This part is non-negotiable, bestie ๐ซถ
When using a COSE key for this algorithm, the following checks are made:
- The 'kty' field MUST be present, and it MUST be 'Symmetric'.
- If the 'alg' field is present, it MUST match the AES Key Wrap algorithm being used.
- If the 'key_ops' field is present, it MUST include 'encrypt' or 'wrap key' when encrypting.
- If the 'key_ops' field is present, it MUST include 'decrypt' or 'unwrap key' when decrypting.
+--------+-------+----------+-----------------------------+
| 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 17: AES Key Wrap Algorithm Values
12.2.1.1. Security Considerations for AES-KW
The shared secret needs to have some method to be regularly updated over time. The shared secret is the basis of trust ๐
12.3. Key Transport
Key transport mode is also called key encryption mode in some standards ๐ท It's different from key wrap mode because it uses an asymmetric encryption algorithm instead of a symmetric one to protect the key. This document doesn't define any key transport mode algorithms, so there's nothing to pick from here ๐
When using a key transport algorithm, the COSE_Encrypt structure for the recipient is organized as follows:
- The 'protected' field MUST be absent.
- The plaintext to be encrypted is the key from the next layer down (usually the content layer).
- At a minimum, the 'unprotected' field MUST contain the 'alg' parameter and SHOULD contain a parameter identifying the asymmetric key.
12.4. Direct Key Agreement โจ
Okay bestie, direct key agreement is giving "make a shared secret, then squeeze a key out of it" ๐. This class of recipient algorithms uses a key agreement method to create a shared secret. A KDF then gets applied to that secret to derive the key that protects the data. That key is normally used as a CEK or MAC key, but it could be used for other purposes if more than two layers are in use (see Appendix B). ๐
The most commonly used key agreement algorithm is Diffie-Hellman, but other variants exist ๐ธ Here's the tea: COSE is built for a store and forward environment, not an online one. So many of the DH variants can't be used, because the receiver of the message can't provide any dynamic key material ๐ญ One side effect is that perfect forward secrecy (see [RFC4949]) is not achievable. A static key will always be used for the receiver of the COSE object.
Two variants of DH are supported:
- Ephemeral-Static (ES) DH: The sender of the message creates a one-time DH key and uses a static key for the recipient. Since the ephemeral sender key is randomly generated for each message, no additional random input is needed. ๐ฆ
- Static-Static DH: A static key is used for both the sender and the recipient. Using static keys lets the recipient get a weak version of data origination for the message. When static-static key agreement is used, some piece of unique data for the KDF is required to make sure a different key is created for each message. ๐ง
When direct key agreement mode is used, there MUST be only one recipient in the message. This method creates the key directly, which makes it hard to mix with additional recipients. If multiple recipients are needed, the version with key wrap needs to be used. ๐ซ๐ฏ
The COSE_Encrypt structure for the recipient is organized as follows:
- At a minimum, headers MUST contain the 'alg' parameter and SHOULD contain a parameter identifying the recipient's asymmetric key. ๐
- The headers SHOULD identify the sender's key for the static-static versions and MUST contain the sender's ephemeral key for the ephemeral-static versions. โจ
12.4.1. ECDH ๐
The mathematics for ECDH can be found in [RFC6090]. In this document, the algorithm gets extended to work with the two curves defined in [RFC7748]. Bestie, this part is so iconic ๐
ECDH is parameterized by the following:
- Curve Type/Curve: The curve selected controls not only the size of the shared secret, but also the mathematics for computing it. It also controls how a point on the curve is represented and what happens for the identity points on the curve. This specification allows a number of different curves to be used, and a set of them is defined in Table 22. The math used to get the computed secret depends on the curve, not on the ECDH algorithm. That's why a new algorithm doesn't need to be defined for each curve. ๐
- Computed Secret to Shared Secret: Once the computed secret is known, the result needs to be converted to a byte string to run the KDF. The x-coordinate is used for all of the curves defined in this document. For curves X25519 and X448, the result is used directly, since it's a byte string of a known length. For the P-256, P-384, and P-521 curves, the x-coordinate is run through the I2OSP function defined in [RFC8017], using the same computation for n as is defined in Section 8.1. ๐ข
- Ephemeral-Static or Static-Static: The key agreement process may be done using either a static or an ephemeral key for the sender's side. When using ephemeral keys, the sender MUST generate a new ephemeral key for every key agreement operation. The ephemeral key is placed in the 'ephemeral key' parameter, and that parameter MUST be present for all algorithm identifiers that use ephemeral keys. When using static keys, the sender MUST either generate a new random value or create a unique value. For the KDFs used, this means either the 'salt' parameter for HKDF (Table 13) or the 'PartyU nonce' parameter for the context structure (Table 14) MUST be present. Both can be present if desired. The value in the parameter MUST be unique for the pair of keys being used. It is acceptable to use a global counter that is incremented for every static-static operation and use the resulting value. When using static keys, the static key should be identified to the recipient. The static key can be identified either by providing the key ('static key') or by providing a key identifier for the static key ('static key id'). Both of these parameters are defined in Table 19. ๐
- Key Derivation Algorithm: The result of an ECDH key agreement does not provide a uniformly random secret. So it needs to be run through a KDF to produce a usable key. Running the secret through a KDF also lets you add context material: how the key is going to be used, plus one-time material for static-static key agreement. All of the algorithms defined in this document use one of the HKDF algorithms defined in Section 11.1, with the context structure defined in Section 11.2. ๐ง
- Key Wrap Algorithm: No key wrap algorithm is used. This is represented in Table 18 as 'none'. The key size for the context structure is the content layer encryption algorithm size. ๐ซถ
The set of direct ECDH algorithms defined in this document is found in Table 18.
+-----------+-------+---------+------------+--------+---------------+
| Name | Value | KDF | Ephemeral- | Key | Description |
| | | | Static | 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 18: ECDH Algorithm Values
+-----------+-------+----------+---------------------+--------------+
| 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 19: ECDH Algorithm Parameters
This document defines these algorithms to be used with the curves P-256, P-384, P-521, X25519, and X448. Implementations MUST verify that the key type and curve are correct. Different curves are restricted to different key types. Implementations MUST verify that the curve and algorithm are appropriate for the entities involved. ๐ง
When using a COSE key for this algorithm, the following checks are made:
- The 'kty' field MUST be present, and it MUST be 'EC2' or 'OKP'. ๐๏ธ
- If the 'alg' field is present, it MUST match the key agreement algorithm being used. โ
- If the 'key_ops' field is present, it MUST include 'derive key' or 'derive bits' for the private key. ๐
- If the 'key_ops' field is present, it MUST be empty for the public key. ๐
12.4.2. Security Considerations ๐
There is a method of checking that points provided from external entities are valid. For the 'EC2' key format, this can be done by checking that the x and y values form a point on the curve. For the 'OKP' format, there is no simple way to do point validation. ๐ฌ
Consideration was given to requiring that the public keys of both entities be provided as part of the key derivation process (as recommended in Section 6.1 of [RFC7748]). This was not done, because COSE is used in a store and forward format rather than in online key exchange. For this to be a problem, either the receiver public key has to be chosen maliciously or the sender has to be malicious. In either case, all security evaporates anyway. Not me being dramatic, but this is serious ๐๐ฅ
A proof of possession of the private key associated with the public key is recommended when a key is moved from untrusted to trusted (either by the end user or by the entity that is responsible for making trust statements on keys). ๐ก๏ธ
12.5. Key Agreement with Key Wrap ๐
Key Agreement with Key Wrap uses a randomly generated CEK. The CEK is then encrypted using a key wrap algorithm and a key derived from the shared secret computed by the key agreement algorithm. The function for this would be:
encryptedKey = KeyWrap(KDF(DH-Shared, context), CEK)
The COSE_Encrypt structure for the recipient is organized as follows:
- The 'protected' field is fed into the KDF context structure. ๐งฉ
- The plaintext to be encrypted is the key from the next layer down (usually the content layer). ๐ฐ
- The 'alg' parameter MUST be present in the layer. ๐
- A parameter identifying the recipient's key SHOULD be present. A parameter identifying the sender's key SHOULD be present. ๐
12.5.1. ECDH ๐ฆ
okay so these algorithms are all listed in Table 20, bestie ๐
ECDH with Key Agreement takes the same parameters as plain ECDH (peep Section 12.4.1 for those), with a few extra tweaks:
- Key Wrap Algorithm ๐: any of the key wrap algorithms from Section 12.2.1 are supported! The size of the key used for the key wrap algorithm gets fed into the KDF. The identifiers live in Table 20.
+-----------+-------+---------+------------+--------+---------------+
| Name | Value | KDF | Ephemeral- | Key | Description |
| | | | Static | Wrap | |
+-----------+-------+---------+------------+--------+---------------+
| ECDH-ES + | -29 | HKDF - | yes | A128KW | ECDH ES w/ |
| A128KW | | SHA-256 | | | Concat KDF |
| | | | | | and AES Key |
| | | | | | Wrap w/ |
| | | | | | 128-bit key |
| | | | | | |
| ECDH-ES + | -30 | HKDF - | yes | A192KW | ECDH ES w/ |
| A192KW | | SHA-256 | | | Concat KDF |
| | | | | | and AES Key |
| | | | | | Wrap w/ |
| | | | | | 192-bit key |
| | | | | | |
| ECDH-ES + | -31 | HKDF - | yes | A256KW | ECDH ES w/ |
| A256KW | | SHA-256 | | | Concat KDF |
| | | | | | and AES Key |
| | | | | | Wrap w/ |
| | | | | | 256-bit key |
| | | | | | |
| ECDH-SS + | -32 | HKDF - | no | A128KW | ECDH SS w/ |
| A128KW | | SHA-256 | | | Concat KDF |
| | | | | | and AES Key |
| | | | | | Wrap w/ |
| | | | | | 128-bit key |
| | | | | | |
| ECDH-SS + | -33 | HKDF - | no | A192KW | ECDH SS w/ |
| A192KW | | SHA-256 | | | Concat KDF |
| | | | | | and AES Key |
| | | | | | Wrap w/ |
| | | | | | 192-bit key |
| | | | | | |
| ECDH-SS + | -34 | HKDF - | no | A256KW | ECDH SS w/ |
| A256KW | | SHA-256 | | | Concat KDF |
| | | | | | and AES Key |
| | | | | | Wrap w/ |
| | | | | | 256-bit key |
+-----------+-------+---------+------------+--------+---------------+
Table 20: ECDH Algorithm Values with Key Wrap
When you use a COSE key for this algorithm, these checks happen, so pay attention ๐:
- The
ktyfield MUST be present, and it MUST beEC2orOKP. - If the
algfield is present, it MUST match the key agreement algorithm being used. - If the
key_opsfield is present, it MUST includederive keyorderive bitsfor the private key. - If the
key_opsfield is present, it MUST be empty for the public key.
13. Key Object Parameters ๐
The COSE_Key object gives you a way to hold a single key object ๐๏ธ It still has to be defined what the members of each individual key type are, and this section is where we define an initial set of members for specific key types. Cute, right?
For each key type, we define both public and private members. The public members are what gets sent to others so they can use them. Private members let individuals archive their keys. However, there are some situations where private keys may be distributed to entities in a protocol ๐ Examples include: entities with poor random number generation, centralized key creation for multicast-type operations, and protocols where a shared secret is used as a bearer token for authorization purposes. Dramatic, but real.
Key types are identified by the kty member of the COSE_Key object. In this document, we define four values for that member:
+-----------+-------+-----------------------------------------------+
| Name | Value | Description |
+-----------+-------+-----------------------------------------------+
| OKP | 1 | Octet Key Pair |
| EC2 | 2 | Elliptic Curve Keys w/ x- and y-coordinate |
| | | pair |
| Symmetric | 4 | Symmetric Keys |
| Reserved | 0 | This value is reserved |
+-----------+-------+-----------------------------------------------+
Table 21: Key Type Values
13.1. Elliptic Curve Keys โจ
Two different key structures are defined for elliptic curve keys ๐ซ One version uses both an x-coordinate and a y-coordinate, potentially with point compression (EC2). This is the traditional EC point representation used in [RFC5480]. The other version uses only the x-coordinate, since the y-coordinate is either going to be recomputed or isn't needed for the key agreement operation (OKP).
Applications MUST check that the curve and the key type are consistent and reject a key if they are not. No mismatched vibes allowed ๐ โโ๏ธ
+---------+-------+----------+------------------------------------+
| Name | Value | Key Type | Description |
+---------+-------+----------+------------------------------------+
| P-256 | 1 | EC2 | NIST P-256 also known as secp256r1 |
| P-384 | 2 | EC2 | NIST P-384 also known as secp384r1 |
| P-521 | 3 | EC2 | NIST P-521 also known as secp521r1 |
| X25519 | 4 | OKP | X25519 for use w/ ECDH only |
| X448 | 5 | OKP | X448 for use w/ ECDH only |
| Ed25519 | 6 | OKP | Ed25519 for use w/ EdDSA only |
| Ed448 | 7 | OKP | Ed448 for use w/ EdDSA only |
+---------+-------+----------+------------------------------------+
Table 22: Elliptic Curves
13.1.1. Double Coordinate Curves ๐ธ
The traditional way of sending ECs has been to send either both the x-coordinate and the y-coordinate, or the x-coordinate plus a sign bit for the y-coordinate. The latter encoding has not been recommended in the IETF because of potential IPR issues ๐ฌ That said, for operations in constrained environments, being able to shrink a message by not sending the y-coordinate is potentially super useful ๐ง
For EC keys with both coordinates, the kty member is set to 2 (EC2). The key parameters defined in this section are summarized in Table 23. The members defined for this key type are:
crv: This contains an identifier of the curve to be used with the key. The curves defined in this document for this key type can be found in Table 22. Other curves may be registered in the future, and private curves can be used as well.x: This contains the x-coordinate for the EC point. The integer is converted to an octet string as defined in [SEC1]. Leading zero octets MUST be preserved.y: This contains either the sign bit or the value of the y-coordinate for the EC point. When encoding the value y, the integer is converted to an octet string (as defined in [SEC1]) and encoded as a CBOR bstr. Leading zero octets MUST be preserved. The compressed point encoding is also supported. Compute the sign bit as laid out in the Elliptic-Curve-Point-to-Octet-String Conversion function of [SEC1]. If the sign bit is zero, then encode y as a CBOR false value; otherwise, encode y as a CBOR true value. The encoding of the infinity point is not supported.d: This contains the private key.
For public keys, it is REQUIRED that crv, x, and y be present in the structure. For private keys, it is REQUIRED that crv and d be present in the structure. For private keys, it is RECOMMENDED that x and y also be present, but they can be recomputed from the required elements, and omitting them saves on space ๐
+-------+------+-------+--------+-----------------------------------+
| Key | Name | Label | CBOR | Description |
| Type | | | Type | |
+-------+------+-------+--------+-----------------------------------+
| 2 | crv | -1 | int / | EC identifier - Taken from the |
| | | | tstr | "COSE Elliptic Curves" registry |
| 2 | x | -2 | bstr | x-coordinate |
| 2 | y | -3 | bstr / | y-coordinate |
| | | | bool | |
| 2 | d | -4 | bstr | Private key |
+-------+------+-------+--------+-----------------------------------+
Table 23: EC Key Parameters
13.2. Octet Key Pair ๐ฆ
A new key type is defined for Octet Key Pairs (OKP). Do not assume that keys using this type are elliptic curves! This key type could be used for other curve types, for example, mathematics based on hyper-elliptic surfaces ๐
The key parameters defined in this section are summarized in Table 24. The members defined for this key type are:
crv: This contains an identifier of the curve to be used with the key. The curves defined in this document for this key type can be found in Table 22. Other curves may be registered in the future, and private curves can be used as well.x: This contains the x-coordinate for the EC point. The octet string represents a little-endian encoding of x.d: This contains the private key.
For public keys, it is REQUIRED that crv and x be present in the structure. For private keys, it is REQUIRED that crv and d be present in the structure. For private keys, it is RECOMMENDED that x also be present, but it can be recomputed from the required elements, and omitting it saves on space โจ
+------+-------+-------+--------+-----------------------------------+
| Name | Key | Label | Type | Description |
| | Type | | | |
+------+-------+-------+--------+-----------------------------------+
| crv | 1 | -1 | int / | EC identifier - Taken from the |
| | | | tstr | "COSE Key Common Parameters" |
| | | | | registry |
| x | 1 | -2 | bstr | x-coordinate |
| d | 1 | -4 | bstr | Private key |
+------+-------+-------+--------+-----------------------------------+
Table 24: Octet Key Pair Parameters
13.3. Symmetric Keys ๐
Okay bestie, sometimes a symmetric key needs to get passed from one entity to another, and this key structure is the thing that makes that possible ๐
For symmetric keys, the 'kty' member gets set to 4 ('Symmetric'). The only member defined for this key type is:
k: this is where the value of the key lives ๐๏ธ
This key structure doesn't have a form that contains only public members. Since this structure is going to get transmitted, we have to be super careful that it's never sent accidentally or insecurely ๐ญ For symmetric keys, it is REQUIRED that 'k' be present in the structure.
+------+----------+-------+------+-------------+
| Name | Key Type | Label | Type | Description |
+------+----------+-------+------+-------------+
| k | 4 | -1 | bstr | Key Value |
+------+----------+-------+------+-------------+
Table 25: Symmetric Key Parameters
14. CBOR Encoder Restrictions โจ
We tried to keep the number of places where this document has to boss around the CBOR Encoder super small, and we managed to narrow it down to these restrictions:
- The restriction applies to the encoding of the
Sig_structure, theEnc_structure, and theMAC_structure. - The rules for "Canonical CBOR" (Section 3.9 of RFC 7049) MUST be used in these locations. The main rule that needs to be enforced is that all lengths in these structures MUST be encoded such that they are using definite lengths, and the minimum length encoding is used.
- Applications MUST NOT generate messages with the same label used twice as a key in a single map. Applications MUST NOT parse and process messages with the same label used twice as a key in a single map. Applications can enforce the parse and process requirement by using parsers that will fail the parse step or by using parsers that will pass all keys to the application, and the application can perform the check for duplicate keys. ๐
15. Application Profiling Considerations ๐งฉ
This document is designed to provide a set of security services, but it doesn't give implementation requirements for specific usage. The interoperability requirements explain how each of the individual services gets used and how the algorithms are to be used for interoperability. Which algorithms and which services are needed is left up to each application to decide.
An example of a profile can be found in [OSCOAP], where two profiles are being developed. One is for carrying content by itself, and the other is for carrying content in combination with CoAP headers.
It's intended that a profile of this document gets created that defines the interoperability requirements for that specific application. This section gives a set of guidelines and topics that need to be considered when profiling this document. ๐
- Applications need to determine the set of messages defined in this document that they will be using. The set of messages corresponds fairly directly to the set of security services that are needed and to the security levels needed.
- Applications may define new header parameters for a specific purpose. Applications will often times select specific header parameters to use or not to use. For example, an application would normally state a preference for using either the IV or the Partial IV parameter. If the Partial IV parameter is specified, then the application would also need to define how the fixed portion of the IV would be determined.
- When applications use externally defined authenticated data, they need to define how that data is encoded. This document assumes that the data will be provided as a byte stream. More information can be found in Section 4.3.
- Applications need to determine the set of security algorithms that are to be used. When selecting the algorithms to be used as the mandatory-to-implement set, consideration should be given to choosing different types of algorithms when two are chosen for a specific purpose. An example of this would be choosing HMAC-SHA512 and AES-CMAC as different MAC algorithms, since the construction is vastly different between these two algorithms. This means that a weakening of one algorithm would be unlikely to lead to a weakening of the other algorithms. Of course, these algorithms do not provide the same level of security and thus may not be comparable for the desired security functionality. ๐ฅ
- Applications may need to provide some type of negotiation or discovery method if multiple algorithms or message structures are permitted. The method can be as simple as requiring preconfiguration of the set of algorithms, or as fancy as a discovery method built into the protocol. S/MIME gave applications a bunch of different ways to approach the problem that they could follow:
16. IANA Considerations ๐
16.1. CBOR Tag Assignment ๐ท๏ธ
IANA has assigned some tags from the "CBOR Tags" registry. The tags for COSE_Sign1, COSE_Encrypt0, and COSE_Mac0 were assigned in the 1 to 23 value range (one byte long when encoded). The tags for COSE_Sign, COSE_Encrypt, and COSE_Mac were assigned in the 24 to 255 value range (two bytes long when encoded).
The tags assigned are in Table 1.
16.2. COSE Header Parameters Registry ๐
IANA has created a new registry titled "COSE Header Parameters". The registry has been created to use the "Expert Review Required" registration procedure [RFC8126]. Guidelines for the experts are provided in Section 16.11. It should be noted that, in addition to the expert review, some portions of the registry require a specification, potentially a Standards Track RFC, be supplied as well.
The columns of the registry are:
- Name: The name is present to make it easier to refer to and discuss the registration entry. The value is not used in the protocol. Names are to be unique in the table.
- Label: This is the value used for the label. The label can be either an integer or a string. Registration in the table is based on the value of the label requested. Integer values between 1 and 255 and strings of length 1 are designated as "Standards Action". Integer values from 256 to 65535 and strings of length 2 are designated as "Specification Required". Integer values of greater than 65535 and strings of length greater than 2 are designated as "Expert Review". Integer values in the range -1 to -65536 are "delegated to the COSE Header Algorithm Parameters registry". Integer values less than -65536 are marked as private use.
- Value Type: This contains the CBOR type for the value portion of the label.
- Value Registry: This contains a pointer to the registry used to contain values where the set is limited.
- Description: This contains a brief description of the header field.
- Reference: This contains a pointer to the specification defining the header field (where public).
The initial contents of the registry can be found in Tables 2 and 27. All of the entries in the "References" column of this registry point to this document.
Additionally, the label of 0 is to be marked as 'Reserved'.
16.3. COSE Header Algorithm Parameters Registry ๐งฎ
IANA has created a new registry titled "COSE Header Algorithm Parameters". The registry uses the "Expert Review Required" registration procedure. Expert review guidelines are provided in Section 16.11.
The columns of the registry are:
- Name: The name is present to make it easier to refer to and discuss the registration entry. The value is not used in the protocol.
- Algorithm: The algorithm(s) that this registry entry is used for. This value is taken from the "COSE Algorithms" registry. Multiple algorithms can be specified in this entry. For the table, the algorithm/label pair MUST be unique.
- Label: This is the value used for the label. The label is an integer in the range of -1 to -65536.
- Type: This contains the CBOR type for the value portion of the label.
- Description: This contains a brief description of the header field.
- Reference: This contains a pointer to the specification defining the header field (where public).
The initial contents of the registry can be found in Tables 13, 14, and 19. All of the entries in the "References" column of this registry point to this document.
16.4. COSE Algorithms Registry ๐
IANA has created a new registry titled "COSE Algorithms". The registry has been created to use the "Expert Review Required" registration procedure. Guidelines for the experts are provided in Section 16.11. It should be noted that, in addition to the expert review, some portions of the registry require a specification, potentially a Standards Track RFC, be supplied as well.
The columns of the registry are:
- Name: A value that can be used to identify an algorithm in documents for easier comprehension. The name SHOULD be unique. However, the 'Value' field is what is used to identify the algorithm, not the 'name' field.
- Value: The value to be used to identify this algorithm. Algorithm values MUST be unique. The value can be a positive integer, a negative integer, or a string. Integer values between -256 and 255 and strings of length 1 are designated as "Standards Action". Integer values from -65536 to 65535 and strings of length 2 are designated as "Specification Required". Integer values greater than 65535 and strings of length greater than 2 are designated as "Expert Review". Integer values less than -65536 are marked as private use.
- Description: A short description of the algorithm.
- Reference: A document where the algorithm is defined (if publicly available).
- Recommended: Does the IETF have a consensus recommendation to use the algorithm? The legal values are 'Yes', 'No', and 'Deprecated'.
The initial contents of the registry can be found in Tables 5, 6, 7, 8, 9, 10, 11, 15, 16, 17, 18, and 20. All of the entries in the "References" column of this registry point to this document. All of the entries in the "Recommended" column are set to "Yes".
Additionally, the label of 0 is to be marked as 'Reserved'.
NOTE: The assignment of algorithm identifiers in this document was done so that positive numbers were used for the first layer objects (COSE_Sign, COSE_Sign1, COSE_Encrypt, COSE_Encrypt0, COSE_Mac, and COSE_Mac0). Negative numbers were used for second layer objects (COSE_Signature and COSE_recipient). Expert reviewers should consider this practice, but are not expected to be restricted by this precedent. ๐
16.5. COSE Key Common Parameters Registry ๐โจ
okay bestie, IANA is making a brand new registry called "COSE Key Common Parameters" ๐ It uses the "Expert Review Required" registration procedure, and the guidelines for the experts are in Section 16.11. ngl, the tea here is that on top of the expert review, some parts of this registry need a specification too, and that spec could be a Standards Track RFC ๐ง
The columns are:
- Name: a descriptive name so people can refer to the item easily ๐ท๏ธ It is not used in the encoding.
- Label: the value used to identify the item. Key map labels MUST be unique ๐ A label can be a positive integer, a negative integer, or a string. Integers from 0 to 255 and strings of length 1 are "Standards Action". Integers from 256 to 65535 and strings of length 2 are "Specification Required". Integers greater than 65535 and strings of length greater than 2 are "Expert Review". Integers from -65536 to -1 are "used for key parameters specific to a single algorithm delegated to the COSE Key Type Parameters registry". Integers less than -65536 are marked as private use ๐
- CBOR Type: the CBOR type for the field ๐ง
- Value Registry: which registry the values come from, if there is one ๐
- Description: a brief description of the field ๐ฌ
- Reference: a pointer to the public specification for the field, if one exists ๐
This registry was initially filled in with the values from Table 3 ๐ธ Every entry in the "References" column points back to this document, so it's all one family ๐ซถ
16.6. COSE Key Type Parameters Registry ๐งฉ
IANA made a new registry called "COSE Key Type Parameters" ๐ It uses the "Expert Review Required" procedure too, and the expert review guidelines are in Section 16.11 ๐
The columns are:
- Key Type: a descriptive string for a key type. This should be a value that's in the "COSE Key Common Parameters" registry and gets placed in the 'kty' field of a COSE Key structure ๐๏ธ
- Name: a descriptive name for easy reference. It is not used in the encoding ๐ท๏ธ
- Label: the label has to be unique for every value of key type. The range is from -65536 to -1. Labels are expected to be reused for different keys ๐
- CBOR Type: the CBOR type for the field ๐ง
- Description: a brief description of the field ๐ฌ
- Reference: a pointer to the public specification for the field, if one exists ๐
This registry was initially populated with the values in Tables 23, 24, and 25 ๐ฆ All of the entries in the "References" column point to this document ๐
16.7. COSE Key Types Registry ๐ท
IANA made a new registry called "COSE Key Types" ๐ It uses the "Expert Review Required" procedure, and the guidelines are in Section 16.11 โจ
The columns are:
- Name: a descriptive name for easy reference. The name MUST be unique ๐ซง It is not used in the encoding.
- Value: the value used to identify the curve. These values MUST be unique ๐ A value can be a positive integer, a negative integer, or a string.
- Description: a brief description of the curve ๐ฌ
- References: a pointer to the public specification for the curve, if one exists ๐
This registry was initially populated with the values in Table 21 ๐ The specification column for all of these entries will be this document ๐
16.8. COSE Elliptic Curves Registry ๐
IANA made a new registry called "COSE Elliptic Curves" ๐งโโ๏ธ It uses the "Expert Review Required" procedure. The guidelines for the experts are in Section 16.11, and, same as before, some parts of the registry need a specification too, potentially a Standards Track RFC ๐ซถ
The columns are:
- Name: a descriptive name for easy reference. It is not used in the encoding ๐ท๏ธ
- Value: the value used to identify the curve. These values MUST be unique ๐ Integers from -256 to 255 are "Standards Action". Integers from 256 to 65535 and from -65536 to -257 are "Specification Required". Integers over 65535 are "Expert Review". Integers less than -65536 are marked as private use ๐
- Key Type: the key type or types that can be used with this curve ๐๏ธ
- Description: a brief description of the curve ๐ฌ
- Reference: a pointer to the public specification for the curve, if one exists ๐
- Recommended: does the IETF have a consensus recommendation to use the algorithm? The legal values are 'Yes', 'No', and 'Deprecated' ๐ฆ
This registry was initially populated with the values in Table 22 ๐ธ All of the entries in the "References" column point to this document, and every entry in the "Recommended" column is set to "Yes" ๐ฏ
16.9. Media Type Registrations ๐ฎ
16.9.1. COSE Security Message ๐
This section registers the 'application/cose' media type in the "Media Types" registry ๐ These media types show that the content is a COSE message.
Type name: application
Subtype name: cose
Required parameters: N/A
Optional parameters: cose-type
Encoding considerations: binary
Security considerations: See the Security Considerations section
of RFC 8152.
Interoperability considerations: N/A
Published specification: RFC 8152
Applications that use this media type: IoT applications sending
security content over HTTP(S) transports.
Fragment identifier considerations: N/A
Additional information:
* Deprecated alias names for this type: N/A
* Magic number(s): N/A
* File extension(s): cbor
* Macintosh file type code(s): N/A
Person & email address to contact for further information:
iesg@ietf.org
Intended usage: COMMON
Restrictions on usage: N/A
Author: Jim Schaad, ietf@augustcellars.com
Change Controller: IESG
Provisional registration? No
16.9.2. COSE Key Media Type ๐๏ธ๐
This section registers the 'application/cose-key' and 'application/cose-key-set' media types in the "Media Types" registry ๐ฆ These media types show that the content is a COSE_Key or a COSE_KeySet object, respectively.
The template for registering 'application/cose-key' is:
Type name: application
Subtype name: cose-key
Required parameters: N/A
Optional parameters: N/A
Encoding considerations: binary
Security considerations: See the Security Considerations section
of RFC 8152.
Interoperability considerations: N/A
Published specification: RFC 8152
Applications that use this media type: Distribution of COSE based
keys for IoT applications.
Fragment identifier considerations: N/A
Additional information:
* Deprecated alias names for this type: N/A
* Magic number(s): N/A
* File extension(s): cbor
* Macintosh file type code(s): N/A
Person & email address to contact for further information:
iesg@ietf.org
Intended usage: COMMON
Restrictions on usage: N/A
Author: Jim Schaad, ietf@augustcellars.com
Change Controller: IESG
Provisional registration? No
The template for registering 'application/cose-key-set' is:
Type name: application
Subtype name: cose-key-set
Required parameters: N/A
Optional parameters: N/A
Encoding considerations: binary
Security considerations: See the Security Considerations section
of RFC 8152.
Interoperability considerations: N/A
Published specification: RFC 8152
Applications that use this media type: Distribution of COSE based
keys for IoT applications.
Fragment identifier considerations: N/A
Additional information:
* Deprecated alias names for this type: N/A
* Magic number(s): N/A
* File extension(s): cbor
* Macintosh file type code(s): N/A
Person & email address to contact for further information:
iesg@ietf.org
Intended usage: COMMON
Restrictions on usage: N/A
Author: Jim Schaad, ietf@augustcellars.com
Change Controller: IESG
Provisional registration? No
16.10. CoAP Content-Formats Registry ๐
IANA has added the following entries to the "CoAP Content-Formats" registry ๐ผ
+--------------------------------------+----------+-----+-----------+
| Media Type | Encoding | ID | Reference |
+--------------------------------------+----------+-----+-----------+
| application/cose; cose-type="cose- | | 98 | [RFC8152] |
| sign" | | | |
| application/cose; cose-type="cose- | | 18 | [RFC8152] |
| sign1" | | | |
| application/cose; cose-type="cose- | | 96 | [RFC8152] |
| encrypt" | | | |
| application/cose; cose-type="cose- | | 16 | [RFC8152] |
| encrypt0" | | | |
| application/cose; cose-type="cose- | | 97 | [RFC8152] |
| mac" | | | |
| application/cose; cose-type="cose- | | 17 | [RFC8152] |
| mac0" | | | |
| application/cose-key | | 101 | [RFC8152] |
| application/cose-key-set | | 102 | [RFC8152] |
+--------------------------------------+----------+-----+-----------+
Table 26: CoAP Content-Formats for COSE
okay bestie, let's get into the expert review stuff ๐ ๐
16.11. Expert Review Instructions
All of the IANA registries established in this document are defined as expert review. ๐ง This section gives some general guidelines for what the experts should be looking for, but they are being designated as experts for a reason, so they should be given substantial latitude. โจ
Expert reviewers should take into consideration the following points:
- Point squatting should be discouraged. ๐ Reviewers are encouraged to get sufficient information for registration requests to ensure that the usage is not going to duplicate one that is already registered, and that the point is likely to be used in deployments. The zones tagged as private use are intended for testing purposes and closed environments; code points in other ranges should not be assigned for testing. ๐
- Specifications are required for the standards track range of point assignment. ๐ Specifications should exist for specification required ranges, but early assignment before a specification is available is considered to be permissible. Specifications are needed for the first-come, first-serve range if they are expected to be used outside of closed environments in an interoperable way. When specifications are not provided, the description provided needs to have sufficient information to identify what the point is being used for. ๐ซถ
- Experts should take into account the expected usage of fields when approving point assignment. ๐ธ The fact that there is a range for standards track documents does not mean that a standards track document cannot have points assigned outside of that range. The length of the encoded value should be weighed against how many code points of that length are left, the size of device it will be used on, and the number of code points left that encode to that size. ๐ฅ
- When algorithms are registered, vanity registrations should be discouraged. ๐ One way to do this is to require registrations to provide additional documentation on security analysis of the algorithm. Another thing that should be considered is requesting an opinion on the algorithm from the Crypto Forum Research Group (CFRG). Algorithms that do not meet the security requirements of the community and the messages structures should not be registered. ๐ญ
17. Security Considerations ๐
There are a number of security considerations that need to be taken into account by implementers of this specification. The security considerations that are specific to an individual algorithm are placed next to the description of the algorithm. While some considerations have been highlighted here, additional considerations may be found in the documents listed in the references. ๐ฆ
Implementations need to protect the private key material for any individuals. There are some cases in this document that need to be highlighted on this issue. ๐
- Using the same key for two different algorithms can leak information about the key. It is therefore recommended that keys be restricted to a single algorithm. ๐
- Use of 'direct' as a recipient algorithm combined with a second recipient algorithm exposes the direct key to the second recipient. ๐ฌ
- Several of the algorithms in this document have limits on the number of times that a key can be used without leaking information about the key. ๐จ
The use of ECDH and direct plus KDF (with no key wrap) will not directly lead to the private key being leaked; the one way function of the KDF will prevent that. ๐ง There is, however, a different issue that needs to be addressed. Having two recipients requires that the CEK be shared between two recipients. The second recipient therefore has a CEK that was derived from material that can be used for the weak proof of origin. The second recipient could create a message using the same CEK and send it to the first recipient; the first recipient would, for either static-static ECDH or direct plus KDF, make an assumption that the CEK could be used for proof of origin even though it is from the wrong entity. If the key wrap step is added, then no proof of origin is implied and this is not an issue. ๐
Although it has been mentioned before, the use of a single key for multiple algorithms has been demonstrated in some cases to leak information about a key, provide the opportunity for attackers to forge integrity tags, or gain information about encrypted content. Binding a key to a single algorithm prevents these problems. Key creators and key consumers are strongly encouraged not only to create new keys for each different algorithm, but to include that selection of algorithm in any distribution of key material and strictly enforce the matching of algorithms in the key structure to algorithms in the message structure. In addition to checking that algorithms are correct, the key form needs to be checked as well. Do not use an 'EC2' key where an 'OKP' key is expected. ๐ซ
Before using a key for transmission, or before acting on information received, a trust decision on a key needs to be made. Is the data or action something that the entity associated with the key has a right to see or a right to request? A number of factors are associated with this trust decision. Some of the ones that are highlighted here are:
- What are the permissions associated with the key owner? ๐ชช
- Is the cryptographic algorithm acceptable in the current context? ๐ง
- Have the restrictions associated with the key, such as algorithm or freshness, been checked and are they correct? โ
- Is the request something that is reasonable, given the current state of the application? ๐ค
- Have any security considerations that are part of the message been enforced (as specified by the application or 'crit' parameter)? ๐ก๏ธ
There are a large number of algorithms presented in this document that use nonce values. For all of the nonces defined in this document, there is some type of restriction on the nonce being a unique value either for a key or for some other conditions. In all of these cases, there is no known requirement on the nonce being both unique and unpredictable; under these circumstances, it's reasonable to use a counter for creation of the nonce. In cases where one wants the pattern of the nonce to be unpredictable as well as unique, one can use a key created for that purpose and encrypt the counter to produce the nonce value. ๐ขโจ
One area that has been starting to get exposure is doing traffic analysis of encrypted messages based on the length of the message. This specification does not provide for a uniform method of providing padding as part of the message structure. An observer can distinguish between two different strings (for example, 'YES' and 'NO') based on the length for all of the content encryption algorithms that are defined in this document. This means that it is up to the applications to document how content padding is to be done in order to prevent or discourage such analysis. (For example, the strings could be defined as 'YES' and 'NO '.) ๐ต๏ธโโ๏ธ๐
18. References ๐
18.1. Normative References
- [AES-GCM]: National Institute of Standards and Technology, "Recommendation for Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC", NIST Special Publication 800-38D, DOI 10.6028/NIST.SP.800-38D, November 2007, <https://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf>. ๐
- [COAP.Formats]: IANA, "Constrained RESTful Environments (CoRE) Parameters", <http://www.iana.org/assignments/core-parameters/>. ๐
- [DSS]: National Institute of Standards and Technology, "Digital Signature Standard (DSS)", FIPS PUB 186-4, DOI 10.6028/NIST.FIPS.186-4, July 2013, <http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf>. ๐
- [MAC]: National Institute of Standards and Technology, "Computer Data Authentication", FIPS PUB 113, May 1985, <http://csrc.nist.gov/publications/fips/fips113/fips113.html>. ๐ฆ
- [RFC2104]: Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-Hashing for Message Authentication", RFC 2104, DOI 10.17487/RFC2104, February 1997, <http://www.rfc-editor.org/info/rfc2104>. ๐ธ
- [RFC2119]: Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <http://www.rfc-editor.org/info/rfc2119>. ๐
- [RFC3394]: Schaad, J. and R. Housley, "Advanced Encryption Standard (AES) Key Wrap Algorithm", RFC 3394, DOI 10.17487/RFC3394, September 2002, <http://www.rfc-editor.org/info/rfc3394>. ๐ง
- [RFC3610]: Whiting, D., Housley, R., and N. Ferguson, "Counter with CBC-MAC (CCM)", RFC 3610, DOI 10.17487/RFC3610, September 2003, <http://www.rfc-editor.org/info/rfc3610>. โจ
- [RFC5869]: Krawczyk, H. and P. Eronen, "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)", RFC 5869, DOI 10.17487/RFC5869, May 2010, <http://www.rfc-editor.org/info/rfc5869>. ๐ซง
- [RFC6090]: McGrew, D., Igoe, K., and M. Salter, "Fundamental Elliptic Curve Cryptography Algorithms", RFC 6090, DOI 10.17487/RFC6090, February 2011, <http://www.rfc-editor.org/info/rfc6090>. ๐
- [RFC6979]: Pornin, T., "Deterministic Usage of the Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA)", RFC 6979, DOI 10.17487/RFC6979, August 2013, <http://www.rfc-editor.org/info/rfc6979>. ๐ญ
- [RFC7049]: Bormann, C. and P. Hoffman, "Concise Binary Object Representation (CBOR)", RFC 7049, DOI 10.17487/RFC7049, October 2013, <http://www.rfc-editor.org/info/rfc7049>. ๐ท
- [RFC7539]: Nir, Y. and A. Langley, "ChaCha20 and Poly1305 for IETF Protocols", RFC 7539, DOI 10.17487/RFC7539, May 2015, <http://www.rfc-editor.org/info/rfc7539>. ๐
- [RFC7748]: Langley, A., Hamburg, M., and S. Turner, "Elliptic Curves for Security", RFC 7748, DOI 10.17487/RFC7748, January 2016, <http://www.rfc-editor.org/info/rfc7748>. ๐
- [RFC8032]: Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital Signature Algorithm (EdDSA)", RFC 8032, DOI 10.17487/RFC8032, January 2017, <http://www.rfc-editor.org/info/rfc8032>. ๐
- [RFC8174]: Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <http://www.rfc-editor.org/info/rfc8174>. ๐
- [SEC1]: Certicom Research, "SEC 1: Elliptic Curve Cryptography", Standards for Efficient Cryptography, Version 2.0, May 2009, <http://www.secg.org/sec1-v2.pdf>. ๐ฆ
18.2. Informative References โจ
Okay bestie, here are the informative references, the extra reading that backs up the spec ๐๐ Every single one is listed below exactly as written, DOIs and URLs included, so nothing gets lost ๐ซถ
[CDDL] Vigano, C. and H. Birkholz, "CBOR data definition language
(CDDL): a notational convention to express CBOR data
structures", Work in Progress, draft-greevenbosch-appsawg-
cbor-cddl-09, March 2017.
[OSCOAP] Selander, G., Mattsson, J., Palombini, F., and L. Seitz,
"Object Security of CoAP (OSCOAP)", Work in Progress,
draft-ietf-core-object-security-03, May 2017.
[PVSig] Brown, D. and D. Johnson, "Formal Security Proofs for a
Signature Scheme with Partial Message Recovery",
DOI 10.1007/3-540-45353-9_11, LNCS Volume 2020, June 2000.
[RFC2633] Ramsdell, B., Ed., "S/MIME Version 3 Message
Specification", RFC 2633, DOI 10.17487/RFC2633, June 1999,
<http://www.rfc-editor.org/info/rfc2633>.
[RFC4231] Nystrom, M., "Identifiers and Test Vectors for HMAC-SHA-
224, HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512",
RFC 4231, DOI 10.17487/RFC4231, December 2005,
<http://www.rfc-editor.org/info/rfc4231>.
[RFC4262] Santesson, S., "X.509 Certificate Extension for Secure/
Multipurpose Internet Mail Extensions (S/MIME)
Capabilities", RFC 4262, DOI 10.17487/RFC4262, December
2005, <http://www.rfc-editor.org/info/rfc4262>.
[RFC4493] Song, JH., Poovendran, R., Lee, J., and T. Iwata, "The
AES-CMAC Algorithm", RFC 4493, DOI 10.17487/RFC4493, June
2006, <http://www.rfc-editor.org/info/rfc4493>.
[RFC4949] Shirey, R., "Internet Security Glossary, Version 2",
FYI 36, RFC 4949, DOI 10.17487/RFC4949, August 2007,
<http://www.rfc-editor.org/info/rfc4949>.
[RFC5116] McGrew, D., "An Interface and Algorithms for Authenticated
Encryption", RFC 5116, DOI 10.17487/RFC5116, January 2008,
<http://www.rfc-editor.org/info/rfc5116>.
[RFC5480] Turner, S., Brown, D., Yiu, K., Housley, R., and T. Polk,
"Elliptic Curve Cryptography Subject Public Key
Information", RFC 5480, DOI 10.17487/RFC5480, March 2009,
<http://www.rfc-editor.org/info/rfc5480>.
[RFC5652] Housley, R., "Cryptographic Message Syntax (CMS)", STD 70,
RFC 5652, DOI 10.17487/RFC5652, September 2009,
<http://www.rfc-editor.org/info/rfc5652>.
[RFC5751] Ramsdell, B. and S. Turner, "Secure/Multipurpose Internet
Mail Extensions (S/MIME) Version 3.2 Message
Specification", RFC 5751, DOI 10.17487/RFC5751, January
2010, <http://www.rfc-editor.org/info/rfc5751>.
[RFC5752] Turner, S. and J. Schaad, "Multiple Signatures in
Cryptographic Message Syntax (CMS)", RFC 5752,
DOI 10.17487/RFC5752, January 2010,
<http://www.rfc-editor.org/info/rfc5752>.
[RFC5990] Randall, J., Kaliski, B., Brainard, J., and S. Turner,
"Use of the RSA-KEM Key Transport Algorithm in the
Cryptographic Message Syntax (CMS)", RFC 5990,
DOI 10.17487/RFC5990, September 2010,
<http://www.rfc-editor.org/info/rfc5990>.
[RFC6151] Turner, S. and L. Chen, "Updated Security Considerations
for the MD5 Message-Digest and the HMAC-MD5 Algorithms",
RFC 6151, DOI 10.17487/RFC6151, March 2011,
<http://www.rfc-editor.org/info/rfc6151>.
[RFC6838] Freed, N., Klensin, J., and T. Hansen, "Media Type
Specifications and Registration Procedures", BCP 13,
RFC 6838, DOI 10.17487/RFC6838, January 2013,
<http://www.rfc-editor.org/info/rfc6838>.
[RFC7159] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data
Interchange Format", RFC 7159, DOI 10.17487/RFC7159, March
2014, <http://www.rfc-editor.org/info/rfc7159>.
[RFC7252] Shelby, Z., Hartke, K., and C. Bormann, "The Constrained
Application Protocol (CoAP)", RFC 7252,
DOI 10.17487/RFC7252, June 2014,
<http://www.rfc-editor.org/info/rfc7252>.
[RFC7515] Jones, M., Bradley, J., and N. Sakimura, "JSON Web
Signature (JWS)", RFC 7515, DOI 10.17487/RFC7515, May
2015, <http://www.rfc-editor.org/info/rfc7515>.
[RFC7516] Jones, M. and J. Hildebrand, "JSON Web Encryption (JWE)",
RFC 7516, DOI 10.17487/RFC7516, May 2015,
<http://www.rfc-editor.org/info/rfc7516>.
[RFC7517] Jones, M., "JSON Web Key (JWK)", RFC 7517,
DOI 10.17487/RFC7517, May 2015,
<http://www.rfc-editor.org/info/rfc7517>.
[RFC7518] Jones, M., "JSON Web Algorithms (JWA)", RFC 7518,
DOI 10.17487/RFC7518, May 2015,
<http://www.rfc-editor.org/info/rfc7518>.
[RFC8017] Moriarty, K., Ed., Kaliski, B., Jonsson, J., and A. Rusch,
"PKCS #1: RSA Cryptography Specifications Version 2.2",
RFC 8017, DOI 10.17487/RFC8017, November 2016,
<http://www.rfc-editor.org/info/rfc8017>.
[RFC8018] Moriarty, K., Ed., Kaliski, B., and A. Rusch, "PKCS #5:
Password-Based Cryptography Specification Version 2.1",
RFC 8018, DOI 10.17487/RFC8018, January 2017,
<http://www.rfc-editor.org/info/rfc8018>.
[RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for
Writing an IANA Considerations Section in RFCs", BCP 26,
RFC 8126, DOI 10.17487/RFC8126, June 2017,
<http://www.rfc-editor.org/info/rfc8126>.
[SP800-56A]
Barker, E., Chen, L., Roginsky, A., and M. Smid,
"Recommendation for Pair-Wise Key Establishment Schemes
Using Discrete Logarithm Cryptography", NIST Special
Publication 800-56A, Revision 2,
DOI 10.6028/NIST.SP.800-56Ar2, May 2013,
<http://nvlpubs.nist.gov/nistpubs/SpecialPublications/
NIST.SP.800-56Ar2.pdf>.
[W3C.WebCrypto]
Watson, M., "Web Cryptography API", W3C Recommendation,
January 2017, <https://www.w3.org/TR/WebCryptoAPI/>.
Appendix A. Guidelines for External Data Authentication of Algorithms ๐ฆ
Okay so, a chunk of the working group is super keen to loosen up the rule that the algorithm identifier has to show up at every level of a COSE object ๐ There are two main reasons for this ๐ธ
- First, the message gets smaller if the algorithm identifier is left out of the most common messages in a CoAP environment ๐
- Second, there's a sneaky potential bug if the full checking isn't done correctly across all the different spots an algorithm identifier could live: the message itself, an application statement, the key structure the sender has, and the key structure the recipient has ๐ญ
This appendix lays out how the change can be made, plus the details an application needs to specify if it wants to use this option โจ There are two different sets of details here: the ones needed to omit an algorithm identifier, and the ones needed to use a variant of the counter signature attribute that contains no attributes about itself ๐ง๐
A.1. Algorithm Identification โจ
Okay bestie, so this section lays out three sets of recommendations ๐ง. The first set is for when there's one implicit algorithm for a single layer of a COSE object. The second set is for when there are multiple implicit algorithms across multiple layers. The third set is for implicit algorithms spread over multiple COSE object constructs ๐ .
The key words from RFC 2119 are deliberately not used here. This specification can provide recommendations, but it cannot enforce them ๐.
This first set is for when an application hands out a fixed algorithm along with the key info for use in a single COSE object. It usually applies to the smallest COSE objects, which are COSE_Sign1, COSE_Mac0, and COSE_Encrypt0, but it could apply to the other structures too ๐.
Here's what to keep in mind:
- Applications need to list the set of COSE structures where implicit algorithms are used. They also need to require that receiving an explicit algorithm identifier in one of these structures gets the message rejected. This is so there's never any confusion about whether to use the implicit or the explicit algorithm ๐ฅ. This applies even if the transported algorithm identifier is a protected attribute. It also applies even if the transported algorithm is the same as the implicit algorithm.
- Applications need to define what counts as part of a context when algorithm identifiers are left out. At a minimum, that's the key identifier (if needed), the key, the algorithm, and the COSE structure it's used with. Applications should restrict the use of a single key to a single algorithm. As noted for some algorithms in this document, using the same key across different related algorithms can leak info about the key, leak info about the data, or make forgeries possible ๐.
- Applications that make the algorithm identifier implicit will often want to make the context identifier implicit too, for the same reason. Leaving out the context identifier shrinks the message size, which can be a lot depending on how long the identifier is โจ. Applications that do this need to describe when the context identifier gets omitted and how it's inferred in those cases. (Searching through all of the keys exhaustively would normally not be considered acceptable ๐ โโ๏ธ.) One example is tying the context to a transaction identifier. Both get sent on the original message, but after that only the transaction identifier needs to be sent, because the context is tied into it. Another way is to associate a context with a network address. All messages coming from one network address can be assumed to belong to a specific context. (In this case, the address would normally be distributed as part of the context.)
- You can't count on key identifiers being unique unless you put serious effort into computing them so that they're guaranteed unique ๐ง. Even then, uniqueness might break if the application runs in different contexts (meaning a different context provider), or if the system merges security contexts from different applications into one store ๐ฌ.
- Applications should keep protecting the algorithm identifier. Since it isn't protected by being placed in the protected attributes field, applications should define an application-specific external data structure that includes this value ๐. That external data field can be used this way for content encryption, MAC, and signature algorithms. It can go in the SuppPrivInfo field for algorithms that use a KDF to derive a key value. Applications may also want to protect other information that's part of the context structure. Note that fields such as the key or a Base IV are protected just by being used in the cryptographic computation, so they don't need to be included in the external data field ๐ฆ.
The second case is having multiple implicit algorithm identifiers specified for a multiple layer COSE object. An example is an encryption context that an application specifies, which contains a content encryption algorithm, a key wrap algorithm, a key identifier, and a shared secret ๐. The sender leaves out the algorithm identifier for both the content layer and the recipient layer, so only the key identifier is left. The receiver then uses the key identifier to look up the implicit algorithm identifiers ๐.
These additional items need to be taken into consideration:
- Applications that want to support this will need to define a structure that allows for, and clearly identifies, both the COSE structure used with a given key and the structure and algorithm used for the secondary layer. The key for the secondary layer is computed as normal from the recipient layer ๐.
The third case is having multiple implicit algorithm identifiers, but aimed at potentially unrelated layers or different COSE objects. There are a bunch of scenarios where this might come up. Some of them are:
- Two contexts are distributed as a pair. Each context is for use with a COSE_Encrypt message. Each one has its own distinct secret keys and IVs, and potentially even different algorithms. One context is for sending messages from party A to party B, and the other is for sending messages from party B to party A. That means there's no chance of a reflection attack, since each party uses different secret keys to send its messages. A message reflected back to its sender would fail to decrypt ๐ช.
- Two contexts are distributed as a pair. The first context is used to encrypt the message, and the second context is used to place a counter signature on the message. The second context can be handed out to other entities independently of the first. This lets those entities check that the message came from a particular individual, without being able to decrypt it and see the content ๐.
- Two contexts are distributed as a pair. The first context has a key for MACed messages, and the second context has a key for encrypted messages. This allows a unified distribution of keys to participants for different types of messages that use different keys, but where those keys may be used in a coordinated way ๐ค.
For these cases, the following additional items need to be considered:
- Applications need to make sure the multiple contexts stay associated. If one of the contexts gets invalidated for any reason, all of the contexts associated with it should also be invalidated ๐ซ.
A.2. Counter Signature without Headers ๐
There's a group of people who want a counter signature parameter that's directly tied to the value being signed, so the authenticated and unauthenticated buckets can be removed from the message being sent ๐ฅน. The goal here is an even smaller size, since all the info about how the counter signature was created is implicit rather than explicitly carried in the message. That includes not just the algorithm identifier from above, but also things like the key identification, which is always external to the signature structure ๐. This means the entities validating the counter signature are required to infer which key to use from context instead of it being explicit. One way to do that would be to assume all data coming from a specific port (or going to a specific URL) is validated by a specific key. (Note that the key identifier doesn't need to be part of the signed value, since it doesn't serve a cryptographic purpose. If the key validates the counter signature, then it should be presumed that the entity associated with that key produced the signature ๐.)
When computing the signature for the bare counter signature header, the same Sig_stucture defined in Section 4.4 is used. The sign_protected field is omitted, since there's no protected header field in this counter signature header. The value of "CounterSignature0" is placed in the context field of the Sig_stucture โจ.
+-------------------+-------+-------+-------+-----------------------+
| Name | Label | Value | Value | Description |
| | | Type | | |
+-------------------+-------+-------+-------+-----------------------+
| CounterSignature0 | 9 | bstr | | Counter signature |
| | | | | with implied signer |
| | | | | and headers |
+-------------------+-------+-------+-------+-----------------------+
Table 27: Header Parameter for CounterSignature0 ๐ธ
Appendix B. Two Layers of Recipient Information โจ
okay so, every recipient algorithm class that's defined right now only uses two layers of the COSE_Encrypt structure ๐ Layer one is the message content, and layer two is the content key encryption. BUT ๐ if you use a recipient algorithm like the RSA Key Encapsulation Mechanism (RSA-KEM) (see Appendix A of RSA-KEM [RFC5990]), then it actually makes sense to have three layers of the COSE_Encrypt structure.
Here are the layers:
- Layer 0: The content encryption layer. This layer contains the payload of the message.
- Layer 1: The encryption of the CEK by a KEK.
- Layer 2: The encryption of a long random secret using an RSA key and a key derivation function to convert that secret into the KEK.
This is an example of what a triple layer message looks like ๐ฆ The message has these layers:
- Layer 0: Has a content encrypted with AES-GCM using a 128-bit key.
- Layer 1: Uses the AES Key Wrap algorithm with a 128-bit key.
- Layer 2: Uses ECDH Ephemeral-Static direct to generate the layer 1 key.
In effect, this example is a decomposed version of using the ECDH-ES+A128KW algorithm. It's giving main character energy ๐
Size of binary file is 183 bytes
96(
[
/ protected / h'a10101' / {
\ alg \ 1:1 \ AES-GCM 128 \
} / ,
/ unprotected / {
/ iv / 5:h'02d1f7e6f26c43d4868d87ce'
},
/ ciphertext / h'64f84d913ba60a76070a9a48f26e97e863e2852948658f0
811139868826e89218a75715b',
/ recipients / [
[
/ protected / h'',
/ unprotected / {
/ alg / 1:-3 / A128KW /
},
/ ciphertext / h'dbd43c4e9d719c27c6275c67d628d493f090593db82
18f11',
/ recipients / [
[
/ 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''
]
]
]
]
]
)
Appendix C. Examples ๐
This appendix is a whole collection of examples showing the different features and message types defined in this document. They're written in the extended CBOR diagnostic notation (defined in [CDDL]) instead of as a binary dump, so they're way easier to read ๐ค
There's a GitHub project at https://github.com/cose-wg/Examples with these examples plus a much bigger set of testing examples ๐ Each example lives in a JSON file that has the inputs used to create it, some of the intermediate values you can use for debugging, and the output in both hex and CBOR diagnostic notation. Some of the examples over there are designed failure testing cases, and they're clearly marked as such in the JSON file. If errors in the examples in this document get found, the ones on GitHub will be updated, and a note about it will go in the JSON file.
As I said, the examples use CBOR's diagnostic notation. There's a Ruby-based tool that converts between diagnostic notation and binary. You can install it with this command line:
gem install cbor-diag
And you can turn diagnostic notation into binary files with this one:
diag2cbor.rb < inputfile > outputfile
You can pull the examples out of the XML version of this document with an XPath expression, since all the artwork is tagged with type='CBORdiag' ๐ง (Depending on which XPath evaluator you use, you might need to deal with > as an entity, just so you know ๐)
//artwork[@type='CDDL']/text()
C.1. Examples of Signed Messages
C.1.1. Single Signature
This example uses the following:
- Signature Algorithm: ECDSA w/ SHA-256, Curve P-256
Size of binary file is 103 bytes
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'
]
]
]
)
C.1.2. Multiple Signers
This example uses the following:
- Signature Algorithm: ECDSA w/ SHA-256, Curve P-256
- Signature Algorithm: ECDSA w/ SHA-512, Curve P-521
Size of binary file is 277 bytes
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
} / ,
/ unprotected / {
/ kid / 4:'bilbo.baggins@hobbiton.example'
},
/ signature / h'00a2d28a7c2bdb1587877420f65adf7d0b9a06635dd1
de64bb62974c863f0b160dd2163734034e6ac003b01e8705524c5c4ca479a952f024
7ee8cb0b4fb7397ba08d009e0c8bf482270cc5771aa143966e5a469a09f613488030
c5b07ec6d722e3835adb5b2d8c44e95ffb13877dd2582866883535de3bb03d01753f
83ab87bb4f7a0297'
]
]
]
)
C.1.3. Counter Signature
This example uses the following:
- Signature Algorithm: ECDSA w/ SHA-256, Curve P-256
- The same parameters are used for both the signature and the counter signature.
Size of binary file is 180 bytes
98(
[
/ protected / h'',
/ unprotected / {
/ countersign / 7:[
/ protected / h'a10126' / {
\ alg \ 1:-7 \ ECDSA 256 \
} / ,
/ unprotected / {
/ kid / 4:'11'
},
/ signature / h'5ac05e289d5d0e1b0a7f048a5d2b643813ded50bc9e4
9220f4f7278f85f19d4a77d655c9d3b51e805a74b099e1e085aacd97fc29d72f887e
8802bb6650cceb2c'
]
},
/ payload / 'This is the content.',
/ signatures / [
[
/ protected / h'a10126' / {
\ alg \ 1:-7 \ ECDSA 256 \
} / ,
/ unprotected / {
/ kid / 4:'11'
},
/ signature / h'e2aeafd40d69d19dfe6e52077c5d7ff4e408282cbefb
5d06cbf414af2e19d982ac45ac98b8544c908b4507de1e90b717c3d34816fe926a2b
98f53afd2fa0f30a'
]
]
]
)
C.1.4. Signature with Criticality
This example uses the following:
- Signature Algorithm: ECDSA w/ SHA-256, Curve P-256
- There is a criticality marker on the "reserved" header parameter
Size of binary file is 125 bytes
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'
]
]
]
)
C.2. Single Signer Examples
C.2.1. Single ECDSA Signature
This example uses the following:
- Signature Algorithm: ECDSA w/ SHA-256, Curve P-256
Size of binary file is 98 bytes
18(
[
/ protected / h'a10126' / {
\ alg \ 1:-7 \ ECDSA 256 \
} / ,
/ unprotected / {
/ kid / 4:'11'
},
/ payload / 'This is the content.',
/ signature / h'8eb33e4ca31d1c465ab05aac34cc6b23d58fef5c083106c4
d25a91aef0b0117e2af9a291aa32e14ab834dc56ed2a223444547e01f11d3b0916e5
a4c345cacb36'
]
)
C.3. Examples of Enveloped Messages
C.3.1. Direct ECDH
This example uses the following:
- CEK: AES-GCM w/ 128-bit key
- Recipient class: ECDH Ephemeral-Static, Curve P-256
Size of binary file is 151 bytes
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''
]
]
]
)
C.3.2. Direct Plus Key Derivation
This example uses the following:
- CEK: AES-CCM w/ 128-bit key, truncate the tag to 64 bits
- Recipient class: Use HKDF on a shared secret with the following implicit fields as part of the context.
- salt: "aabbccddeeffgghh"
- PartyU identity: "lighting-client"
- PartyV identity: "lighting-server"
- Supplementary Public Other: "Encryption Example 02"
Size of binary file is 91 bytes
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''
]
]
]
)
C.3.3. Counter Signature on Encrypted Content โจ
okay so this one is giving layers ๐ง. We've got an encrypted message and then a counter signature sitting on top of it, so the whole thing gets double-checked ๐
- CEK: AES-GCM w/ 128-bit key
- Recipient class: ECDH Ephemeral-Static, Curve P-256
Size of binary file is 326 bytes ๐
96(
[
/ protected / h'a10101' / {
\ alg \ 1:1 \ AES-GCM 128 \
} / ,
/ unprotected / {
/ iv / 5:h'c9cf4df2fe6c632bf7886413',
/ countersign / 7:[
/ protected / h'a1013823' / {
\ alg \ 1:-36
} / ,
/ unprotected / {
/ kid / 4:'bilbo.baggins@hobbiton.example'
},
/ signature / h'00929663c8789bb28177ae28467e66377da12302d7f9
594d2999afa5dfa531294f8896f2b6cdf1740014f4c7f1a358e3a6cf57f4ed6fb02f
cf8f7aa989f5dfd07f0700a3a7d8f3c604ba70fa9411bd10c2591b483e1d2c31de00
3183e434d8fba18f17a4c7e3dfa003ac1cf3d30d44d2533c4989d3ac38c38b71481c
c3430c9d65e7ddff'
]
},
/ 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''
]
]
]
)
C.3.4. Encrypted Content with External Data ๐ธ
this one brings in some outside info, the externally supplied AAD ๐ง it's just extra bytes that get fed into the process without being sent in the message itself. so cute, right? ๐ฅน
- CEK: AES-GCM w/ 128-bit key
- Recipient class: ECDH static-Static, Curve P-256 with AES Key Wrap
- Externally Supplied AAD:
h'0011bbcc22dd44ee55ff660077'
Size of binary file is 173 bytes ๐
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 \ ECHD-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'
]
]
]
)
C.4. Examples of Encrypted Messages ๐
C.4.1. Simple Encrypted Message ๐
the simplest of the simple. just one content encryption key doing its thing ๐ซถ
- CEK: AES-CCM w/ 128-bit key and a 64-bit tag
Size of binary file is 52 bytes โจ
16(
[
/ protected / h'a1010a' / {
\ alg \ 1:10 \ AES-CCM-16-64-128 \
} / ,
/ unprotected / {
/ iv / 5:h'89f52f65a1c580933b5261a78c'
},
/ ciphertext / h'5974e1b99a3a4cc09a659aa2e9e7fff161d38ce71cb45ce
460ffb569'
]
)
C.4.2. Encrypted Message with a Partial IV ๐ฆ
same vibe as the last one, but this time the IV gets trimmed down to a partial version, which is super efficient bestie ๐ง โจ
- CEK: AES-CCM w/ 128-bit key and a 64-bit tag
- Prefix for IV is 89F52F65A1C580933B52
Size of binary file is 41 bytes ๐
16(
[
/ protected / h'a1010a' / {
\ alg \ 1:10 \ AES-CCM-16-64-128 \
} / ,
/ unprotected / {
/ partial iv / 6:h'61a7'
},
/ ciphertext / h'252a8911d465c125b6764739700f0141ed09192de139e05
3bd09abca'
]
)
C.5. Examples of MACed Messages ๐งฟ
C.5.1. Shared Secret Direct MAC ๐
okay this is a MAC, which is basically a tag that proves the message wasn't messed with ๐ and the shared secret is doing all the heavy lifting here ๐
- MAC: AES-CMAC, 256-bit key, truncated to 64 bits
- Recipient class: direct shared secret
Size of binary file is 57 bytes ๐
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''
]
]
]
)
C.5.2. ECDH Direct MAC ๐ธ
this one uses ECDH to agree on the key with two static keys, and then HKDF with a context structure so the derived key is locked to its purpose ๐ฅฐ it's giving careful.
- MAC: HMAC w/SHA-256, 256-bit key
- Recipient class: ECDH key agreement, two static keys, HKDF w/ context structure
Size of binary file is 214 bytes ๐
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''
]
]
]
)
C.5.3. Wrapped MAC ๐
the MAC key itself gets wrapped with AES Key Wrap, using a pre-shared 256-bit key. like tucking a present inside another present ๐โจ
- MAC: AES-MAC, 128-bit key, truncated to 64 bits
- Recipient class: AES Key Wrap w/ a pre-shared 256-bit key
Size of binary file is 109 bytes ๐ง
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'
]
]
]
)
C.5.4. Multi-Recipient MACed Message ๐ซง
this is the big one, with a bunch of recipients all getting access to the same MAC ๐ the recipient class section mentions three different methods, and it's a whole vibe โจ
- MAC: HMAC w/ SHA-256, 128-bit key
- Recipient class: Uses three different methods
- ECDH Ephemeral-Static, Curve P-521, AES Key Wrap w/ 128-bit key
- AES Key Wrap w/ 256-bit key
Size of binary file is 309 bytes ๐
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 \ ECHD-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'
]
]
]
)
C.6. Examples of MAC0 Messages ๐ง
C.6.1. Shared Secret Direct MAC ๐ท
this is the MAC0 version, same family as before but a bit more streamlined ๐ฆ
- MAC: AES-CMAC, 256-bit key, truncated to 64 bits
- Recipient class: direct shared secret
Size of binary file is 37 bytes โจ
17(
[
/ protected / h'a1010f' / {
\ alg \ 1:15 \ AES-CBC-MAC-256//64 \
} / ,
/ unprotected / {},
/ payload / 'This is the content.',
/ tag / h'726043745027214f'
]
)
Note that this example uses the same inputs as Appendix C.5.1.
C.7. COSE Keys ๐
C.7.1. Public Keys ๐๏ธ
this is a COSE Key Set with the public keys for all of the examples we've looked at so far ๐ there are four keys in it, in this order:
- An EC key with a kid of "meriadoc.brandybuck@buckland.example"
- An EC key with a kid of "peregrin.took@tuckborough.example"
- An EC key with a kid of "bilbo.baggins@hobbiton.example"
- An EC key with a kid of "11"
Size of binary file is 481 bytes ๐ซถ
[
{
-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'
}
]
C.7.2. Private Keys ๐
okay so this one is the private key set ๐ It's giving "here's the whole squad's secret stuff" and it includes the private keys for every example we've looked at so far. ๐ซถ
In order, the keys are:
- An EC key with a kid of
meriadoc.brandybuck@buckland.example๐ธ - A shared-secret key with a kid of
our-secret๐คซ - An EC key with a kid of
peregrin.took@tuckborough.example๐ฆ - A shared-secret key with a kid of
018c0ae5-4d9b-471b-bfd6-eef314bc7037๐ - An EC key with a kid of
bilbo.baggins@hobbiton.example๐ง - An EC key with a kid of
11๐
Size of binary file is 816 bytes ๐ฆ
[
{
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'
}
]
Acknowledgments ๐
This document is a product of the COSE working group of the IETF. ๐
The following individuals are to blame for getting me started on this project in the first place: Richard Barnes, Matt Miller, and Martin Thomson. ๐ literally the origin story, bestie ๐ญ
The initial version of the specification was based to some degree on the outputs of the JOSE and S/MIME working groups. โจ
The following individuals provided input into the final form of the document: Carsten Bormann, John Bradley, Brain Campbell, Michael B. Jones, Ilari Liusvaara, Francesca Palombini, Ludwig Seitz, and Goran Selander. ๐ the whole council showed up, iconic ๐ซถ
Author's Address ๐
Jim Schaad August Cellars
Email: ietf@augustcellars.com ๐ฆ
๐ฆ where this page comes from
- ietf: rfc8152 2017-07
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms