I am testing an API that uses JWT for authentication. This JWT has a HS256 signature to prevent modification. I figured that if I determine the secret key used in this signature, I can create my own JWTs. How can I crack the secret key of a JWT signature?

I tried using jumbo john which does seem to have JWT support, but I can't get it to work:

$ ./john jwt.txt 
Using default input encoding: UTF-8
No password hashes loaded (see FAQ)

There is no JWT option in john --list=format.

  • Could you upload your jwt.txt to a GitHub Gist or Pastebin paste :) ? – Minh-Triet Pham Tran Feb 10 at 4:46

I ended up writing a little Python script that uses PyJWT to parse the JWT and check the signature.

There is also jwtbrute. I haven't tested it, but it seems to be a bit more efficient than my script because it does much work such as base64-decoding outside of the loop.

If you want to crack JWTs using John the Ripper, you need to convert their format to something like this:


As you can see the first two parts are the same, but the signature is now hex instead of base64. Also, it is separated from the data with a # instead of .. I wrote a little script to do the conversion.

You also need a recent version of john. The version that comes with Kali didn't work for me, but the version on GitHub did.

$ ./john ~/dev/crackjwt/jwt.john
Using default input encoding: UTF-8
Loaded 1 password hash (HMAC-SHA256 [password is key, SHA256 256/256 AVX2 8x])
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
secret           (?)
1g 0:00:00:00 DONE 2/3 (2016-08-24 15:58) 6.666g/s 218453p/s 218453c/s 218453C/s 123456..skyline!
Use the "--show" option to display all of the cracked passwords reliably
Session completed
|improve this answer|||||
  • In your script you catch the exception ExpiredSignatureError. What significance does this have to guessing the secret? Even if it was an expired signature, couldn't we continue to attack the JWT for the secret? @sjoerd – Copy and Paste Sep 14 '16 at 17:46
  • 1
    Also if you could place comments on that script, it would help a lot. I was attempting to understand the flow, and reasoning for exceptions/etc. – Copy and Paste Sep 14 '16 at 18:04
  • Did you update your script to make it more efficient? By the way, it is possible to crack the key of an RS256-signed JWT? (I noticed you only mentioned HS256 on your GitHub repository) – baptx Jun 7 '19 at 12:31

Based on what you posted it appears that you are attacking the whole JWT, which I don't think JTR is smart enough to decode the base64, and separate out the signature.

How JWT work:

The have a header:

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

They have claims

{ "sub": "1234567890", "name": "John Doe", "admin": true }

You encode them in base64Url and combine them with a secret to get something like:


Testing against this is no good since brute force is trying to attack this entire string, which is not the secret.

Better bet:

Download a JWT library, use their parser function, and rainbow table and hope they people using the API are stupid enough to use a dictionary word for security.

You could brute force it I suppose, but if it's strong, you'll be sitting for an awfully long time.

|improve this answer|||||

john has been supporting JWT natively as of this commit https://github.com/magnumripper/JohnTheRipper/commit/85aa7b3e3f8204360683ddc5ec9734bf793d07cf (2015).

So you can just put a JWT hash in the pw file without any changes nowadays, without having to do any transformations.

$ cat jwt.john 
$ john jwt.john
# Wait a few hours, then:
$ john --show jwt.john
|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.