Subject: [jose] Distinguishing signed, encrypted, and unprotected tokens

From: "Manger, James H" <[email-masked]>
Date: Thu, 17 May 2012 14:57:06 +1000

draft-jones-json-web-token-10#section-5 suggests looking at the "alg" value in the header to distinguish whether you have a JWE, JWS, or plain JWT.

Wouldn't it be better to distinguish these cases by the number of dots:
* 3 dots (4 segments) => JWE
* 2 dots (3 segments) => JWS
Then we could use 1 segment for a plaintext JWT
* 0 dots (1 segment) => Plaintext JWT (base64url-encoded JWT Claim Set)

Benefits:

1. JWT spec doesn't need to confusingly specify the "JWT header" as though it is a separate thing from a JWS or JWE header. Rules are specified for the JWT header (unique names, no duplicates, all understood or reject, JWT-specific "typ" definition) but surely these should just be the JWS or JWE header rules as appropriate.

2. No need for the rather pointless "eyJhbGciOiJub25lIn0." prefix (for {"alg":"none"}) on plaintext JWTs

3. Top-level code doesn't need to know all sig & enc algs; can leave that to signing & encryption libraries

4. Don't need to split, decode, parse header before passing JWT onto JWS or JWE processing (which may well split, decode, and parse the same stuff all over again) [eg https://github.com/NimbusDS/Nimbus-JWT/blob/master/src/com/nimbusds/jwt/JWT.java#LC137]

5. Less risk that "none" is implemented as a proper JWS signature verification algorithm and accidentally allows unsigned code to pass security gates.

--
James Manger

---

From: John Bradley <[email-masked]>
Date: Fri, 18 May 2012 07:45:20 -0400

I would be against using the number of segments to determine the type.  That has changes over time as we added integrity to encryption.

I would not want to assume that some new algorithm might not need another segment.   

Their might also be attacks that we haven't considerd that might be possible by altering the number of segments.

I understand that it is an attractive shortcut, but I think the downside is risky.

John B.

On 2012-05-17, at 12:57 AM, Manger, James H wrote:

> _______________________________________________
> jose mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/jose

---

From: "Manger, James H" <[email-masked]>
Date: Sun, 20 May 2012 17:48:03 +1000

First, for unprotected plaintext we still need the header to hold metadata about the payload, like its type ("typ" header field). So I now suggest:
* 3 dots (4 segments) => JWE
* 2 dots (3 segments) => JWS
* 1 dot  (2 segments) => unprotected payload (<header>.<payload>)

If you don't like using the dot-count to distinguish these cases, how about adding an explicit indication? For instance, a JWE is "E".<header>.<wrappedkey>.<ciphertext>.<MAC>; a JWS is "S".<header>.<payload>.<signature>, and an unprotected payload is "P".<header>.<payload>.

Distinguishing using "alg" value is a poor choice. Consider receiving a JWT in 2 year. After splitting on dots, base64 decoding, interpreting as UTF-8, JSON parsing, and extracting "alg", you get the value "XY512". Uhmmm.. obviously a new algorithm has been defined since the initial publication of "JWA" -- which is not too surprising, eg SHA-3 is expected soon. So you look at the IANA web page for registered "alg" values. "XY512" is in the list. Its usage is "alg" (not "enc" or "int"). That still means it could be a key-wrapping alg or an asymmetric signature alg so you still cannot distinguish what you have. You follow the IANA reference to a spec for "XY512" and, at last, you know if you have a JWE or JWS.

For many apps if you don't know the "alg" it doesn't really matter if it is a JWE or JWS since you cannot decrypt or verify it so the app will just reject it. But for other apps (or other layers of an app or other steps in a processing chain) it would be nice to distinguish signed/encrypted/plain at bit more simply.

--
James Manger

-----Original Message-----
From: John Bradley [mailto:[email-masked]] 
Sent: Friday, 18 May 2012 9:45 PM
To: Manger, James H
Cc: [email-masked]
Subject: Re: [jose] Distinguishing signed, encrypted, and unprotected tokens

John B.

---

From: Mike Jones <[email-masked]>
Date: Sun, 20 May 2012 16:14:35 +0000

