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]