如果使用python计算,JWT hs512签名与jwt.io略有不同

问题描述

所以我为同一个JWT获得了不同的签名。

标题

{
  "alg": "HS512","typ": "JWT"
}

有效载荷

{
  "sub": "1234567890","name": "John Doe","iat": 1516239022
}

作为签名密钥,我使用了“ abc

jwt.io得到的JWT是:eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.sNgS2IRq0LCvUaIzg9dCBVvmY_9KnrXDEmKTii6U4APbRMeUkU084wf3h5v4baP2WeZOyGunCTEa9wxh25IW6w

如果我使用python这样计算签名:

import hmac
import hashlib
import base64

s= b"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ"

res = base64.b64encode(hmac.new(b"abc",msg=s,digestmod=hashlib.sha512).digest())

print(res)

然后将其打印出来: b'sNgS2IRq0LCvUaIzg9dCBVvmY/9KnrXDEmKTii6U4APbRMeUkU084wf3h5v4baP2WeZOyGunCTEa9wxh25IW6w=='

现在,除了最后两个字符“ ==”和此“ /”之外,它们是相同的。有人可以向我解释为什么会这样吗?仅仅是base64的填充,实际上是否有两个相等的符号并不重要?这就是为什么jwt.io删除它们吗?

编辑: 将编码的python代码更改为jps的提示就可以了:

import hmac
import hashlib
import base64

s= b"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ"

res = base64.b64encode(hmac.new(b"abc",digestmod=hashlib.sha512).digest())
x = res.decode("utf-8")
x = x.replace("+","-")
x = x.replace("/","_")
x = x.replace("=","")
print(x)

解决方法

在Python代码中,您使用了Base64编码,但是JWT standard需要Base64URL编码。区别在于Base64编码中的字符“ +”和“ /”被替换为“-”和“ _”,并且省略了填充。

根据接收方Base64URL解码器的实现,它可能会或可能不会工作。为了安全起见,我建议您遵循标准。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...