Per http://tools.ietf.org/html/draft-jones-json-web-token-08#section-5, there already is an explicit indication in the header.
   A second
   method is determining whether an "enc" (encryption method) member
   exists.  If the "enc" member exists, the JWT is a JWE; otherwise, the
   JWT is a JWS.  Both methods will yield the same result.

Use that method if you prefer, as it is algorithm independent.  Adding a second explicit indication would be redundant.

BTW, JWT is not a JOSE spec - it has been accepted as an OAuth spec.  If you want to continue this thread, I suggest removing [email-masked] and adding [email-masked].

				Best wishes,
				-- Mike

-----Original Message-----
From: [email-masked] [mailto:[email-masked]] On Behalf Of Manger, James H
Sent: Sunday, May 20, 2012 12:48 AM
To: John Bradley
Cc: [email-masked]
Subject: Re: [jose] Distinguishing signed, encrypted, and unprotected tokens

--
James Manger

-----Original Message-----
From: John Bradley [mailto:[email-masked]] 
Sent: Friday, 18 May 2012 9:45 PM
To: Manger, James H
Cc: [email-masked]
Subject: Re: [jose] Distinguishing signed, encrypted, and unprotected tokens

John B.

---

From: "Jim Schaad" <[email-masked]>
Date: Sun, 20 May 2012 12:12:36 -0700

<no hat>

What happens if you are distinguishing based on the number of dots and then
you move to a new encoding format that is not dot separated?

Jim

