即使签名的最后一个字符发生更改,也可以进行 JWT 令牌解码 [英] JWT token decoding even when the last character of the signature is changed

查看:30
本文介绍了即使签名的最后一个字符发生更改,也可以进行 JWT 令牌解码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是在一个 rails 应用程序上尝试 JWT 令牌,使用这个 jwt 库:该范围内最后一个字符的变化只会导致最后两位的变化(浅灰色),但不会改变原始数据,因为变化的位超出了原始数据的最后一位.

如果你真的很在意最后的2位,可以考虑把签名算法改成HS384.

然后你就有了一个 384 位(= 48 字节)的散列,它用 64 个 Base64 字符表示.384可以被8整除,也可以被6整除,所以最后没有不重要的位,最后一个字符的任何变化都会导致验证失败.

HS512 也会有同样的问题".与 HS256 一样,最后甚至是 4 个无关紧要的位,但更长的哈希值(512 位 vs. 384 位 vs. 256 位)被认为更安全.

结论:一切都很好,这里没有错.签名的验证基于其二进制值,不受编码特性的影响.如果你担心的话,你可以改变算法,但我认为这并不是真正必要的,算法的选择不应该以此为基础.

I was just trying out JWT tokens on a rails app, using this jwt library: https://github.com/jwt/ruby-jwt

JWT.encode({sss: "333"}, 'SECRET_KEY')

returns below token:

eyJhbGciOiJIUzI1NiJ9.eyJzc3MiOiIzMzMifQ.CwX_1FztYHVpyx_G27u938SceilsVc5AB5Akwqlo2HA

Then I decoded using the above token

JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJzc3MiOiIzMzMifQ.CwX_1FztYHVpyx_G27u938SceilsVc5AB5Akwqlo2HA", 'SECRET_KEY')

returns below response correctly:

[{"sss"=>"333"}, {"alg"=>"HS256"}]

But if I try to change the last letter of the token to B instead of current A it is still returning the same response which is weird.

JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJzc3MiOiIzMzMifQ.CwX_1FztYHVpyx_G27u938SceilsVc5AB5Akwqlo2HB", 'SECRET_KEY')

Getting this response even though the token I provided is wrong:

[{"sss"=>"333"}, {"alg"=>"HS256"}]

Actually I am getting the same response for all characters up to 'D'

If I use F and others above then its showing error as expected:

JWT.decode("eyJhbGciOiJIUzI1NiJ9.eyJzc3MiOiIzMzMifQ.CwX_1FztYHVpyx_G27u938SceilsVc5AB5Akwqlo2HF", 'SECRET_KEY')

JWT::VerificationError (Signature verification raised) from (irb):34

What could be the reason for this? Is it the expected behavior or am I doing something wrong here?

解决方案

The reason is the base64url encoding. The three parts of a JWT are all base64url encoded. Base64 encoding transforms the input data to a 6-Bit representation, mapped to a set of 64 ASCII characters. If you have 3 bytes source data (24 bits), the base64 encoded result is 4 characters long, each character representing a 6 bit value, so 4 * 6 bits = 24 bits. If the number of bits that need to be encoded can't be divided by 6 without remainder, there'll be one character more with 2 or 4 insignificant bits.

In your case, the encoded signature has 43 characters, which means 43 * 6 = 258 bits. So you could theoretically encode 258 bits, but the signature is only 256 bits (32 bytes) long, which means there are 2 insignificant bits on the end.

A look on the base64 encoding table shows that 'A' to 'D' represent the 6 bit values 0 (000000) to 4 (000011), so the first four bits, which are still significant, are all identical, and only the last two, insignificant bits are changing. But the character 'E' stands for 5 (000100) and would change the last bit of the 256 bit value.

The following table illustrates that. It shows the last 4 base64 characters of the signature, including the possible changes of the last character (A-D) and the bit and byte number of the original data: The change of the last character in that range only causes a change of the last two bits (light grey) but does not change the original data, because the changed bits are beyond the last bit of the original data.

If you're really concerned about the 2 bits on the end, you can consider to change the signature algorithm to HS384.

Then you have a 384 bit (= 48 byte) hash, which is represented in 64 Base64 characters. 384 can be divided by 8 and by 6 without remainder, so there are no insignificant bits on the end and any change on the last character will lead to a failed verification.

HS512 would have the same "problem" as HS256, and then even 4 insignificant bits on the end, but nonetheless a longer hash (512 bits vs. 384 bits vs. 256 bits) is considered more secure.

Conclusion: it's all fine, nothing wrong here. The verification of a signature is based on its binary value, which is not affected by the peculiarities of the encoding. You can change the algorithm, if you're worried, but I think it's not really necessary and the choice of an algorithm should not be based on that.

这篇关于即使签名的最后一个字符发生更改,也可以进行 JWT 令牌解码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