DinoChiesa / jwt-webtool

Source code repo for the online JWT webtool.
Apache License 2.0
134 stars 45 forks source link

encrypted token idempotence #24

Closed missinglink closed 1 year ago

missinglink commented 1 year ago

Heya,

When using 'Encrypted' mode, the token changes every time when using the same inputs.

I assumed that this is due to the "iat" or "exp" timestamps changing, but they appear to be static and removing them doesn't make the tokens consistent.

Question: is this a 'feature' of web tokens or maybe just an implementation detail of the webtool? 🤔

Screenshot 2023-03-17 at 11 48 46 Screenshot 2023-03-17 at 11 48 57
DinoChiesa commented 1 year ago

Hi there, thanks for the question. It's just the way JWE works.

In more detail.... "encrypted JWT" is really just a form of JWE, which is described in the IETF specification RFC 7516. All JWE except for those that use the "dir" algorithm, use a hybrid encryption. It's as if there are two locked boxes - the first box holds the content (yknow, the payload and protected header of your JWT) , and is locked with a content-encryption key (CEK). The second box holds the CEK, and is locked with the key-encryption key (KEK). To unlock the content, you need to first use the KEK to unlock box 2 and thereby decrypt the CEK, and then you must use the decrypted CEK to unlock box 1 and decrypt the JWT content.

The randomness comes in because the CEK itself is randomly generated for each new encrypted JWT. (According to the JWE spec there is no way for the generator to select a specific CEK. You could build your own tool to do this, but it would violate the spec.) Using the CEK to encrypt the payload results in the ciphertext (the encrypted form) of the content. Obviously changing the CEK will result in a different ciphertext. There is additional randomness injected into the process via the initialization vector (IV), which is used in the AES encryption. The IV is also randomly selected for each run. This ciphertext and the IV both get serialized into the JWT. So you see, the serialized form of the encrypted JWT will always vary.

You didn't ask, but you may be wondering, if the CEK is randomly generated, how can the receiver of the encrypted JWT decrypt the JWT? The receiver of the JWT cannot possibly have that randomly generated key unless the generator of the JWT gives it to him! And yes, that's just what happens. The generator of the JWT embeds the encrypted CEK into the serialized JWE (encrypted JWT).

Decrypting is the process of

DinoChiesa commented 1 year ago

BTW, if you use "Signed" tokens (much more popular), you will see no randomness when using RS algorithms. But the PS algorithms introduce randomness in what gets signed, so if you choose PS256, repeated signings of the same content will result in different JWT.

DinoChiesa commented 1 year ago

not a bug

missinglink commented 1 year ago

Thanks for your thoughtful answer 🙏