Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jws.utils.encode and key order #18

Open
dthakur opened this issue Jun 1, 2015 · 4 comments
Open

jws.utils.encode and key order #18

dthakur opened this issue Jun 1, 2015 · 4 comments

Comments

@dthakur
Copy link

dthakur commented Jun 1, 2015

I use python-jws for JWT.

The jws.utils.encode function uses json.dumps without the sort_keys=True parameter.

In my testing, this can cause JWT header, for example, to be encoded differently randomly.

{ "alg": "HS256", "typ": "JWT" }

vs

{ "typ": "JWT" "alg": "HS256", }

Here is my JWT verification code:

def from_jwt(jwt, algo, key):
    (header, claim, sig) = jwt.split('.')
    header = jws.utils.decode(header)
    assert header['alg'] == algo, header
    claim = jws.utils.decode(claim)
    r = jws.verify(header, claim, sig, key)
    assert r
    return claim

jws.verify signature verification fails when header is ordered differently.

Does it make sense to set sort_keys=True?

@jrconlin
Copy link

Just hit this same error. Unfortunately, the JWS spec doesn't specify key ordering, which means that the header and claims can be in any order. What I believe needs to be done is that the header and claims section need to be preserved from the original JWT and those strings used to check the sig value. Converting back and forth between dicts and strings pretty much rolls the dice on whether or not things get shuffled around. It's best to avoid that source of entropy and just use the original data when doing sig value checks, then pass back the decoded claim.

@jesebo
Copy link

jesebo commented Mar 14, 2016

We've got same trouble, what we choose to do is to always sort JSON before sign it. That's the only way to be sure that the signature doesn't depends on the sort.

@jrconlin
Copy link

@jesebo Hrm, sadly, that's not really solving the problem. Key signing needs both sides to agree on what's being signed. Key sorting is ok ONLY if you control both key generation and key validation. The spec does say the signature is generated from the header as a string + "." + claims as a string, so that's the one item that is common to both sides. You really need to have the original strings and not the converted JSON objects.

@meredian
Copy link

meredian commented Sep 1, 2017

Hey, not sure if it's still actual, but real point of using JWS is that you need to use header and payload you received without any decoding, just right after .split('.') - you already have desired base64, concatenate it and check HMAC. That will provide 100% compatibility, which does not depend on any object key ordering.

Currently you decode it into object - and of course python shuffles keys inside a hash map. Maybe you have to change lib API here a bit, it seems much more convenient methods like jws.verify(jwt, key)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants