JWT encrypting payload in python? (JWE)


According to RFC 7516 it should be possible to encrypt the payload/claim, called JWE.

Are there any python libraries out there that support that?

I’ve checked PyJWT, python-jose and jwcrypto but they all just have examples for signing with HS256 (JWS).

Sorry if this is totally obvious, but when it comes to things involving crypto I’m extra cautious.

Asked By: Johnny



Both Jose and jwcrypto libraries can do JWE.

For 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'+

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

For jwcrypto:

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


from jwcrypto import jwk
_k = jwk.JWK.generate(kty='RSA', size=2048)
_text = _k.export()

import json
# loading the key back
_import_key_dict = json.loads(_text)
key = jwk.JWK(**json.loads(_import_key_dict))

Answered By: Meng Wee Tan

I can add a new library to the above suggested libraries, named jwskate, as initials of "JSON Web Signing, Keys, Algorithms, Tokens, and Encryption". Disclaimer: I am the author of that lib. I wrote it because I was not satisfied with the APIs from the previous libs which are not Pythonic enough for my tastes.

Here is an usage example to encode/decode a JWE, in this particular case using ECDH-ES+A256KW and A128CBC-HS256, but obviously you can use any supported key management and encryption algorithm:

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")
# it will look like: 
# eyJlcGsiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiItVnNfYkdSNTdUUVY4MHNnUENwcWZhVjNmWXR4dWdTWmJRM1FLeTJEVDdNIiwieSI6IjBtc0pZSUFfMC1OY2lfM0plOWZLSml3RU1ZdGRBaE9kZDZhdkp5THd0dzQifSwiYWxnIjoiRUNESC1FUytBMjU2S1ciLCJlbmMiOiJBMTI4Q0JDLUhTMjU2Iiwia2lkIjoiOC1uTGdCc2EtdlhJX2dlb0d0MDYxX1ppVlo4QkItaFlCRFNvT1FqOVFnSSJ9.nnOEhmdonA19LRvyKSrL7f8aEb2vVwE7EU-zO91fyTUls4otMVppYg.h8h7Mxz4irvckPnknsnM0g.sRQJJq-RmiF7GeqvL8EpWTstS-daLbfgGnOPybWeOj8.z3heCfTiI0cjw8GaV0qcHw

# as recipient, you can decrypt your JWE like this:
jwe = JweCompact("""eyJlcGsiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiJkSllwMHNTZUVhMnhiMkc4M2Jnam
assert jwe.decrypt(key) == plaintext
Answered By: Guillaume
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.