JOSE Working Group | R. Barnes |
Internet-Draft | BBN |
Intended status: Informational | April 11, 2013 |
Expires: October 13, 2013 |
Proposed Refactoring of JOSE to Align Encryption and Key Wrapping
draft-barnes-jose-key-wrapping-00
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.
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 13, 2013.
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 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.
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:
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 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.
Details of these proposals are described below.
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”.
To create an an object encrypted with AES-GCM and AES-KW, we need to specify the following parameters:
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
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
PROPOSED-JSON: { "alg": { "name": "A128GCM", "iv": "hRskpf3RwFQmEKQ5" }, "key": { "alg": "A128KW", "key": "preSharedKey", "data": "Pe15h6BYJ7SrEq0ev8m9ce4vq4phLFJK" }, "data": "jZpHMF7GhBNYSD5QIJkBXWu6POh_KTN5", "mac": "b2ersuWujfIaoghd5kOpWw" }
Figure 6
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.
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).
In the course of the key wrapping discussions in JOSE, a few new requirements have arisen:
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.
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:
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:
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.
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.
{ 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 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.
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 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.
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.
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.
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:
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.
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.
Input: JSON object X representing a JWE object in the JSON serialization
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).
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
Input: Text string representing a JWE object in the compact serialization
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
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:
JWS Fields Key Alg Hdr "alg" X "jku" X "jwk" X "x5u" X "x5t" X "x5c" X "kid" X "typ" X "cty" X
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
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:
The corresponding unmarshaling procedures have corresponding inputs and outputs (octet string + binary and JSON dictionary, respectively).
Parameters: Marshaling algorithm
Input: JWK object, wrapping algorithm, wrapping key, list of private fields
Output: JWE object with optional “kat” and “wj” attributes
Parameters: Marshaling algorithm
Input: JWE object with optional “kat” and “wj” attributes
Output: Unwrapped dictionary
There are several possible compact serializations for JWK, which offer different trade-offs between size and complexity.
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:
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.
Parameters: Table with one binary field for each key type
Input: JSON dictionary, key type
Output: Marshaled JSON, “wj” flag
Parameters: Table with a list of binary fields for each key type
Input: JSON dictionary, key type
Output: Marshaled JSON, “wj” flag
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
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:
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.
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.
This memo makes no request of IANA. However, changes to the JOSE specs resulting from this proposal might require adjustments to some IANA registrations.
[I-D.ietf-jose-json-web-encryption] | Jones, M., Rescorla, E. and J. Hildebrand, "JSON Web Encryption (JWE)", Internet-Draft draft-ietf-jose-json-web-encryption-08, December 2012. |
[I-D.ietf-jose-json-web-signature] | Jones, M., Bradley, J. and N. Sakimura, "JSON Web Signature (JWS)", Internet-Draft draft-ietf-jose-json-web-signature-08, December 2012. |
[I-D.ietf-jose-json-web-algorithms] | Jones, M., "JSON Web Algorithms (JWA)", Internet-Draft draft-ietf-jose-json-web-algorithms-08, December 2012. |
[I-D.ietf-jose-json-web-key] | Jones, M., "JSON Web Key (JWK)", Internet-Draft draft-ietf-jose-json-web-key-08, December 2012. |