使用Python加密JWT负载?(JWE)

13
根据RFC 7516,应该可以加密称为JWE的有效载荷/声明。
是否有任何支持此功能的Python库?
我已经检查了PyJWT、python-jose和jwcrypto,但它们都只有使用HS256(JWS)进行签名的示例。
如果涉及加密事项,对于我来说很明显,但也需要特别小心。
3个回答

15

Jose和jwcrypto库都可以处理JWE。

对于jose

claims = {
'iss': 'http://www.example.com',
'sub': 42,
}
pubKey = {'k':\
           '-----BEGIN PUBLIC KEY-----\n\
-----END PUBLIC KEY-----'
    }
# decrypt on the other end using the private key
privKey = {'k': 
    '-----BEGIN RSA PRIVATE KEY-----\n'+\
'-----END RSA PRIVATE KEY-----'
}

encJwt = jose.encrypt(claims, pubKey)
serJwt = jose.serialize_compact(encJwt)
decJwt = jose.decrypt(jose.deserialize_compact(serJwt), privKey)

对于 jwcrypto


# algorithm to use
eprot = {'alg': "RSA-OAEP", 'enc': "A128CBC-HS256"}
stringPayload = u'attack at dawn'
E = jwe.JWE(stringPayload, json_encode(eprot))
E.add_recipient(pubKey)
encrypted_token = E.serialize(compact=True)
E = jwe.JWE()
E.deserialize(encrypted_token, key=privKey)
decrypted_payload = E.payload

1
你/有人能否请添加一个详细的示例,演示如何将现有的RSA密钥导入到jwcrypto中?我一直在尝试,但是一直出错。 - kilokahn
5
jose库不支持Python 3,详情请查看https://github.com/Demonware/jose/pull/15。令人困惑的是,另一个名为python-jose的库不支持JWE。 - jnnnnn
2
@kilokahn 三年后,但由于我有同样的问题; 您可以使用key = jwcrypto.jwk.JWK.from_pem(pemfile.read()),如此处所述:https://jwcrypto.readthedocs.io/en/stable/jwk.html#examples - Jacob Davis-Hansson

0

我可以添加一个新的库到上面建议的库中,名为jwskate,作为“JSON Web Signing、Keys、Algorithms、Tokens和Encryption”的缩写。免责声明:我是该库的作者。我编写它是因为我对以前的库的API不够Pythonic感到不满意。

这里有一个使用示例来编码/解码JWE,在这种特定情况下使用ECDH-ES+A256KWA128CBC-HS256,但显然您可以使用任何支持的密钥管理和加密算法:

from jwskate import JweCompact, Jwk

plaintext = b"this is an example plaintext"

# I'll use this specific Elliptic Curve private key:
key = Jwk(
    {'kid': '8-nLgBsa-vXI_geoGt061_ZiVZ8BB-hYBDSoOQj9QgI',
     'alg': 'ECDH-ES+A256KW',
     'crv': 'P-256',
     'd': '39QMopTVL1u267FOx4ayvsueDU317vHaq_z-PU_NioA',
     'kty': 'EC',
     'x': 'f_VRZlIk1Qd2eNGFVas9sNXx9wd43L8VymknAyP5Ntk',
     'y': 'NmsfCs5VVOk6FEE31aaN9jB8rlfz1MWolBC3af_8DGs'}
)


# alternatively, you can generate one like this:
random_key = Jwk.generate_for_alg("ECDH-ES+A256KW").with_kid_thumbprint()

# sign your JWE
jwe = JweCompact.encrypt(plaintext, jwk=key.public_jwk(), enc="A128CBC-HS256")
print(jwe)
# it will look like: 
# eyJlcGsiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiItVnNfYkdSNTdUUVY4MHNnUENwcWZhVjNmWXR4dWdTWmJRM1FLeTJEVDdNIiwieSI6IjBtc0pZSUFfMC1OY2lfM0plOWZLSml3RU1ZdGRBaE9kZDZhdkp5THd0dzQifSwiYWxnIjoiRUNESC1FUytBMjU2S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2Iiwia2lkIjoiOC1uTGdCc2EtdlhJX2dlb0d0MDYxX1ppVlo4QkItaFlCRFNvT1FqOVFnSSJ9.nnOEhmdonA19LRvyKSrL7f8aEb2vVwE7EU-zO91fyTUls4otMVppYg.h8h7Mxz4irvckPnknsnM0g.sRQJJq-RmiF7GeqvL8EpWTstS-daLbfgGnOPybWeOj8.z3heCfTiI0cjw8GaV0qcHw


# as recipient, you can decrypt your JWE like this:
jwe = JweCompact("""eyJlcGsiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiJkSllwMHNTZUVhMnhiMkc4M2Jnam
1VNnp4OEFxTkZRVmlJclJXUnlJYURzIiwieSI6InJXcEZ0OENESGNkQXFoMVR2eG9BZTFCT3FfZ2I3RzJya0hVd0hhNldfV0kif
SwiYWxnIjoiRUNESC1FUytBMjU2S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2Iiwia2lkIjoiOC1uTGdCc2EtdlhJX2dlb0d0MDYx
X1ppVlo4QkItaFlCRFNvT1FqOVFnSSJ9.Nt89wpmYDZmbmjQCEZnZOygTOP5x2s7trvzLFehw1I_lMzTU-qlrcg.SQgJPG_WNUn
F13XnCJMAtw.wWwu_VUG7LPbsnWFTv-rAyiG84RW4tszR2fQ-AQaLBI.Onf3K4MSKhXaUrS8NpMDIA""")
assert jwe.decrypt(key) == plaintext

-1

1
你在这里混淆了你的模块;这是一个JWK密钥创建、保存/加载的演示。使用JWE创建和解密JWT加密令牌时,不需要使用JWK - Martijn Pieters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接