RFC 8152

CBOR Object Signing and Encryption (COSE)

๐Ÿ“… published July 2017, from ietf

๐ŸŽ€ 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 (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 ๐Ÿ› ๏ธ.

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:

  1. The set of protected header parameters, wrapped in a bstr.
  2. The set of unprotected header parameters, as a map.
  3. 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 ๐Ÿ•ต๏ธโ€โ™€๏ธ:

  1. 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.
  2. 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 ๐Ÿท๏ธ.
  3. 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 ๐Ÿ’Œ.
  4. 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
  1. 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:

  1. Left-pad the Partial IV with zeros to the length of IV.
  2. 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:

  1. 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.
  2. 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.
  3. 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.
  4. 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.)
  5. 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 ๐Ÿง:

  1. Create a Sig_structure and populate it with the appropriate fields.
  2. Create the value ToBeSigned by encoding the Sig_structure to a byte string, using the encoding described in Section 14.
  3. 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).
  4. Place the resulting signature value in the 'signature' field of the array.

The steps for verifying a signature are:

  1. Create a Sig_structure object and populate it with the appropriate fields.
  2. Create the value ToBeSigned by encoding the Sig_structure to a byte string, using the encoding described in Section 14.
  3. 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:

  1. 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 ๐Ÿงš

  1. The protected attributes from the body structure, encoded as a bstr. If there are no protected attributes, you use a bstr of length zero ๐Ÿ“
  2. 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: ๐Ÿ’…

  1. Create an Enc_structure and fill in the appropriate fields.
  2. Encode the Enc_structure to a byte stream (this is the Additional Authenticated Data, or AAD), using the encoding described in Section 14.
  3. 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 ๐ŸŽฒ

  1. 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 ๐Ÿ’–
  2. 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: ๐Ÿฆ‹

  1. Create an Enc_structure and fill in the appropriate fields.
  2. Encode the Enc_structure to a byte stream (AAD), using the encoding described in Section 14.
  3. 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 ๐Ÿ‘‘

  1. 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: ๐Ÿ’…

  1. Verify that the 'protected' field is empty. ๐Ÿซถ
  2. Verify that there was no external additional authenticated data supplied for this operation. ๐Ÿ™ˆ
  3. 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 ๐ŸŽฒ

  1. 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 ๐Ÿ’–
  2. 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: ๐Ÿฆ‹

  1. Verify that the 'protected' field is empty. ๐Ÿซถ
  2. Verify that there was no external additional authenticated data supplied for this operation. ๐Ÿ™ˆ
  3. 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 ๐Ÿ‘‘

  1. 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:

  1. A text string that names the structure being encoded. It's "MAC" for the COSE_Mac structure and "MAC0" for the COSE_Mac0 structure.
  2. The protected attributes from the COSE_MAC structure. If there are no protected attributes, a zero-length bstr is used ๐Ÿซถ
  3. 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 ๐Ÿ’…)
  4. 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:

  1. Create a MAC_structure and fill it with the appropriate fields.
  2. Create the value ToBeMaced by encoding the MAC_structure to a byte stream, using the encoding described in Section 14.
  3. 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).
  4. Place the resulting MAC in the tag field of the COSE_Mac or COSE_Mac0 structure.
  5. Encrypt and encode the MAC key for each recipient of the message. ๐Ÿ”‘

The steps to verify a MAC are:

  1. Create a MAC_structure object and fill it with the appropriate fields.
  2. Create the value ToBeMaced by encoding the MAC_structure to a byte stream, using the encoding described in Section 14.
  3. Obtain the cryptographic key from one of the recipients of the message.
  4. 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).
  5. Compare the MAC value to the tag field 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 kty field MUST be present, and it MUST be 'EC2'.
  • If the alg field is present, it MUST match the ECDSA signature algorithm being used.
  • If the key_ops field is present, it MUST include 'sign' when creating an ECDSA signature.
  • If the key_ops field 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 kty field MUST be present, and it MUST be 'OKP' (Octet Key Pair).
  • The crv field MUST be present, and it MUST be a curve defined for this signature algorithm.
  • If the alg field is present, it MUST match 'EdDSA'.
  • If the key_ops field is present, it MUST include 'sign' when creating an EdDSA signature.
  • If the key_ops field 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^56 possible 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 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.

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, the Enc_structure, and the MAC_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. ๐Ÿ’…

  1. 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.
  2. 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.
  3. 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.
  4. 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. ๐Ÿ”ฅ
  5. 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:
    • Advertising in the message (S/MIME capabilities) [RFC5751].
    • Advertising in the certificate (capabilities extension) [RFC4262].
    • Minimum requirements for the S/MIME, which have been updated over time [RFC2633] [RFC5751] (note that [RFC2633] has been obsoleted by [RFC5751]).

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

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 &gt; 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
    1. ECDH Ephemeral-Static, Curve P-521, AES Key Wrap w/ 128-bit key
    2. 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