即使签名的最后一个字符被更改,JWT令牌解码

时间:2019-10-21 18:16:02

标签: ruby-on-rails jwt jwt-auth

我只是使用以下jwt库在Rails应用程序上尝试JWT令牌: https://github.com/jwt/ruby-jwt

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

返回以下令牌:

  

eyJhbGciOiJIUzI1NiJ9.eyJzc3MiOiIzMzMifQ.CwX_1FztYHVpyx_G27u938SceilsVc5AB5Akwqlo2HA

然后我使用上述令牌进行了解码

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

正确返回以下响应:

  

[{“ sss” =>“ 333”},{“ alg” =>“ HS256”}]

但是,如果我尝试将令牌的最后一个字母更改为 B 而不是当前的 A ,它仍会返回相同的响应,很奇怪。

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

即使我提供的令牌是错误的,也得到此响应:

  

[{“ sss” =>“ 333”},{“ alg” =>“ HS256”}]

实际上,对于所有字符,直到'D',我都得到相同的响应

如果我使用F和上面的其他代码,则会显示预期的错误:

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

JWT :: VerificationError(引发签名验证)           来自(irb):34

这可能是什么原因?是预期的行为还是我在这里做错了什么?

1 个答案:

答案 0 :(得分:1)

原因是base64url编码。 JWT的三个部分都是base64url编码的。 Base64 encoding将输入数据转换为6位表示形式,并映射到一组64个ASCII字符。如果您有3个字节的源数据,则base64编码结果的长度为4个字符,每个字符代表6位值,因此4 * 6位= 24位。

在您的情况下,编码的签名具有43个字符,这意味着43 * 6 = 258位。 因此,从理论上讲,您可以编码258位,但是签名只有256位(32字节)长,这意味着最后有2个无关紧要的位。

通过查看base64 encoding table可以看出,“ A”至“ D”代表6位值0(000000)至4(000011),因此前四个仍然有效的位都相同,只有最后两个无关紧要的位在变化。但是字符“ E”代表5(000100),它将更改256位值的最后一位。

结论:一切都很好,这里没有错,可以按预期工作。