JOSE Working Group R. Barnes Internet-Draft BBN Intended status: Informational April 03, 2013 Expires: October 5, 2013 Proposed Refactoring of JOSE to Align Encryption and Key Wrapping draft-barnes-jose-key-wrapping-00 Abstract The discussions around key wrapping in the JOSE working group have raised new requirements for wrapped keys, namely: (1) Wrapping keys other than symmetric keys, (2) cryptographically binding attributes to keys, and (3) allowing the use of AEAD cryptographic algorithms for key wrapping (other than AES-KW). This document proposes a refactoring of the JOSE document set that provides a cleaner conceptual structure for JWS / JWE and transparent support for wrapped keys, all with a relatively minor impact on the compact form of JWS and JWE objects. Status of this Memo This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet- Drafts is at http://datatracker.ietf.org/drafts/current/. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." This Internet-Draft will expire on October 5, 2013. Copyright Notice Copyright (c) 2013 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect Barnes Expires October 5, 2013 [Page 1] Internet-Draft JOSE Refactor April 2013 to 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 and are provided without warranty as described in the Simplified BSD License. Table of Contents 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 3 2. Requirements . . . . . . . . . . . . . . . . . . . . . . . . . 5 3. Proposed Changes . . . . . . . . . . . . . . . . . . . . . . . 6 4. Summary of Benefits / Costs . . . . . . . . . . . . . . . . . 7 5. Example: Current vs. Proposed . . . . . . . . . . . . . . . . 8 5.1. AES-GCM with AES-KW wrapping . . . . . . . . . . . . . . . 8 5.2. AES-GCM with AES-GCM wrapping . . . . . . . . . . . . . . 10 6. Rationale . . . . . . . . . . . . . . . . . . . . . . . . . . 12 6.1. Requirements and Goals . . . . . . . . . . . . . . . . . . 12 6.2. JWE vs Key Wrapping . . . . . . . . . . . . . . . . . . . 12 6.3. JWE with Wrapped Keys . . . . . . . . . . . . . . . . . . 14 6.4. Impact on the Compact Format . . . . . . . . . . . . . . . 16 6.5. JWS . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 6.6. Summary . . . . . . . . . . . . . . . . . . . . . . . . . 18 7. Revised JSON Format and Translation to Compact . . . . . . . . 19 7.1. Translation from JSON to Compact . . . . . . . . . . . . . 19 7.2. Translation from Compact to JSON . . . . . . . . . . . . . 20 8. Disposition of Header Fields (Proposal Part 3) . . . . . . . . 22 9. Key Wrapping Procedure (Proposal Part 4) . . . . . . . . . . . 24 9.1. Wrapping procedure . . . . . . . . . . . . . . . . . . . . 24 9.2. Unwrapping Procedure . . . . . . . . . . . . . . . . . . . 25 10. Compact JWK Marshaling (Proposal Part 4) . . . . . . . . . . . 26 10.1. JWKS2 . . . . . . . . . . . . . . . . . . . . . . . . . . 26 10.2. JWKS3 . . . . . . . . . . . . . . . . . . . . . . . . . . 27 10.3. Test Cases . . . . . . . . . . . . . . . . . . . . . . . . 28 10.4. Performance on Test Cases . . . . . . . . . . . . . . . . 29 11. Security Considerations . . . . . . . . . . . . . . . . . . . 30 12. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 31 13. Normative References . . . . . . . . . . . . . . . . . . . . . 32 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 33 Barnes Expires October 5, 2013 [Page 2] Internet-Draft JOSE Refactor April 2013 1. Introduction The goal of a JOSE object is to provide the recipient with the result of a cryptographic operation (encryption or signature) and instructions for how to process that result. These instructutions are in two main parts: (1) A cryptographic algorithm to be applied, and (2) the key to be used with that algorithm (in wrapped form). The current structure of the JWE and JWS headers scatters these two information elements across several different header parameters. For example, if an object has been encrypted with the "direct" mode of key agreement, then the recipient must reconstruct the algorithm from the "enc", "epu", and "epv" parameters. If a developer wants to validate that a JOSE algorithm has all required parameters for a given algorithm, he must search through all header fields. It would help clarify the structure of JOSE objects if algorithm parameters and key parameters could be grouped together. We propose to make two changes to the JWE and JWS headers: 1. Re-define the "alg" parameter to contain all necessary parameters to describe the encryption algorithm. 2. Define a new "key" parameter to contain all necessary paramters to describe the CMK. This restructuring also simplifies key wrapping, by using JWE for key wrapping. Since the encrypted CMK is just another encrypted object, and because the wrapped key is encapsulated in the "key" object, it can re-use the "alg" and "enc" fields - making the encrypted key just another JWE. The following example shows how the proposed refactoring changes the implicit grouping of key-related fields in JWE into an explicit grouping. Current: {"enc":"A128CBC+HS256", "alg":"RSA1_5","kid":"1" } Proposed: {"alg":"A128CBC+HS256","key":{"alg":"RSA1_5","key":"1"}} Figure 1 This example JWE has three fields, "enc", "alg", and "kid". One of these fields relates to how the content of the JWE itself is encrypted; the other two relate to how the key is encrypted. The proposed syntax groups the key-related fields together into a JSON object. In fact, this new object can be thought of a second JWE, encrypting the key instead of the content. This change has a minimal impact on the JWE and JWS compact serializations, both in terms of representation and processing. In Barnes Expires October 5, 2013 [Page 3] Internet-Draft JOSE Refactor April 2013 the example above, the proposed header has the same information content as the original header, and is only 8 octets longer. For JWE, the proposed form even offers a simplification in processing, since the encrypted key can be processed with the same code as the encrypted content - both are JWEs. The proposed form also allows for a much cleaner JSON representation than is currently allowed. The following figure illustrates the current and proposed JSON serializations. The proposed serialization is much more developer friendly, since it exposes header information directly, instead of in a base64-encoded string. Current: { "recipients": [{ "header": "....", "encrypted_key": "...". "integrity_value": "..." }], "initialization_vector": "...", "ciphertext": "..." } Proposed: { "alg": { "name": "A128CBC+HS256", "iv": "..." }, "key": { "alg":"RSA1_5", "key":"1" "data": "..." } "data": "...", "mac": "..." } Figure 2 The remainder of this document describes the rational for the proposed changes in more detail, and provides an outline of the detailed changes that would be needed to implement the proposal. Barnes Expires October 5, 2013 [Page 4] Internet-Draft JOSE Refactor April 2013 2. Requirements o Enable key wrapping with JWE o Avoid having more than one format for the same key wrapped with the same algorithm o Enable key wrapping with all AEAD algorithms, for JWE as well as external wrapped keys o Enable password-based encryption for JWE Barnes Expires October 5, 2013 [Page 5] Internet-Draft JOSE Refactor April 2013 3. Proposed Changes o JWE/JWS: Define required "alg" and "key" parameters * "alg": JWA algorithm object * "key": Key identifier or JWE containing encrypted key o JWE/JWS: Define a revised JSON serialization and mapping to the compact serialization o JWA: Refactor to describe algorithm objects for JWE/JWS * Move algorithm parameters from JWE to JWA * Define validation rules per algorithm (which parameters are required) * Add password-based encryption parameters o JWK: Define a procedure for using JWE to wrap keys * OPTIONAL: Define a compact serialization for keys Details of these proposals are described below. Barnes Expires October 5, 2013 [Page 6] Internet-Draft JOSE Refactor April 2013 4. Summary of Benefits / Costs o Costs: * Few (<30) bytes of extra header overhead * Breaks compatibility with old code o Benefits: * Clean architecture covering JWE, JWS, wrapped JWK * Code re-use bewteen JWE processing and wrapped key processing * Easier validation rules for algorithm parameters * Key wrapping based on JWE in all cases * Support for new use cases in compact serialization * Key management for MAC Barnes Expires October 5, 2013 [Page 7] Internet-Draft JOSE Refactor April 2013 5. Example: Current vs. Proposed In this section, we consider two examples of how the proposed serialization offers cleaner syntax and more flexibility than the current structure. First, we look at a JWE encrypted with AES-GCM, using a key wrapped with AES-KW. This allows us to directly compare the two formats. Second, we consider the same JWE, but using a key that is also protected with AES-GCM. This case is easily supported in the proposed syntax, but impossible to support in the current syntax. In both cases, the parties have a pre-shared key with identifier "preSharedKey". 5.1. AES-GCM with AES-KW wrapping To create an an object encrypted with AES-GCM and AES-KW, we need to specify the following parameters: o Algorithm name (A128GCM) o Key wrapping algorithm (AES-KW) o Key wrapping key ID ("preSharedKey") o 96-bit initialization vector o Wrapped key o Ciphertext o Integrity check value In the current compact form, the header encodes the first three of these, and the remainder are appended as base64url-encoded components. CURRENT-COMPACT-HEADER: {"enc":"A128GCM","alg":"A128KW","kid":"preSharedKey"} CURRENT-COMPACT: eyJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiQTEyOEtXIiwia2lkIjoicHJlU2h hcmVkS2V5In0K .Pe15h6BYJ7SrEq0ev8m9ce4vq4phLFJK .hRskpf3RwFQmEKQ5 .jZpHMF7GhBNYSD5QIJkBXWu6POh_KTN5 .b2ersuWujfIaoghd5kOpWw Figure 3 Barnes Expires October 5, 2013 [Page 8] Internet-Draft JOSE Refactor April 2013 In the proposed compact form, the header would have the same information, but arranged so that the key-wrapping parameters ("alg", "kid") are gathered under a "key" parameter. The remaining components are appended in the same way. PROPOSED-COMPACT-HEADER: {"alg":"A128GCM", "key":{"alg":"A128KW","key":"preSharedKey"}} PROPOSED-COMPACT eyJhbGciOiJBMTI4R0NNIiwia2V5Ijp7ImFsZyI6IkExMjhLVyIsImtleSI 6InByZVNoYXJlZEtleSJ9fQo .Pe15h6BYJ7SrEq0ev8m9ce4vq4phLFJK .hRskpf3RwFQmEKQ5 .jZpHMF7GhBNYSD5QIJkBXWu6POh_KTN5 .b2ersuWujfIaoghd5kOpWw Figure 4 The proposed compact form of this JWE object is 189 octets long, while the current form is 178. So the overhead imposed by the refactoring is 11 octets, or 6%. The difference is clearer with regard to the JSON representations. The current JSON form is just as opaque as the compact form. By contrast, the proposed JSON form provides the header information without base64-encoding, making it more easily accessible. The UTF-8 serialization of the proposed JSON syntax is also 27% shorter than the serialization of the current JSON syntax (209 vs. 287 octets). CURRENT-JSON: { "recipients": [{ "header": "eyJlbmMiOiJBMTI4R0NNIiwiYWxnIjoiQTEyOEtX Iiwia2lkIjoicHJlU2hhcmVkS2V5In0K", "encrypted_key": "Pe15h6BYJ7SrEq0ev8m9ce4vq4phLFJK" "integrity_value": "b2ersuWujfIaoghd5kOpWw" }], "initialization_vector": "hRskpf3RwFQmEKQ5", "ciphertext": "jZpHMF7GhBNYSD5QIJkBXWu6POh_KTN5" } Figure 5 Barnes Expires October 5, 2013 [Page 9] Internet-Draft JOSE Refactor April 2013 PROPOSED-JSON: { "alg": { "name": "A128GCM", "iv": "hRskpf3RwFQmEKQ5" }, "key": { "alg": "A128KW", "key": "preSharedKey", "data": "Pe15h6BYJ7SrEq0ev8m9ce4vq4phLFJK" }, "data": "jZpHMF7GhBNYSD5QIJkBXWu6POh_KTN5", "mac": "b2ersuWujfIaoghd5kOpWw" } Figure 6 5.2. AES-GCM with AES-GCM wrapping The proposed syntax uses JWE to wrap the keys used for JWE. This allows key wrapping to take advantage of all of the algorithms available for content encryption. So while key wrapping with AES-GCM is impossible with current JWE specification, the proposed modification makes it possible, in both JSON and compact form. The JSON syntax shows how the parameters are laid out. The "alg" parameter at the top level specifies the parameters for the content encryption. The "key" parameter at the top level contains the wrapped key as a JWE, with its own "alg" parameter specifying independent parameters for GCM. The "data" attribute of the "key" object (key.data) contains the wrapped key, and the "mac" attribute (key.mac) contains the GCM integrity check value over the key. The "data" and "mac" attributes at the top level contain the encrypted content and its integrity check value. A recipient would process this JWE in the same manner as a normal JWE. First, the recipient decrypts the key using the GCM parameters inside the "key" parameter and the key identified by "preSharedKey". Second, the recipient decrypts the content using the top-level GCM parameters and the unwrapped key. Barnes Expires October 5, 2013 [Page 10] Internet-Draft JOSE Refactor April 2013 PROPOSED-JSON: { "alg": { "name": "A128GCM", "iv": "wkir6xYeu2uYfCRM" }, "key": { "alg": { "name": "A128GCM", "iv": "F6va6e3mFryvrk34" } "key": "preSharedKey", "data": "R1mdiiHJvI98Dh634xPN4Q", "mac": "Ia5YAJ6XniSL3WGBSlbkXA" }, "data": "6J1u_z-LhIm0GsDVV6o-s_1p2MKJFq5_", "mac": "e3LqKZrivwH-oHtsa1TStQ" } Figure 7 Even though this object uses parameters that cannot be accounted for in the current JWE compact encoding, it can still be rendered in the compact encoding. The parameters that the compact encoding accommodates are moved out of the header, including the top-level IV, the encrypted key, the ciphertext, and the integrity check value. The other binary parameters (the key wrapping IV and integrity check value) remain in the header. PROPOSED-COMPACT-HEADER: {"alg":"A128GCM","key":{"alg":{"name":"A128KW", "iv":"F6va6e3mFryvrk34"},"key":"preSharedKey", "mac":"Ia5YAJ6XniSL3WGBSlbkXA"}} PROPOSED-COMPACT: eyJhbGciOiJBMTI4R0NNIiwia2V5Ijp7ImFsZyI6eyJuYW1lIjoiQTEyOEt XIiwiaXYiOiJGNnZhNmUzbUZyeXZyazM0In0sImtleSI6InByZVNoYXJlZE tleSIsIm1hYyI6IklhNVlBSjZYbmlTTDNXR0JTbGJrWEEifX0K .R1mdiiHJvI98Dh634xPN4Q .wkir6xYeu2uYfCRM .6J1u_z-LhIm0GsDVV6o-s_1p2MKJFq5_ .e3LqKZrivwH-oHtsa1TStQ Figure 8 This compact encoding is larger than the one in the previous example (264 vs. 209 octets), but 25% shorter than the base64url-encoded serialization of the JSON form (264 vs. 352 octets). Barnes Expires October 5, 2013 [Page 11] Internet-Draft JOSE Refactor April 2013 6. Rationale 6.1. Requirements and Goals In the course of the key wrapping discussions in JOSE, a few new requirements have arisen: o Wrap private and symmetric keys o Wrap keys with attributes attached. o Wrap keys using general AEAD algorithms (e.g., AES-GCM) o Encrypt keys and JWEs with password-based encryption A design goal in meeting these requirements should be to duplicate functionality as little as possible. For example, it would violate this goal to have JWE define one way of encrypting a symmetric key with no attributes, and for a JWK key wrapping specification to define another. In addition, we would like to avoid the need for obscure algorithms, in particular RSA-KEM. With the above requirements and goals in mind, compare the algorithm requirements of JWE and wrapped JWK: JWE JWK AES-GCM & other AEAD X X AES Key Wrap X RSA Encryption X Key Agreement X Password-based Enc. X X Figure 9 It makes one wonder whether it might make sense to use the same framework for both of these. 6.2. JWE vs Key Wrapping As a starting point for considering whether we can align JWE and wrapped JWKs, let's compare a JWE performing direct encryption with AES-GCM with a notional wrapped key using AES-KW derived from the JWE wrapped key format: Barnes Expires October 5, 2013 [Page 12] Internet-Draft JOSE Refactor April 2013 JWE (notional) JWE Key Wrap (notional) ------------------------------------- ---------------------------- { { alg: "dir" enc: "A128GCM", alg: "A128KW", iv: "...", kid: "this", kid: "that", data:"..." data:"..." mac: "..." } } ------------------------------------- ---------------------------- Figure 10 Here I've assigned some names in JSON to fields that don't have names in JWE. I've labeled the JWE Initialization Vector as "iv", the JWE Ciphertext as "data", and the JWE Integrity Value as "mac". Now, suppose we say that a missing "alg" parameter means that "alg" is assumed to be direct. This isn't too unreasonable, since "alg" indicates a key wrapping algorithm, and there's no key wrapping going on here. Then we can omit the alg parameter: JWE (modified) JWE Key Wrap (notional) ------------------------------------- ---------------------------- { { enc: "A128GCM", iv: "...", alg: "A128KW", kid: "this", kid: "that", data:"..." data:"..." mac: "..." } } ------------------------------------- ---------------------------- Figure 11 The two objects start to look very similar now. They each have three critical sections: 1. A specification of the encryption algorithm and any necessary parameters. (AES-KW requires no parameters, of course.) 2. An identifier for the key being used 3. The ciphertext output of the algorithm We can make the syntax match this conceptual model if we just put the parameters in an object together with the algorithm name. For symmetry, we'll call the algorithm parameter "alg" in both cases; we'll rename "kid" to "key" for reasons that will be apparent in a moment. Barnes Expires October 5, 2013 [Page 13] Internet-Draft JOSE Refactor April 2013 JWE (modified) JWE Key Wrap (notional) ------------------------------------- ---------------------------- { { alg: {name: "A128GCM", iv: "..."}, alg: "A128KW", key: "this", key: "that", data:"..." data:"..." mac: "..." } } ------------------------------------- ---------------------------- Figure 12 So with a few minor simplifications to the JWE header format, we've created a structure that applies naturally to both general encryption (JWE) and key encryption specifically (JWK Key Wrap). The only difference is the "mac" field, which can be optional, since AES-KW has an internal integrity check, much like AES-CCM. 6.3. JWE with Wrapped Keys Now, how do we deal with JWEs that use a wrapped CMK in this framework? Well, the whole point of the last section was to make JWEs the same as wrapped keys - so we allow the "key" attribute to be a JWE containing the wrapped CMK. For example, if we combine the two objects from the previous section, we can have a JWE representing an encryption with AES-GCM under a key protected with AES-KW. { alg: { name: "A128GCM", iv: "..." }, key: { alg: "A128KW", key: "that", data: "..." }, data: "..." mac: "..." } Figure 13 This gives a simple, self-similar structure for wrapped keys. The self-similarity allows us to transparently account for more advanced use cases. For example, if someone wanted to use a CMK that came along with a bunch of attributes, they could use RSA to wrap another symmetric key, and use AES-GCM to wrap the CMK. Barnes Expires October 5, 2013 [Page 14] Internet-Draft JOSE Refactor April 2013 { alg: { name: "A128GCM", iv: "..." }, key: { alg: "A128GCM", key: { alg: "RSA-OAEP", key: /* JWK public key */ data: "..." }, data: "..." }, data: "..." mac: "..." } Figure 14 The example looks kind of ridiculous, but it's not entirely far- fetched. You could imagine it happening, for example, if a system were distributing content decryption keys with attributes, and a recipient patched one into a JWE to decrypt it with a JWE library. The decryption process can handle the self-similarity naturally with recursion. If the "key" value in the JWE you're processing is a key you know (e.g., a "kid" for a key you have), then you use that key. Otherwise, you process the "key" value as a JWE and use the decrypted content to decrypt the JWE you started with. In other words, you recursively process encrypted keys until you hit a key you know, then work your way back up the stack decrypting as you go. +------+ +------+ +------+ | alg | +-->| alg | +-->| alg | +------+ | +------+ | +------+ | key |--+-->| key |--+-->| key |---+ = known key / ID +------+ | +------+ | +------+ | | data | +-->| data | +-->| data |<--+ decrypts +------+ +------+ +------+ ^ | ^ | | | | | +-----------+ +-----------+ decrypts decrypts Figure 15 Obviously, this sort of recursion could be dangerous, since you could Barnes Expires October 5, 2013 [Page 15] Internet-Draft JOSE Refactor April 2013 end up with many levels of recursion, resulting in memory overflows, etc. However, it doesn't seem likely that many levels will be necessary in practice, so we could specify that implementations should impose limits on the number of levels of recursion that they will allow. To see how the format outlined above compares to JWE, let's look at how the normal JWE fields map to the fields in the example object above. { alg: { name: "A128GCM", <--- "enc" iv: "..." <--- JWE Initialization Vector }, key: { alg: "A128KW", <--- "alg" key: "that", <--- "kid" data: "..." <--- JWE Encrypted Key }, data: "..." <--- JWE Ciphertext mac: "..." <--- JWE Integrity Value } Figure 16 As you can see, there's no new information here, just the same fields rearranged so that there's less need for special handling of IVs or Encrypted Keys - they're just a natural part of the format. One last thing: We've said that the "data" value corresponding to the JWE Encrypted Key contains a JWK representing the CMK. In order for that value not to impose additional overhead for symmetric keys (by wrapping a JSON-encoded key instead of the raw key octets), it will be necessary to have a compact format for JWKs. Such a format should produce a raw octet string for symmetric keys with now attributes, and may produce an optimized JSON format for other types of keys. A few candidate algorithms are discussed in the detailed considerations below. 6.4. Impact on the Compact Format So far, we've been talking about a JSON format, equivalent to the current JSON serialization. How does one take one of these and serialize it to something like the JWE compact encoding? The obvious answer is to keep the other fields the same, and just change the header to accommodate the revised JSON form. So the example we just considered would serialize as a normal JWE, but with the above JSON Barnes Expires October 5, 2013 [Page 16] Internet-Draft JOSE Refactor April 2013 object as the header, and JWE Initialization Vector, JWE Encrypted Key, and JWE Ciphertext removed (since they'll be binary components afterward). { alg: { name: "A128GCM", <--- "enc" }, key: { alg: "A128KW", <--- "alg" key: "that", <--- "kid" }, } Figure 17 To see the impact on header size, let's compare this header with the comparable normal JWE header: {"alg":{"name":"A128GCM"},"key":{"alg":"A128KW","key":"that"}} {"enc": "A128GCM" , "alg":"A128KW","kid":"that" } ........ . ....... . Figure 18 The overhead of this proposed change is thus 17 octets of header, which comes to 20 octets after base64url encoding. So while this does change the header structure - so it will break compatibility with existing implementations - it doesn't change the overall structure of a JWE, and doesn't add a dramatic amount of overhead. In fact, one could argue that this makes the compact form even more flexible. The current compact form has no way to accommodate, for example, the double-wrapped case above. In the revised header structure, the double-wrapped key would still work: The wrapped CMK would be removed to a binary part, and the secondary wrapped key would remain in the header. It would be gigantic, but it would work. 6.5. JWS The same story makes sense for JWS, with a couple of revisions. First, JWS signatures with asymmetric keys don't need wrapped keys, so their "key" values would just be a JWK for the public key. (Other metadata parameters, such as "x5c" could live at the same level as the "alg", and "key" parameters, or in the JWK.) On the other hand, JWS objects that encode MACs could benefit from having wrapped keys in the "key" field. Barnes Expires October 5, 2013 [Page 17] Internet-Draft JOSE Refactor April 2013 The second major difference is that for JWS, it is sometimes desirable to store the input to to cryptographic operation (the signed data) in addition to the output (the signature). In the JWE examples above, the "data" field represents the output of the cryptographic operation. So it would be good to define an additional, optional field for JWS, which would contain an octet string for the protected data. If that field were present, the JWS could be process directly; otherwise, it would represent a detached signature. 6.6. Summary In the above, we've described a proposed change to the JWE and JWS headers to move away from a flat bag of parameters, toward a structure with two required fields and two optional fields: 1. REQUIRED: "alg", containing parameters to describe the algorithm used to process the JWE/JWS object 2. REQUIRED: "key", containing the key used to process the JWE/JWS, either directly, in wrapped form, or as an ID 3. OPTIONAL: "data", containing the ciphertext (JWE) or signed data (JWS) 4. OPTIONAL: "mac", containing the MAC or signature value for the JWE/JWS object This revised structure doesn't lose any features relative to the current format, since other header fields like "zip" can still be added to the header. And it imposes low length overhead, in the low tens of octets. This simpler structure makes it possible to address all of the requirements above with out significant changes to JWE and JWS. In fact, it goes beyond the design goals - instead of having one way to encrypt keys, we have one way to encrypt anything at all. Barnes Expires October 5, 2013 [Page 18] Internet-Draft JOSE Refactor April 2013 7. Revised JSON Format and Translation to Compact In the discussion above, we've outlined a JSON structure that provides some richer structure than the current JWE header. This requires us to modify somewhat the mapping between a JSON-serialized JWE or JWS object and its compact encoding. In this section, we describe the mapping in detail for JWE. With a minor change to the JWS compact serializatoin (adding fields for IV and encrypted key, which can be left empty), the same translation can be used for both JWE and JWS. 7.1. Translation from JSON to Compact Input: JSON object X representing a JWE object in the JSON serialization o Set the Encoded JWE Encrypted Key to X.key.data. If X.key is not present, set it to the empty string. o Set the Encoded JWE Initialization Vector to X.alg.iv. If X.alg is not present, set it to the empty string. o Set the Encoded JWE Ciphertext to X.data o Set the Encoded JWE Integrity Value to X.mac o Delete the "data" field from X.key, the "iv" field from X.alg, and the "data" and "mac" fields from X o Base64url encode the bytes of the UTF-8 representation of the X to create the Encoded JWE Header. o Assemble the final representation: The Compact Serialization of this result is the concatenation of the Encoded JWE Header, the Encoded JWE Encrypted Key, the Encoded JWE Initialization Vector, the Encoded JWE Ciphertext, and the Encoded JWE Integrity Value in that order, with the five strings being separated by four period ('.') characters. Output: Text string representing a JWE object in the compact serialization The following JavaScript functions implement this translation, first for the current JSON serialization and second for the proposed serialization (as described above). Barnes Expires October 5, 2013 [Page 19] Internet-Draft JOSE Refactor April 2013 function json2compact_current(obj) { var JWE_key = obj.recipients[0].encrypted_key; var JWE_iv = obj.initialization_vector; var JWE_data = obj.ciphertext; var JWE_mac = obj.recipients[0].integrity_value; var JWE_header = obj.recipients[0].header; return [ JWE_header, JWE_key, JWE_iv, JWE_data, JWE_mac ].join("."); } function json2compact_proposed(obj) { var JWE_key = obj.key.data; var JWE_iv = obj.alg.iv; var JWE_data = obj; var JWE_mac = obj.mac; delete obj.key.data; delete obj.alg.iv; delete obj.data; delete obj.mac; var JWE_header = base64url(JSON.stringify(obj)); return [ JWE_header, JWE_key, JWE_iv, JWE_data, JWE_mac ].join("."); } Figure 19 7.2. Translation from Compact to JSON Input: Text string representing a JWE object in the compact serialization o Split the string on the period ('.') character to obtain the Encoded JWE Header, the Encoded JWE Ciphertext, and the Encoded JWE Integrity Value. Barnes Expires October 5, 2013 [Page 20] Internet-Draft JOSE Refactor April 2013 o Base64url decode the Encoded JWE Header and parse it into a JSON object X o Set the field X.key.data to the Encoded JWE Encrypted Key o Set the field X.alg.iv to the Encoded JWE Initialization Vector o Set the field X.data to the Encoded JWE Ciphertext o Set the field X.mac to the Encoded JWE Integrity Value Output: JSON object X representing a JWE object in the JSON serialization The following JavaScript functions implement this translation, first for the current JSON serialization and second for the proposed serialization (as described above). function compact2json_current(str) { var parts = str.split("."); var obj = { recipients: [{}], }; obj.recipients[0].header = parts[0]; obj.recipients[0].encrypted_key = parts[1]; obj.recipients[0].integrity_value = parts[4]; obj.initialization_vector = parts[2]; obj.ciphertext = parts[3]; return obj; } function compact2json_proposed(str) { var parts = str.split("."); var obj = JSON.parse(parts[0]); obj.key.data = parts[1]; obj.alg.iv = parts[2]; obj.data = parts[3]; obj.mac = parts[4]; return obj; } Figure 20 Barnes Expires October 5, 2013 [Page 21] Internet-Draft JOSE Refactor April 2013 8. Disposition of Header Fields (Proposal Part 3) The refactoring of the JWE and JWS headers described above requires adding one new field to the header ("key") and redefining one field ("alg"). The new "key" header subsumes the functionality of the "kid" and "jwk" headers; it allows a key to be expressed either directly (as a "jwk" object) or indirectly (as a "kid" string). (We could also just require that either "kid" or "jwk" be present.) With the extension of JWK to wrapped keys, "key" would also support the use of wrapped keys. The re-defined "alg" header would collect all the parameters describing an algorithm into a single object, whose format would be defined in the revised JWA document. For example, an "alg" value for a key agreement algorithm would have a "name" field indicating the key agreement algorithm (as in the current "alg" field), as well as the "epk", "apu", and "apv" fields from the current JWE object. An "alg" value for symmetric encryption with AES-GCM would include a "name" field and an "iv" field with an Initialization Vector. The refactoring has no effect on the many JWE and JWS fields that are secondary to cryptographic processing. For example, the "cty" field remains at the top level of the header. In the following tables, we assign each of the current JWS and JWE header fields one of the following dispositions: o Key: Subsumed by "key" field (or an alternative instantiation of it) o Alg: Subsumed by "alg" field (move to the JWA) o Hdr: Remains as a header parameter JWS Fields Key Alg Hdr "alg" X "jku" X "jwk" X "x5u" X "x5t" X "x5c" X "kid" X "typ" X "cty" X Barnes Expires October 5, 2013 [Page 22] Internet-Draft JOSE Refactor April 2013 Figure 21 JWE Fields Key Alg Hdr "alg" X "enc" X "epk" X "zip" X "jku" X "jwk" X "x5u" X "x5t" X "x5c" X "kid" X "typ" X "cty" X "apu" X "apv" X "epu" X "epv" X Figure 22 Barnes Expires October 5, 2013 [Page 23] Internet-Draft JOSE Refactor April 2013 9. Key Wrapping Procedure (Proposal Part 4) At a high level, there are two steps in the key wrap. First, the JSON dictionary for the original JWK is split into "public" and "private" dictionaries, by dictionary key. The private dictionary is marshaled using a marshaling algorithm (see below), then encrypted in a JWE. The public dictionary becomes the "kat" attribute of the JWE. Key unwrapping proceeds in the opposite direction, retrieving the public and private dictionaries from the "kat" and "wk" attributes (unwrapping the private part), then merging the two into a final JWK. +--> pub -----------------------> "kat" | key --+ | +--> priv -> marshal -> encrypt -> "data" Figure 23 The procedures in this section do not presume a given marshaling algorithm. Instead we discuss several possible options below. Each marshaling procedure has the same interface: o Inputs: * Key type ("kty") * JSON dictionary o Output: * Octet string with the marshaled value * Binary flag indicating whether the marshaled value contains JSON content The corresponding unmarshaling procedures have corresponding inputs and outputs (octet string + binary and JSON dictionary, respectively). 9.1. Wrapping procedure Parameters: Marshaling algorithm Input: JWK object, wrapping algorithm, wrapping key, list of private fields Barnes Expires October 5, 2013 [Page 24] Internet-Draft JOSE Refactor April 2013 o Construct a private object by copying all private fields (listed in the list of private fields) from the input JWK to a new dictionary o Construct a public object by copying all other fields from the input JWK to a new dictionary o Marshal the private object using the marshaling algorithm, and record the value of the returned "wj" flag o Create a JWE encrypting the marshaled private object with the wrapping algorithm and wrapping key o If the "wj" flag is set to true, add it to the JWE as the "wj" attribute o If the public object is non-empty, add it to the JWE as the "kat" attribute o Return the JWE Output: JWE object with optional "kat" and "wj" attributes 9.2. Unwrapping Procedure Parameters: Marshaling algorithm Input: JWE object with optional "kat" and "wj" attributes o Initialize the unwrapped key to an empty JSON dictionary o If the "kat" field is present in the JWE, copy its contents into the unwrapped key o Set the "wj" flag to false if it is not present in the JWE o Decrypt the JWE to obtain the marshalled private dictionary o Unmarshal the private dictionary, using the marshaling algorithm and the "wj" flag o Copy all fields from the private dictionary into the unwrapped key dictionary, overwriting existing fields if necessary o Return the unwrapped key dictionary Output: Unwrapped dictionary Barnes Expires October 5, 2013 [Page 25] Internet-Draft JOSE Refactor April 2013 10. Compact JWK Marshaling (Proposal Part 4) There are several possible compact serializations for JWK, which offer different trade-offs between size and complexity. o JWKS0: UTF-8 o JWKS1: UTF-8, or raw binary for symmetric keys with no attributes o JWKS2: UTF-8, or raw binary for one field per key type o JWKS3: UTF-8, with raw binary for a fixed list of fields per key type o JWKS4: UTF-8, with raw binary for an arbitrary list of fields In this section, we describe details for JWKS2 and JWKS3, since JWKS2 doesn't have significantly more complexity than JWKS1, and JWKS3 is much simpler than JWKS4. For brevity, we list only the encoding procedures. To illustrate the trade-offs of these algorithms, we consider three test cases: o A 256-bit AES key o A 256-bit EC private key o A 2048-bit RSA private key In addition to the two above algorithms, we also consider the simple wrapping procedure in which the entire JWK is serialized to UTF-8 and wrapped as a JWE. 10.1. JWKS2 Parameters: Table with one binary field for each key type Input: JSON dictionary, key type o If the key type is in the table, and the only field in the dictionary is the binary field for the key type * Set the "wj" flag to false * Set the marshaled JSON to the binary contents of the field Barnes Expires October 5, 2013 [Page 26] Internet-Draft JOSE Refactor April 2013 o Else * Set the "wj" flag to true * Set the marshaled JSON to the UTF-8 serialization of the JSON dictionary Output: Marshaled JSON, "wj" flag 10.2. JWKS3 Parameters: Table with a list of binary fields for each key type Input: JSON dictionary, key type o If the key type is not in the table: * Set the "wj" flag to true * Set the marshaled JSON to the UTF-8 serialization of the JSON dictionary o If the key type is in the table and there is only one binary field in the list for this key type, and that field is the only field in the JSON dictionary: * Set the "wj" flag to false * Set the marshalled JSON to the binary contents of the field o Else if the key type is in the table: * Set the "wj" flag to false * Copy all binary fields from the JSON dictionary to a new dictionary, then remove them from the JSON dictionary * If the JSON dictionary is non-empty, compute its UTF-8 serialization and set the "wj" flag to true * Construct a list of binary components containing: + The serialized JSON dictionary, if non-empty + The cached binary field values, in the order of the list of fields Barnes Expires October 5, 2013 [Page 27] Internet-Draft JOSE Refactor April 2013 * Prefix each binary component with a two-octet length field * Set the marshaled JSON to the concatenation of the length- prefixed binary components Output: Marshaled JSON, "wj" flag 10.3. Test Cases Test case 1: A 32-bit symmetric key, with the single private field "k" { "kty": "oct", "k": "cSax0MQz66lGh7hMsgNm8mC+hS+DplWW7o+yUVVIINU=" } Figure 24 Test case 2: A 256-bit EC private key, with the single private field "d" { "kty": "EC", "crv": "P-256", "kid": "1", "x": "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4", "y": "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM", "d": "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE" } Figure 25 Test case 3: A 2048-bit RSA private key, with six private fields "d", "p", "q", "dp", "dq", "qi". { "kty": "RSA", "alg": "RS256", "kid": "2011-04-29", "n": /* 256 octets */, "e": "AQAB", "d": /* 256 octets */, "p": /* 128 octets */, "q": /* 128 octets */, "dp": /* 128 octets */, "dq": /* 128 octets */, "qi": /* 128 octets */, } Figure 26 Barnes Expires October 5, 2013 [Page 28] Internet-Draft JOSE Refactor April 2013 10.4. Performance on Test Cases To characterize the performance of the marshaling algorithms on the test cases, we compute the number of octets used to represent the wrapped key in the JWE (omitting other JWE parameters, which are constant). We consider four cases: 1. Baseline: Length of the UTF-8 serialization of the JWK 2. Simple: Length of the base64url-encoded UTF-8 serialization of the JWK 3. JWKS2: Length of UTF-8 serialization of the public half of the JWK (as would be in the "kat" field), plus the length of the base64url-encoded output of JWKS2 on the private half 4. JWKS3: Same as JWKS2, but using JWKS3 instead The results of this analysis are as follows: Test Case 1 2 3 AES EC RSA ============================ Baseline 64 186 1648 Simple 88 248 2200 JWKS2 44 180 2066 JWKS3 44 180 1634 Figure 27 As expected, the compact JWKS serializations are more compact in general than the simple approach, because they avoid double-base64 encoding. For test case 2, which involves multiple binary fields in the wrapped key, JWKS2 does a little better than the simple approach because it can handle one field ("d"), and JWKS3 does notably better because it can handle all of the binary fields. Barnes Expires October 5, 2013 [Page 29] Internet-Draft JOSE Refactor April 2013 11. Security Considerations The refactoring proposed in this document has several security benefits. First, by using the JWE format for wrapped keys in JWE, JWE can benefit from general AEAD algorithms for key wrapping, for example, AES-GCM as opposed to AES key wrap. These other AEAD algorithms are more widely available than AES key wrap, and offer better security properties in some situations. This benefit is available to the compact serialization as well as the revised JSON format. Second, by using the same format for key encryption and content encryption, code for processing objects in the proposed format will only have to have support one way of decrypting objects. This simplification will reduce the chance for bugs in implementations. Third, the use of consolidated algorithm and key objects allows for simpler validation rules on JOSE objects, again reducing the chance that an improperly-constructed JOSE object will be able to trigger implementation bugs. The current JWE and JWS specifications require header information to be protected under the integrity check provided by the signature, MAC, or AEAD algorithm. This proposal makes the header computation slightly more difficult in the JSON case, since the recipient will have to reconstruct the header by removing some fields from the JSON object. However, no concrete security benefit has been proposed for header integrity, so it may be better to remove header integrity protection in order to allow for cleaner architecture. Barnes Expires October 5, 2013 [Page 30] Internet-Draft JOSE Refactor April 2013 12. IANA Considerations This memo makes no request of IANA. However, changes to the JOSE specs resulting from this proposal might require adjustments to some IANA registrations. Barnes Expires October 5, 2013 [Page 31] Internet-Draft JOSE Refactor April 2013 13. Normative References [I-D.ietf-jose-json-web-algorithms] Jones, M., "JSON Web Algorithms (JWA)", draft-ietf-jose-json-web-algorithms-08 (work in progress), December 2012. [I-D.ietf-jose-json-web-encryption] Jones, M., Rescorla, E., and J. Hildebrand, "JSON Web Encryption (JWE)", draft-ietf-jose-json-web-encryption-08 (work in progress), December 2012. [I-D.ietf-jose-json-web-key] Jones, M., "JSON Web Key (JWK)", draft-ietf-jose-json-web-key-08 (work in progress), December 2012. [I-D.ietf-jose-json-web-signature] Jones, M., Bradley, J., and N. Sakimura, "JSON Web Signature (JWS)", draft-ietf-jose-json-web-signature-08 (work in progress), December 2012. Barnes Expires October 5, 2013 [Page 32] Internet-Draft JOSE Refactor April 2013 Author's Address Richard Barnes BBN Email: rlb@ipv.sx Barnes Expires October 5, 2013 [Page 33]