Brute forcing JSON Web Tokens in C
github.com
github.com
The example provided has a private key length of 32 bits which is far too short to be secure. Based on the JSON Web Algorithms (RFC 7518) the key length must be at least the length of the output hash (256 bits) to be used in accordance with the standard.
> A key of the same size as the hash output (for instance, 256 bits for "HS256") or larger MUST be used with this algorithm.
One library checks for key lengths [1] and throws exceptions, another one doesn't [2] -- in fact it uses a quickstart example that should obviously fail.
[1] https://github.com/latchset/jwcrypto/ [2] https://github.com/mpdavis/python-jose
> 8Jbr+vX5JpFZOW7P1RLs7/ArYy1Az7hrimMfcI3qqBI=
This "small" Key is already 256-Bit.
if decoded to an Array in Java: > java.util.Base64.getDecoder.decode("8Jbr+vX5JpFZOW7P1RLs7/ArYy1Az7hrimMfcI3qqBI=").length * 8
> res7: Int = 256
if you try to decode a jwt with it, it takes forever. (Actually I guess you also need to raise the length of the progam but it's akward since you probably don't know the correct length.Actually I use HMAC-SHA512 with key sizes between 1024-Bit to 2048-Bit.
Edit: Typo
This is utterly pointless security theater. You don't just get more security by rubbing bigger key sizes on it. The key goes through the hash function (twice, in HMAC; once via ipad, once via opad); the HMAC standard defines keys larger than the hash function's block size to go through the hash function first. With good reason, HMAC recommends key sizes to be equal to the hash function's output length; that's 16 bytes (128 bits) for MD5, and 20 bytes (160 bits) for SHA-1.
Relatedly: GCM supports large nonces, but I don't understand why you would ever use anything other than a 96 bit one. (Larger nonces go through GHASH.)
That's why TLS only uses the public key to exchange a symmetric key then switches over to AES or whatever.
Frustratingly, JWT defines a tons of stuff, where few are required but some are "Recommended" and some are "Recommended+". I'm not sure what "Recommended+" means, but apparently it means "has known cryptographic flaws", because RSA with PKCSv15 padding is "Recommended+".
The Go library I use allows to define custom algorithms, so I just set alg to ED2 and use it.
It's within the app only so it doesn't hurt much.
Also agree, it's rather frustrating that JWT is so well defined but something as simple as using Ed25519 is not part of the standard yet.
The JWT Lib does most of the work and I just stuff in the Ed keys on both ends, don't need to do anything beyond that.
Point of order: Does ES256 enforce RFC 6979? If not, how do you know you aren't repeating k-values?
The only sane crypto in the JWT specification is, sadly, HMAC.
Thanks
Using [1] as a reference for a specialised system in a price range affordable to hobbyists, assuming HMAC-SHA256, a 48bit secret would take about three hours to brute force (48bit is about 10 letters all lowercase), while a 64bit secret would already hold 25 years (assuming no upgrades etc).
With sufficient volume you can probably build such a system for about $5000-$7000. Let's assume $5000, because that number is rounder. If you spend $1,000,000 on your setup (so certainly professional level now), your 64bit secret only holds 44 days.
If the NSA would spend 10% of a single year's budget on GPUs, the resulting machine could crack a 64 bit secret in one hour, but a 84bit secret would take 100 years to crack (84 bits is about 17 lowercase letters, or 14 mixed-case, or 10.5 bytes if you use the entire range of the byte).
Of course that ignores some scaling effects (if you spend $1billion you get much more bang for the buck by designing custom ASICs), but it should give a sense of what's secure against whom. By using proper 256bit secrets you should be secure against everyone until the end-of-life of your application.
1: https://gist.github.com/epixoip/a83d38f412b4737e99bbef804a27...
The whole thing is editorialized to make it sound like the problem is with JWTs. It's not, this is just plain old improper use of perfectly good crypto.
Brute-forcing 32 bit HMAC keys isn't exactly newsworthy.
Also the title "Brute forcing JWT in C" could not be clearer. This is not "0day found in JWT", or just "breaking JWT". This is brute force & nothing more
This is actually editorialized to make it sound the way it really is
> However contrary to my original statement it turned out secret in use was actually only 30 characters long.
I'm guessing it's 32 characters long? (256 bits) That matches to the spec and is a good key - as referenced in other threads anything longer is mostly a waste as the key input gets hashed down to a fixed size.