Skip to main content

5. Encryption Objects

  1. Encryption Objects

COSE supports two different encryption structures. COSE_Encrypt0 is used when a recipient structure is not needed because the key to be used is known implicitly. COSE_Encrypt is used the rest of the time. This includes cases where there are multiple recipients or a recipient algorithm other than direct (i.e., preshared secret) is used.

5.1. Enveloped COSE Structure

The enveloped structure allows for one or more recipients of a message. There are provisions for header parameters about the content and header parameters about the recipient information to be carried in the message. The protected header parameters associated with the content are authenticated by the content encryption algorithm. The protected header parameters associated with the recipient (when the algorithm supports it) are authenticated by the recipient algorithm. Examples of header parameters about the content are the type of the content and the content encryption algorithm. Examples of header parameters about the recipient are the recipient's key identifier and the recipient's encryption algorithm.

The same techniques and nearly the same structure are used for encrypting both the plaintext and the keys. This is different from the approach used by both "Cryptographic Message Syntax (CMS)" [RFC5652] and "JSON Web Encryption (JWE)" [RFC7516], where different structures are used for the content layer and the recipient layer. Two structures are defined: COSE_Encrypt to hold the encrypted content and COSE_recipient to hold the encrypted keys for recipients. Examples of enveloped messages can be found in Appendix C.3.

The COSE_Encrypt structure can be encoded as either tagged or untagged, depending on the context it will be used in. A tagged COSE_Encrypt structure is identified by the CBOR tag 96. The CDDL fragment that represents this is:

COSE_Encrypt_Tagged = #6.96(COSE_Encrypt)

The COSE_Encrypt 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.

ciphertext: This field contains the ciphertext, encoded as a bstr. If the ciphertext is to be transported independently of the control information about the encryption process (i.e., detached content), then the field is encoded as a nil value.

recipients: This field contains an array of recipient information structures. The type for the recipient information structure is a COSE_recipient.

The CDDL fragment that corresponds to the above text is:

COSE_Encrypt = [ Headers, ciphertext : bstr / nil, recipients : [+COSE_recipient] ]

The COSE_recipient 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.

ciphertext: This field contains the encrypted key, encoded as a bstr. All encoded keys are symmetric keys; the binary value of the key is the content. If there is not an encrypted key, then this field is encoded as a nil value.

recipients: This field contains an array of recipient information structures. The type for the recipient information structure is a COSE_recipient (an example of this can be found in Appendix B). If there are no recipient information structures, this element is absent.

The CDDL fragment that corresponds to the above text for COSE_recipient is:

COSE_recipient = [ Headers, ciphertext : bstr / nil, ? recipients : [+COSE_recipient] ]

5.1.1. Content Key Distribution Methods

An encrypted message consists of an encrypted content and an encrypted CEK for one or more recipients. The CEK is encrypted for each recipient, using a key specific to that recipient. The details of this encryption depend on which class the recipient algorithm falls into. Specific details on each of the classes can be found in Section 8.5. A short summary of the five content key distribution methods is:

direct: The CEK is the same as the identified previously distributed symmetric key or is derived from a previously distributed secret. No CEK is transported in the message.

symmetric key-encryption keys (KEKs): The CEK is encrypted using a previously distributed symmetric KEK. Also known as key wrap.

key agreement: The recipient's public key and a sender's private key are used to generate a pairwise secret, a Key Derivation Function (KDF) is applied to derive a key, and then the CEK is either the derived key or encrypted by the derived key.

key transport: The CEK is encrypted with the recipient's public key.

passwords: The CEK is encrypted in a KEK that is derived from a password. As of when this document was published, no password algorithms have been defined.

5.2. Single Recipient Encrypted

The COSE_Encrypt0 encrypted structure does not have the ability to specify recipients of the message. The structure assumes that the recipient of the object will already know the identity of the key to be used in order to decrypt the message. If a key needs to be identified to the recipient, the enveloped structure ought to be used.

Examples of encrypted messages can be found in Appendix C.4.

The COSE_Encrypt0 structure can be encoded as either tagged or untagged, depending on the context it will be used in. A tagged COSE_Encrypt0 structure is identified by the CBOR tag 16. The CDDL fragment that represents this is:

COSE_Encrypt0_Tagged = #6.16(COSE_Encrypt0)

The COSE_Encrypt0 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.

ciphertext: This is as described in Section 5.1.

The CDDL fragment for COSE_Encrypt0 that corresponds to the above text is:

COSE_Encrypt0 = [ Headers, ciphertext : bstr / nil, ]

