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

Multiple valid signatures for when signing with HS256 #269

Closed
note opened this issue Oct 13, 2017 · 1 comment
Closed

Multiple valid signatures for when signing with HS256 #269

note opened this issue Oct 13, 2017 · 1 comment

Comments

@note
Copy link

note commented Oct 13, 2017

According to @lhazlewood suggestions from #123 I am using 64 bytes key for HS256 and I am still having similar problem as it was described here: #123.

I created repo with minimal reproducer: https://github.com/note/jjwt-report. You can either clone the whole repo and run it with sbt or just copy paste https://github.com/note/jjwt-report/blob/master/src/main/java/example/Hello.java to your project.

What is interesting is that finding a collisions like this is very simple - I came across the problem just because I was testing automatically my method. In my test I was generating some JWT token, changing last character in the token and expecting validation of such token to fail. Still in around 10% of cases it was actually passing.

Was also trying with 128 bytes key and it still was the case.

@lhazlewood
Copy link
Contributor

Hi @note!

While it looks suspicious, it's not actually a security collision. You can't just manually change a single remaining character of Base64 encoded string and expect it to always produce different byte arrays. Base64 doesn't always work that way - sometimes barely different Base64 strings may decode to the same byte array - it all depends on which bits are represented and Base64's padding scheme. You might want to check out the Base64 RFC to see how this can be the case - section 4 will be helpful (too much to explain in a GH issue comment! :) )

This isn't a security issue though - the only thing that matters is if you can take a signature output (a byte array) and encode it to text (e.g. via Base64) and decode it back to the original byte array. If you can and the original and resulting byte arrays are identical, then the original signature remains in tact, and security assertions work as expected.

To illustrate this is a Base64 issue and not a security/signature issue, try the following test. I used the test strings in your code example, but took only the signature parts of the JWSs (the last substrings after the final period characters). Notice how only the last character of the two strings differ:

    @Test
    void testBase64() {

        String s1 = 'yzEQE8d38bIdGymKonBU805JqXxJ35EwB1ZgEKYpKoY'
        String s2 = 'yzEQE8d38bIdGymKonBU805JqXxJ35EwB1ZgEKYpKoa'

        byte[] a1 = Base64.getDecoder().decode(s1)
        byte[] a2 = Base64.getDecoder().decode(s2)

        assert Arrays.equals(a1, a2)
    }

This test passes successfully because with Base64, it is possible to represent the same byte array with two different Base64 strings. Note that the underlying signature byte array is still the same. The only thing that matters with signatures is can the same signature byte array (not base64 string) be created using the same verification key and signature algorithm. If it can, the signature can be verified and trusted.

In summary, don't pay too much attention to what the Base64 string looks like - it's not too important from a security perspective. What matters really is the byte array that the Base64 string represents. If you're ever in doubt, create a test like above and if the byte arrays are different and signature validation still passes, only then might there be a real security problem.

Finally, I'm closing out this ticket as, unless I'm mistaken, it doesn't represent actionable work for the JJWT team. If you feel otherwise, please do comment or re-open and we'll be happy to revisit. Cheers!

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

2 participants