如何使用 pyJWT 验证此 JWT 上的签名?
Posted
技术标签:
【中文标题】如何使用 pyJWT 验证此 JWT 上的签名?【英文标题】:How to use pyJWT to verify signature on this JWT? 【发布时间】:2019-05-20 11:09:21 【问题描述】:我收到了一个 JWT 令牌。 我有兴趣打开它并验证它的内容。
我想使用pyJWT 库来做到这一点。请看下面的小程序。
我已经成功地对我的 JWT 进行了 base64 解码。我已经从网上检索到匹配的 JWK。但是我不知道接下来要做什么来验证签名。
当我尝试执行下面的 jwt.decode()
时,我收到错误 jwt.exceptions.DecodeError: Not enough segments
。
# !/usr/bin/env python
import jwt
import base64
import json
import requests
my_jwt = "eyJqa3UiOiJodHRwczovL2U5N2I4YTlkNjcyZTRjZTQ4NDVlYzY5NDdjZDY2ZW" \
"Y2LXNiLmJhYXMubmludGVuZG8uY29tLzEuMC4wL2NlcnRpZmljYXRlcyIsImtp" \
"ZCI6ImZlOWRiYmZmLTQ3MGItNDZjOC04YmFmLTFiNzY5OGRlZTViZSIsImFsZy" \
"I6IlJTMjU2In0.eyJpc3MiOiJodHRwczovL2U5N2I4YTlkNjcyZTRjZTQ4NDVl" \
"YzY5NDdjZDY2ZWY2LXNiLmJhYXMubmludGVuZG8uY29tIiwiZXhwIjoxNTQ1MT" \
"g1NDk2LCJ0eXAiOiJpZF90b2tlbiIsImF1ZCI6IjhkOTc1NTllNjNlY2NkNTYi" \
"LCJiczpkaWQiOiI2NjJhZTQwOWYwNTQyYTBjIiwic3ViIjoiOTNkYmYwNDdiYT" \
"I3NzQ5NSIsImp0aSI6IjY1NDg4ZjJmLTI1NzAtNDBkYy04ODQ3LTMzODNlZWIx" \
"MGJiYiIsIm5pbnRlbmRvIjp7ImFpIjoiMDEwMGY4MDAwMDQ5MjAwMCIsImF2Ij" \
"oiMDAwMCIsImVkaSI6ImJjNTdiYmM3MTZlMDA1MGFmOWRhN2NkYTIzMWRjZDgy" \
"IiwiYXQiOjE1NDUxNzQ2OTZ9LCJpYXQiOjE1NDUxNzQ2OTZ9.ZMUIt3wYrbfhX" \
"nnDh4WraGlKrZy0YuL5prluY70sU_-0W5XvWIB-xmTrLz7LJWHEGwTskcWf81_" \
"HBq_mSb75rMfTAEBwBmOJ4ITmhdnXksz8w7EDOWuPPSEft5XLMNOMD16ztEOYe" \
"5ddU_iqNEbT56L7fcAJEXv0FWy6H_OutxOglYpDaNkcj6CWJ7dpA0JbqerR9dE" \
"szaLwyn1ZBDPVD0YeAIm5bEr61imeedzMb0amxlTl4R87mqK6epsFUnRy6p6Kl" \
"r27_DlTLQ-gej09W7NeNzONCj4thHgCr9szAiaN28krfTc2fobz3qFCoC_eQgh" \
"iIIZBe_-Lksng3Eg6tw"
decoded_token = [
base64.b64decode(i + '=' * (-len(i) % 4))
for i in my_jwt.split('.')
]
header = json.loads(decoded_token[0])
claims = json.loads(decoded_token[1])
signature = decoded_token[2]
print 'Header = \n\n\n'.format(header)
print 'Claims = \n\n\n'.format(claims)
print 'Signature = \n\n\n'.format(signature)
key_found = False
for curr_jwk in requests.get(header['jku']).json()['keys']:
if curr_jwk['kid'] == header['kid']:
key_found = True
break
assert key_found
print 'curr_jwk = \n\n'.format(curr_jwk)
# I am not sure if the following line is correct
jwt.decode(signature, curr_jwk['x5c'][0], algorithms=['RS256'])
以下是完整的输出。请告诉我如何验证签名。我没有在网上找到任何对我有用的 Python 示例。
Header =
u'jku': u'https://e97b8a9d672e4ce4845ec6947cd66ef6-sb.baas.nintendo.com/1.0.0/certificates', u'alg': u'RS256', u'kid': u'fe9dbbff-470b-46c8-8baf-1b7698dee5be'
Claims =
u'aud': u'8d97559e63eccd56', u'iss': u'https://e97b8a9d672e4ce4845ec6947cd66ef6-sb.baas.nintendo.com', u'jti': u'65488f2f-2570-40dc-8847-3383eeb10bbb', u'exp': 1545185496, u'nintendo': u'ai': u'0100f80000492000', u'edi': u'bc57bbc716e0050af9da7cda231dcd82', u'at': 1545174696, u'av': u'0000', u'iat': 1545174696, u'bs:did': u'662ae409f0542a0c', u'typ': u'id_token', u'sub': u'93dbf047ba277495'
Signature =
�dr>�X�ݤn��G�D�6��)�d�T=x&�+�X�y�s1��S��|�j���lI�˪z*Z��9S�OV���B��a������v�J�M͟���P�m>z/� �d�����H:�)
curr_jwk =
u'use': u'sig',
u'e': u'AQAB',
u'kty': u'RSA',
u'alg': u'RS256',
u'n': u'twZRFUFinbzSF9aCaLqSdDSfS4Lfz6bSB-4ymwqkgJPLMLtX0meEVOSsx2qP_OQFkb6_RAZk3GK2CSM46V8A-bZqYn1jHyRyQeQmAfrzvXxAiXBdSq4Eso1C_roFQDjR3p-RnLWDLdMPUHkmAQSPEpVAUbcCvUD8zZwQ-go8GAzG0iQNNvZxma1JQoDsHPgY5LiBVBlqY43tp_jeW_sb3SxZ30zzIckKtQfYDfph_vns-q1_raNRPgS0TQw4E470n27UgLE30yoVn_DlYwmtZneCOWIByVPrMBMIkrv_Gh9VW3GszbqZz2u3K9Aj7rtnCtmUrI9dQbeTnruWOn_Fjw',
u'x5c': [u'MIIC/zCCAeegAwIBAgIHBX0u6g3YCzANBgkqhkiG9w0BAQUFADBAMT4wPAYDVQQDEzVlOTdiOGE5ZDY3MmU0Y2U0ODQ1ZWM2OTQ3Y2Q2NmVmNi1zYi5iYWFzLm5pbnRlbmRvLmNvbTAeFw0xNzEyMTYwMDAwMDBaFw0xOTEyMTcwMDAwMDBaMEAxPjA8BgNVBAMTNWU5N2I4YTlkNjcyZTRjZTQ4NDVlYzY5NDdjZDY2ZWY2LXNiLmJhYXMubmludGVuZG8uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtwZRFUFinbzSF9aCaLqSdDSfS4Lfz6bSB+4ymwqkgJPLMLtX0meEVOSsx2qP/OQFkb6/RAZk3GK2CSM46V8A+bZqYn1jHyRyQeQmAfrzvXxAiXBdSq4Eso1C/roFQDjR3p+RnLWDLdMPUHkmAQSPEpVAUbcCvUD8zZwQ+go8GAzG0iQNNvZxma1JQoDsHPgY5LiBVBlqY43tp/jeW/sb3SxZ30zzIckKtQfYDfph/vns+q1/raNRPgS0TQw4E470n27UgLE30yoVn/DlYwmtZneCOWIByVPrMBMIkrv/Gh9VW3GszbqZz2u3K9Aj7rtnCtmUrI9dQbeTnruWOn/FjwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBsXUY5j/m4pAB0R3zDEHHBXZUCkdN53zCr5M7/Kn4ak0vKb9Hk1gNJqdS+dNyW1C7aNGFPmmcMhOos3tv0KsjNoftA4A27uIA7U6QYtJSUVbtVJgYCu8XUa2VDongGNxB72UvFiD++qY3Xe95b0kzsoSOqGaguicAeRSG/HARDaNJT5I9MhCYdCmjU/z83dGI0t8v33Zua92YVmzL6E06lxQ7KrVa9MlKgVJEiAnju3GESVFmrhEoVt516EVxvTVmFlrsvN6rh+c/jC3mBDkE7E23ukg6FpM8oCVRU/5o8/lnKVcRhYPnBgHwg/wTL/Is5rteMtLihV/mvgt3InWkc'],
u'usage': u'developer',
u'kid': u'fe9dbbff-470b-46c8-8baf-1b7698dee5be'
Traceback (most recent call last):
File "./saqib_test.py", line 46, in <module>
jwt.decode(signature, curr_jwk['x5c'][0], algorithms=['RS256'])
File "/Users/saqib.ali/saqib-env-987/lib/python2.7/site-packages/jwt/api_jwt.py", line 84, in decode
payload, _, _, _ = self._load(jwt)
File "/Users/saqib.ali/saqib-env-987/lib/python2.7/site-packages/jwt/api_jws.py", line 183, in _load
raise DecodeError('Not enough segments')
jwt.exceptions.DecodeError: Not enough segments
【问题讨论】:
【参考方案1】:你让你的解码过程变得非常困难。
这是解码 JWT 令牌的单行代码:
JWT_SECRET = 'secretpassphrase'
JWT_ALGORITHM = 'HS256'
decoded = json.loads(json.dumps(jwt.decode(token, JWT_SECRET, JWT_ALGORITHM)))
此行的作用是使用用于生成令牌的秘密密码解码令牌,然后“json.dumps”将其加载为字节格式,接下来的“json.loads”允许您使用下面的代码对其进行解析。
在此之后,您可以像这样获得令牌的各个属性:
user_id = decoded['user_id']
expiry_time = decoded['exp']
注意:这应该放在 Try: Catch 语句中,因为如果令牌过期或不使用相同的签名,那么 python 将抛出错误。 无效签名或令牌已过期。
def verify_token(token):
try:
decoded = json.loads(json.dumps(jwt.decode(token, JWT_SECRET, JWT_ALGORITHM)))
return
'name': decoded['user_id'],
'exp': decoded['exp']
except:
print("Generic Error")
希望对你有帮助
【讨论】:
这对我很有帮助,非常感谢。我已经在我的 Lambda 函数中查看了这个 jwt 令牌问题一段时间,但无法真正弄清楚如何去做。 @D3vRandom 你的评论对我来说来得正是时候。【参考方案2】:首先,您应该直接解码 base64 编码的消息。那是一个完整的 jwt 消息,而不仅仅是签名。应该是:
jwt.decode(my_jwt, algorithms='RS256')
其次,它不起作用,因为默认情况下不支持RS256
。可以参考这个问题:https://github.com/jpadilla/pyjwt/issues/181
最后,我不认为你可以在没有公钥的情况下解码这个RS256
编码的消息。你有那把钥匙吗?
【讨论】:
我不确定我是否有公钥。我想我会的。但我不是 100% 确定。curr_jwk['x5c'][0]
是公钥吗?
好吧,老实说我不知道。你可以试一试。如果你成功了,那就是。
我的理解是您可以解码 RS256 令牌(它只是 base64 编码 - 使用参数:verify=False) - 但如果没有公钥,您将无法验证它。
以上是关于如何使用 pyJWT 验证此 JWT 上的签名?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用带有公共 PEM 证书的 python PyJWT 验证 JWT?
Python JWT 库 PyJWT 使用 HS256 签名时遇到问题 - 使用 SHA-256 哈希算法的 HMAC