> First, for unprotected plaintext we still need the header to hold metadata
> about the payload, like its type ("typ" header field). So I now suggest:
> If you don't like using the dot-count to distinguish these cases, how
about
> adding an explicit indication? For instance, a JWE is
> "E".<header>.<wrappedkey>.<ciphertext>.<MAC>; a JWS is
> "S".<header>.<payload>.<signature>, and an unprotected payload is
> "P".<header>.<payload>.
> 
> Distinguishing using "alg" value is a poor choice. Consider receiving a
JWT in 2
> year. After splitting on dots, base64 decoding, interpreting as UTF-8,
JSON
> parsing, and extracting "alg", you get the value "XY512". Uhmmm..
obviously
> a new algorithm has been defined since the initial publication of "JWA" --
> which is not too surprising, eg SHA-3 is expected soon. So you look at the
> IANA web page for registered "alg" values. "XY512" is in the list. Its
usage is
> "alg" (not "enc" or "int"). That still means it could be a key-wrapping
alg or an
> asymmetric signature alg so you still cannot distinguish what you have.
You
> follow the IANA reference to a spec for "XY512" and, at last, you know if
you
> have a JWE or JWS.
> 
> For many apps if you don't know the "alg" it doesn't really matter if it
is a JWE
> or JWS since you cannot decrypt or verify it so the app will just reject
it. But
> for other apps (or other layers of an app or other steps in a processing
chain)
> it would be nice to distinguish signed/encrypted/plain at bit more simply.
> 
> --
> James Manger
> 
> I would be against using the number of segments to determine the type.
> That has changes over time as we added integrity to encryption.
> 
> Their might also be attacks that we haven't considerd that might be
possible
> by altering the number of segments.
> 
> > draft-jones-json-web-token-10#section-5 suggests looking at the "alg"
> value in the header to distinguish whether you have a JWE, JWS, or plain
> JWT.
> >
> > 1. JWT spec doesn't need to confusingly specify the "JWT header" as
> though it is a separate thing from a JWS or JWE header. Rules are
specified
> for the JWT header (unique names, no duplicates, all understood or reject,
> JWT-specific "typ" definition) but surely these should just be the JWS or
JWE
> header rules as appropriate.
> >
> > 3. Top-level code doesn't need to know all sig & enc algs; can leave
that to
> signing & encryption libraries
> >
> > 4. Don't need to split, decode, parse header before passing JWT onto JWS
> or JWE processing (which may well split, decode, and parse the same stuff
all
> over again) [eg https://github.com/NimbusDS/Nimbus-
> JWT/blob/master/src/com/nimbusds/jwt/JWT.java#LC137]
> >
> > 5. Less risk that "none" is implemented as a proper JWS signature
> verification algorithm and accidentally allows unsigned code to pass
security
> gates.

---

From: "Richard L. Barnes" <[email-masked]>
Date: Sun, 20 May 2012 15:23:47 -0400

+1

Distinguishing based on number of dots seems really fragile.

---

From: Mike Jones <[email-masked]>
Date: Sun, 20 May 2012 22:43:56 +0000

Indeed, we already have a JSON format proposed in response working group input with no dots.  See these specs:
	http://tools.ietf.org/html/draft-jones-json-web-signature-json-serialization-01
	http://tools.ietf.org/html/draft-jones-json-web-encryption-json-serialization-01

				-- Mike

-----Original Message-----
From: [email-masked] [mailto:[email-masked]] On Behalf Of Richard L. Barnes
Sent: Sunday, May 20, 2012 12:24 PM
To: Jim Schaad
Cc: 'John Bradley'; 'Manger, James H'; [email-masked]
Subject: Re: [jose] Distinguishing signed, encrypted, and unprotected tokens

+1

On May 20, 2012, at 3:12 PM, Jim Schaad wrote:

> <no hat>
> 
> What happens if you are distinguishing based on the number of dots and 
> then you move to a new encoding format that is not dot separated?
> 
> Jim
> 
> 
>> First, for unprotected plaintext we still need the header to hold 
>> metadata about the payload, like its type ("typ" header field). So I now suggest:
>> a new algorithm has been defined since the initial publication of 
>> "JWA" -- which is not too surprising, eg SHA-3 is expected soon. So 
>> you look at the IANA web page for registered "alg" values. "XY512" is 
>> in the list. Its
> usage is
>> I understand that it is an attractive shortcut, but I think the 
>> downside
> is risky.
>> 
>> John B.
>> 
>> value in the header to distinguish whether you have a JWE, JWS, or 
>> plain JWT.
>>> 
>> for the JWT header (unique names, no duplicates, all understood or 
>> reject, JWT-specific "typ" definition) but surely these should just 
>> be the JWS or
> JWE
>>> 2. No need for the rather pointless "eyJhbGciOiJub25lIn0." prefix 
>>> (for
>> {"alg":"none"}) on plaintext JWTs
>>>

---

From: "Manger, James H" <[email-masked]>
Date: Mon, 21 May 2012 10:43:15 +1000

>> then you move to a new encoding format that is not dot separated?

Hang on Jim, of course interop fails if you change syntax.

Mike said:
> Indeed, we already have a JSON format proposed in response working
> group input with no dots.  See these specs:

Neither of these 2 specs talk about having a field that can be a JWE-JS, or a JWS-JS, or an (undefined) Plain-JS and having to distinguish them -- which is the *-JS equivalent to the dot-separated-B64 issue we are discussing.

The *-JS alternatives are illustrative.
JWS-JS:  {"headers":[<h1>,<h2>...], "payload":<p>, "signatures":[<s1>,<s2>...]}
JWE-JS:  {"headers":[<h1>,<h2>...], "encrypted_keys":[<k1>,<k2>...],
          "ciphertext":<c>, "integrity_values":[<s1>,<s2>...]}

The *-JS syntaxes have an *array of headers*. Are you supposed to use the "alg" value from the first header, the last header, check all headers? Or look for an "enc" header field in the first, last, or every header? I hope they are not inconsistent.

A better alternative would be to leave the headers alone and look for an "encrypted_keys" field. Another alternative could be changing the "headers" label to "jws" or "jwe" or "header" (when unprotected).

If you want to send an unprotected payload in *-JS syntax, can you omit the "integrity_values" field, or send an empty array, or send an array with 1 value that is an empty string? The first option sounds best, but the last option is the equivalent of the "alg":"none"-fake-signature method in JWT.

I really think we need -- in the JOSE specs -- to defined the packaging of signed, encrypted, or unprotected content in a way that is trivial to distinguish these 3 modes. If we have another packaging syntax (eg *-JS) it also needs to support these 3 modes and make them trivial to distinguish.

This has nothing to do with a JSON object carrying a bunch of claims (for which the OAuth group might be more appropriate).

--
James Manger