0

I just ran into something strange IMO.

I created a RSA Key using nodejs cryptoutils to use with my JWT auth server.

What I observer using jwt.io was the following: The last letter of the signature can be changed, and the jwt is still considered valid?

In my case, the last part of the signed token is "fWh9F4hBm0IRHo6wv99fWmYTZG-TA". I can change the -TA to -TB, -TC, -TD, etc. until -TP, where -TQ is considered invalid.

The token is using RS256.

Why is this? I personally find this very unexpected, if I can change a signature and the jwt is still considered valid this kind of defeats the purpose, doesnt it?

Did I find a rare hash collision in the sha256 algorithm? Do I need to be worried about integrity and security?

2
  • Addition: I cannot share the jwt itself, mainly because theres private information stored in it. I found this while testing, though I dont know if I will encounter another instance of this problem. On jwt.io I of course used the public key to verify the message crypthographically. Oct 21, 2023 at 21:26
  • 3

1 Answer 1

3

As Dave Thompson's comment points out, you've just misunderstood base64. The signature on the JWT is encoded as a URL-safe variant of base64, and has a fixed length. Base64 (all variants) encode every three bytes as four characters (each character encoding six bits, meaning 64 different characters, thus "base64").

Since no commonly used RSA signature length is a multiple of three bytes long, the last "block" of base64 will be incomplete; the first character will entirely matter, but the second or third (depending on the actual length) will only partially matter. More specifically, with a 256-byte signatures only the most significant two of the six bits represented by the second character will matter; with a 512-byte signature, the most significant four of the six bits represented by the third character (and all of the second character) will matter. The remaining bits will be "don't care" values that are basically padding, and are ignored when decoding the fixed-length base64. As such, you can change the last character in this fixed-length base64 string so long as it doesn't change the most significant bits.

If you look at a base64 table, you can see that 'A' through 'P' represent the first 15 values, 0b000000-0b001111, and all of them have the same two most significant bits 0b00. Combine with the previous character 'T' which encodes 0b010011 to get 0b01001100, which is a full byte 0x4C. 'Q' and above change at least one of those two most significant bits, which when combined with the previous value 'T' would give a different full byte, such as 0b01001101.

So no, not a collision, not a flaw in RSA, just a completely safe quirk of base64 encoding.

1
  • Ahhh, thank you very much! I didnt think about the base64 encoding that takes place. It seems weird that multiple representations are allowed for a certain string, but it makes sense now! Oct 22, 2023 at 10:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .