如果使用 python 计算,JWT hs512 签名与 jwt.io 略有不同
JWT hs512 signature slightly different from jwt.io if calculated with python
所以我得到了同一个 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 删除它们的原因吗?
编辑:
根据 jps 的提示更改 python 代码就可以了:
import hmac
import hashlib
import base64
s= b"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ"
res = base64.b64encode(hmac.new(b"abc", msg=s, digestmod=hashlib.sha512).digest())
x = res.decode("utf-8")
x = x.replace("+","-")
x = x.replace("/","_")
x = x.replace("=", "")
print(x)
在您的 Python 代码中您使用了 Base64 编码,但是 JWT standard requires Base64URL 编码。不同之处在于将Base64编码中的字符“+”和“/”替换为“-”和“_”,并省略了填充。
它可能有效也可能无效,具体取决于接收方 Base64URL 解码器的实现。为了安全起见,我建议按照标准来做。
所以我得到了同一个 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 删除它们的原因吗?
编辑: 根据 jps 的提示更改 python 代码就可以了:
import hmac
import hashlib
import base64
s= b"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ"
res = base64.b64encode(hmac.new(b"abc", msg=s, digestmod=hashlib.sha512).digest())
x = res.decode("utf-8")
x = x.replace("+","-")
x = x.replace("/","_")
x = x.replace("=", "")
print(x)
在您的 Python 代码中您使用了 Base64 编码,但是 JWT standard requires Base64URL 编码。不同之处在于将Base64编码中的字符“+”和“/”替换为“-”和“_”,并省略了填充。
它可能有效也可能无效,具体取决于接收方 Base64URL 解码器的实现。为了安全起见,我建议按照标准来做。