5.3. How to Encrypt and Decrypt for AEAD Algorithms

The encryption algorithm for AEAD algorithms is fairly simple. The first step is to create a consistent byte string for the authenticated data structure. For this purpose, we use an Enc_structure. The Enc_structure is a CBOR array. The fields of the Enc_structure, in order, are:

  1. A context text string identifying the context of the authenticated data structure. The context text string is:

    "Encrypt0" for the content encryption of a COSE_Encrypt0 data structure.

    "Encrypt" for the first layer of a COSE_Encrypt data structure (i.e., for content encryption).

    "Enc_Recipient" for a recipient encoding to be placed in a COSE_Encrypt data structure.

    "Mac_Recipient" for a recipient encoding to be placed in a MACed message structure.

    "Rec_Recipient" for a recipient encoding to be placed in a recipient structure.

  2. The protected attributes from the body structure, encoded in a bstr type. If there are no protected attributes, a zero-length byte string is used.

  3. The externally supplied data from the application encoded in a bstr type. If this field is not supplied, it defaults to a zero- length byte string. (See Section 4.3 for application guidance on constructing this field.)

The CDDL fragment that describes the above text 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 populate it with the appropriate fields.

  2. Encode the Enc_structure to a byte string (Additional Authenticated Data (AAD)), using the encoding described in Section 9.

  3. Determine the encryption key (K). This step is dependent on the class of recipient algorithm being used. For:

    No Recipients: The key to be used is determined by the algorithm and key at the current layer. Examples are key wrap keys (Section 8.5.2) and preshared secrets.

    Direct Encryption and Direct Key Agreement: The key is determined by the key and algorithm in the recipient structure. The encryption algorithm and size of the key to be used are inputs into the KDF used for the recipient. (For direct, the KDF can be thought of as the identity operation.) Examples of these algorithms are found in Sections 6.1 and 6.3 of [RFC9053].

    Other: The key is randomly generated.

  4. Call the encryption algorithm with K (the encryption key), P (the plaintext), and AAD. Place the returned ciphertext into the "ciphertext" field of the structure.

  5. For recipients of the message using non-direct algorithms, 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 populate it with the appropriate fields.

  2. Encode the Enc_structure to a byte string (AAD), using the encoding described in Section 9.

  3. Determine the decryption key. This step is dependent on the class of recipient algorithm being used. For:

    No Recipients: The key to be used is determined by the algorithm and key at the current layer. Examples are key wrap keys (Section 8.5.2) and preshared secrets.

    Direct Encryption and Direct Key Agreement: The key is determined by the key and algorithm in the recipient structure. The encryption algorithm and size of the key to be used are inputs into the KDF used for the recipient. (For direct, the KDF can be thought of as the identity operation.)

    Other: The key is determined by decoding and decrypting one of the recipient structures.

  4. 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 a zero-length byte string.

  2. Verify that there was no external additional authenticated data supplied for this operation.

  3. Determine the encryption key. This step is dependent on the class of recipient algorithm being used. For:

    No Recipients: The key to be used is determined by the algorithm and key at the current layer. Examples are key wrap keys (Section 8.5.2) and preshared secrets.

    Direct Encryption and Direct Key Agreement: The key is determined by the key and algorithm in the recipient structure. The encryption algorithm and size of the key to be used are inputs into the KDF used for the recipient. (For direct, the KDF can be thought of as the identity operation.) Examples of these algorithms are found in Sections 6.1 and 6.3 of [RFC9053].

    Other: The key is randomly generated.

  4. Call the encryption algorithm with K (the encryption key to use) and P (the plaintext). Place the returned ciphertext into the "ciphertext" field of the structure.

  5. For recipients of the message using non-direct algorithms, 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 a zero-length byte string.

  2. Verify that there was no external additional authenticated data supplied for this operation.

  3. Determine the decryption key. This step is dependent on the class of recipient algorithm being used. For:

    No Recipients: The key to be used is determined by the algorithm and key at the current layer. Examples are key wrap keys (Section 8.5.2) and preshared secrets.

    Direct Encryption and Direct Key Agreement: The key is determined by the key and algorithm in the recipient structure. The encryption algorithm and size of the key to be used are inputs into the KDF used for the recipient. (For direct, the KDF can be thought of as the identity operation.) Examples of these algorithms are found in Sections 6.1 and 6.3 of [RFC9053].

    Other: The key is determined by decoding and decrypting one of the recipient structures.

  4. Call the decryption algorithm with K (the decryption key to use) and C (the ciphertext).