As I wrote earlier (and as pointed out by James Manger as the format was being
designed), the array serialization is subject to collisions between keys of
different types unless the field names are also included. [e, kty, n] in
theory could match [kty, x, y] for a different key type, and yet not be the
same key. So the representation needs to include the field names or equivalent
metadata – not just the field values.
As for being brittle and dealing with escaping, at least the printf for a
particular key type can take advantage of knowledge about the representation of
that key type. For instance, for RSA, EC, and OCT keys, no escaping will ever
be needed since the values are all ASCII strings, so the code can be simple.
I agree that any hash input computation with the right properties would do the
job. Those properties are primarily the ability to unambiguously represent a
JWK key and necessary key metadata as an octet sequence. Yes, we could choose
anything. But the good news about the choice in the current draft, which was
James Manger’s idea, is that we already have a data structure that is known to
be able to unambiguously represent JWK keys, both existing ones and future
ones, as an octet sequence. That data structure is a JWK itself! That’s why I
know that the other inventors and I were drawn to James’ suggestion and why I
personally think that it gives us the right balance of simplicity now and
flexibility in the future.
Best wishes,
-- Mike
From: Richard Barnes [mailto:[email protected]]
Sent: Friday, January 23, 2015 12:19 PM
To: Mike Jones
Cc: John Bradley; Matt Miller; Jim Schaad; [email protected]
Subject: Re: [jose] Working Group last call on draft-ietf-jose-jwk-thumbprint
On Fri, Jan 23, 2015 at 2:02 PM, Mike Jones
<[email protected]<mailto:[email protected]>> wrote:
In practice, you wouldn’t ever implement the sort. You’d have printf
statements for the key types you support (and we’ve only defined three of them
to date – only two if you only use public keys). So in pseudo-code, the hash
input generator I would write would look something like this:
if kty == “RSA” then
printf(‘{“e”:”’, e, ‘”,”kty”:”’, kty, ‘”,”n”:”’, n, ‘”}’)
else if kty == “EC” then
printf(‘{“crv”:”’, crv, ‘”,”kty”:”’, kty, ‘”,”x”:”’, x, ‘”,”y”:”’, y, ‘”}’)
else
FAIL
No sorting code involved!
You may notice that I put something similar in my first message on this thread
:)
My point is that this style of code is brittle and deals poorly with things
like escaping.
I can see your point w.r.t. separators. That seems to indicate that Matt's
suggestion of a JSON array is the right answer:
tp_input = JSON.stringify([jwk.e, jwk.kty, jwk.n]).replace(/\s/g, "")
That way the order is preserved, but the JSON serializer handles all the string
serialization.
--Richard
From: Richard Barnes [mailto:[email protected]<mailto:[email protected]>]
Sent: Friday, January 23, 2015 10:54 AM
To: Mike Jones
Cc: John Bradley; Matt Miller; Jim Schaad; [email protected]<mailto:[email protected]>
Subject: Re: [jose] Working Group last call on draft-ietf-jose-jwk-thumbprint
On Fri, Jan 23, 2015 at 1:39 PM, Mike Jones
<[email protected]<mailto:[email protected]>> wrote:
I was about to write a similar message to John's. James Manger also pointed
out the need to have different hash inputs for different kinds of keys, so as
to avoid the possibility of collisions. The simple suggestion earlier in the
thread of using an array of values for the hash input doesn't have this
property. If there were two kinds of keys with the same number of values in
the input, for instance three values such as [A, B, C], then without also
having the member tags "kty", etc. in the hash input, collisions are possible.
That's why James suggested that the natural and safe hash input for a JWK is a
sorted JWK itself. We went with that.
The problem is that there's no good way to create a "sorted JWK". (BTW, you
also mean "whitespace-free".) Thankfully, the whitespace problem is easy to
deal with here. Since the included attributes do not allow any internal
whitespace, you can just delete all whitespace. But sorting is a big deal.
Like I said, it basically requires you to hand-serialize the JSON. At which
point, you might as well use ASN.1 :)
ISTM that (1) including "kty" and (2) using a delimiter that's not in the
allowed character set would together address the collision issues. So we could
get away with something like "kty-value|n-value|e-value". Miller's proposal to
use a JSON array would also work for me, although it would require removing
white space in case the serializer added any. Anything that doesn't require
custom serialization code :)
I agree that encodings using ASN.1 sort of defeat the point. Others could
define how to do that and add them to the appropriate registries if they want,
but using JSON solutions is the point of the working group and this draft.
As for symmetric keys, I don't think we actually have a use case for them at
present. I'd be fine with the working group deciding to drop them or to add
security considerations on the necessity for there to be sufficient key entropy
if a thumbprint is to be exposed to a party not holding the key. Or the
security considerations could say that the thumbprint MUST only be exposed to
parties already in possession of the key. While I understand going the salt
route, I'm only comfortable with us doing that now if someone has a real use
case for it. Since I think the chairs want to have this draft complete
quickly, I'd rather drop symmetric keys than figure out the salt mechanisms on
the fly. But others are free to propose otherwise, obviously.
At a meta-point responding to Jim's message, I think this morning's discussions
exactly demonstrate the value of the draft being in the working group. There's
a lot of good discussion going on about the choices made, tradeoffs, and
alternatives that wouldn't necessarily happen if this weren't a working group
draft.
Thanks all,
-- Mike
-----Original Message-----
From: jose [mailto:[email protected]<mailto:[email protected]>] On
Behalf Of John Bradley
Sent: Friday, January 23, 2015 10:18 AM
To: Matt Miller
Cc: Richard Barnes; Jim Schaad; [email protected]<mailto:[email protected]>
Subject: Re: [jose] Working Group last call on draft-ietf-jose-jwk-thumbprint
Mat in the first version that we did, we didn't have delimiters.
I think it was James Manger that pointed out that without delimiters there were
some potential attacks.
Depending on the order of the parameters the issues are different.
I think the specific issue was concatenating e directly to n.
That lead us to create the current doc.
John B.
> On Jan 23, 2015, at 2:28 PM, ⌘ Matt Miller
> <[email protected]<mailto:[email protected]>> wrote:
>
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA512
>
> On 1/23/15 7:54 AM, Richard Barnes wrote:
>> I would summarize my reaction to this document as "I can live with
>> it, but it makes me really sad that we didn't do the stupid simple
>> obvious thing."
>>
>> The computation of the hash input is technically workable, but
>> unnecessarily complex. Rather than building a simple string based on
>> the components (say, ), it basically requires the implementor to make
>> a custom JSON serializer to ensure that the fields are serialized in
>> the right order.
>>
>> Using Javascript as an example, instead of just doing a simple string
>> construction:
>>
>> tp_input = [jwk.e, jwk.kty, jwk.n].join("|")
>>
>> ... instead, I construct and fill in a template:
>>
>> tp_input = '{"e":"JWK_E","kty":"JWK_KTY","n":"JWK_N"}'
>> .replace("JWK_E", jwk.e) .replace("JWK_KTY", jwk.kty)
>> .replace("JWK_N", jwk.n)
>>
>> Requiring a lot of manual coding like this seems to invite interop
>> issues.
>>
>> The remainder of the text looks fine to me, though.
>>
>
> I agree with Richard that the hash input looks needlessly complex.
> Picking a delimiter isn't necessary if it instead takes advantage of
> existing JSON implementations by simply serializing an array of the
> required values, still ordered lexicographically according to their
> associated member names.
>
> In some real code, that's:
>
> * JavaScript: tp_input = JSON.stringify([jwk.e, jwk.kty, jwk.n]);
> * Ruby: tp_input = JSON.generate [ jwk["e"], jwk["kty"], jwk["n"] ]
> * Python: tp_input = json.dumps([jwk['e'], jwk['kty'], jwk['n'])
>
> This could very well get rid of most of section 5. It might also get
> rid of some of text in Section 7 regarding weird member names if we're
> careful.
>
>
> - --
> - - m&m
>
> Matt Miller < [email protected]<mailto:[email protected]> >
> Cisco Systems, Inc.
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG/MacGPG2 v2.0.22 (Darwin)
> Comment: GPGTools - https://gpgtools.org
>
> iQEcBAEBCgAGBQJUwoTDAAoJEDWi+S0W7cO16gYH+wbQ+RhWRoPOXDEXa0ieyqzD
> GxS+6Jj77QQjknkm9bfw+6mTzP0+CFshy4OJP/qNQScRLSTvDS20sQUPPb4/NAbq
> CV/xV9Td/OrT/73iwR17PHoovLkwHOhbgxX93U4XA6JXVXSlslM0hUKBsDfmqM4j
> jBI0yRvowAweDhmQ5rqdHhH4WBQQamR2XT8y61H9ERHAvlru3v5C9n3Qwa9Y8/ju
> 1SjzQc1t1UIE3vOmhkxZWlkDfnWI6grOoGDt/JIy7JIK/0WJ/g8mjbqUTh61xU3V
> a6SAjw0fjvhfJQ6FJfmmteOYVCOeUO0fCNTCjnkDBMtz9Zho+H7WUfXBvE5QrrY=
> =lZoe
> -----END PGP SIGNATURE-----
>
> _______________________________________________
> jose mailing list
> [email protected]<mailto:[email protected]>
> https://www.ietf.org/mailman/listinfo/jose
_______________________________________________
jose mailing list
[email protected]
https://www.ietf.org/mailman/listinfo/jose