Closed jaimeperez closed 9 years ago
Hi @jaimeperez, thanks for the contribution.
Looking at the sections in the RFC that you've called out, these do all seem to be valid issues and resolved with your patch. We'll have to take a closer look at this and measure potential impact as they're backwards incompatible changes. Unfortunately, things are a little slow right now as most are off for the holidays, so we likely won't be able to get to an in depth review until early in the new year.
Hi Demian,
Thanks a lot! No worries, I understand that the dates are not the best ones, and I'll be myself out of business for a while, probably.
There's another issue I missed in the pull request, for which I don't have a patch yet, unfortunately. After taking a closer look at the specs, I noticed the encrypt()
and decrypt()
methods deal basically with compact serialization, as in the case of JSON serialization the number of elements in the JWT can vary up to 8 (instead of the fixed amount of 5 assumed in the code). This is ok, but the attempt to make the API not tied directly to the compact serialization unfortunately introduces a bug with the authentication tag. According to the JWE draft:
3.1. JWE Compact Serialization Overview
In the JWE Compact Serialization, no JWE Shared Unprotected Header or JWE Per-Recipient Unprotected Header are used. In this case, the JOSE Header and the JWE Protected Header are the same.
and:
5.1.14. Let the Additional Authenticated Data encryption parameter be ASCII(Encoded Protected Header). However if a JWE AAD value is present (which can only be the case when using the JWE JSON Serialization), instead let the Additional Authenticated Data encryption parameter be ASCII(Encoded Protected Header || '.' || BASE64URL(JWE AAD)).
The problem then is that the serialize_compact()
method simply joins all the elements in the tuple with a dot in between, and since the encrypt()
method is serialization-agnostic, nothing is calculating the authentication tag using the JOSE header as input, which is mandatory if the final output is using compact serialization.
Unfortunately this needs some major changes to the library, including the API, so I think I should not provide a patch for that as you should be the ones deciding how to proceed...
I've taken a look at this and the change itself looks good. The problem, however, is that it's backwards incompatible. Given the library is already in use and tokens have been issued, this change will result in effectively invalidating all tokens, which may be a Bad Thing depending on application level implementation details around token handling. Optimally, the library would handle this change internally and would mark the old method as deprecated. This could perhaps be achieved by using a private claim replicated as a header parameter.
I would like to see tests added to the suite that ensure that the changes you've made are not undone (i.e. cipher()
is called using the last half of the key and hash()
is called with the first half). This can be achieved using mock and a custom random number generator or mocking get_random_bytes
.
As far as API changes to allow for JSON serialization, this library was developed following the JOSE spec, but was limited to our immediate needs. As such, JSON serialization was not in the picture and would likely be a very low priority issue for us to tackle. If you have suggestions, feel free to log an issue. Otherwise, a patch contribution (in another PR as to not conflate this one) would likely be the most efficient way of having it addressed and released.
This has been merged as part of the 0.2.2 release (and I've added you to CONTRIB). Thanks for the contribution!
Thanks Demian! Hope it didn't create too much trouble with backwards compatibility in the end...
Not at all and conformance is always worth it. Thanks again for the submission.
The issues, according to the JWA spec are: