最近在用阿里云的函数计算服务,需要使用JWK(Json Web Key)来生成JWT(Json Web Token),一时之间竟没有找到一个优雅的、提供JWK生成JWT的库,差点绝望的使用了阿里云给的Java样例。然后惊喜的发现PyJWT其实是支持JWK的,但是文档上并没有写。
此篇做一个系统的梳理,算是对官方文档的补充。
安装
如果你不需要使用类似于RSA的加密算法,那么正常的pipenv install pyjwt
即可,否则应该使用pipenv install pyjwt[crypto]
去安装(这会安装cryptography)。
一般使用
对称加密
常规使用JWT一般会使用对称加密进行签名,一是加解密速度相对快,二是密钥容易配置——随便一个字符串就行了。
以下为PyJWT官方文档例子:
>>> import jwt
>>> encoded_jwt = jwt.encode({'some': 'payload'}, 'SECRET', algorithm='HS256')
>>> encoded_jwt
'eyJhbGciOiJIU...'
>>> jwt.decode(encoded_jwt, 'SECRET', algorithms=['HS256'])
{'some': 'payload'}
其中SECRET
就是需要保管的密钥,algorithm
则指定了签名方法,algorithms
指定验证签名时尝试使用的方法列表。
encode
与decode
的第一个参数就是需要进行签名的数据。
非对称加密
事实上常规使用非对称加密进行签名也很简单,自己生成一对密钥。
下面依旧是官方文档的例子:
>>> import jwt
>>> private_key = b'-----BEGIN PRIVATE KEY-----\nMIGEAgEAMBAGByqGSM49AgEGBS...'
>>> public_key = b'-----BEGIN PUBLIC KEY-----\nMHYwEAYHKoZIzj0CAQYFK4EEAC...'
>>> encoded = jwt.encode({'some': 'payload'}, private_key, algorithm='RS256')
'eyJhbGciOiJIU...'
>>> decoded = jwt.decode(encoded, public_key, algorithms='RS256')
{'some': 'payload'}
除了注意验证签名时用公钥,签名时用私钥。写起来与对称加密签名没什么不同。
JWK使用
JWK是由RFC7517定义的格式。它一般是一个JSON对象。可以在 https://mkjwk.org/ 网站生成一对 JWK 对象。
from jwt.algorithms import RSAAlgorithm
RSAPublicKey = RSAAlgorithm.from_jwk(JWK-Public)
RSAPrivateKey = RSAAlgorithm.from_jwk(JWK-Private)
首先,分别使用JWK的公钥(JWK-Public)与私钥(JWK-Private)生成需要使用的公钥与私钥对象。注意,这里两者必须都是正确的JSON格式的字符串。
接下来的使用就如同常规的非对称加密方法一样了:
token = jwt.encode(data, key=RSAPrivateKey, algorithm='RS256')
data = jwt.decode(token, key=RSAPublicKey, algorithms="RS256")
在这里不得不吐槽一下,关于给PyJWT补充JWK的文档其实早有讨论,但是不知道为什么就不了了之了。快两年了吧,文档里还是没有介绍如何使用JWK。