Прежде всего, проект Demonware / JOSE изначально был написан для Python 2, вы, вероятно, используете ветку Python 3 . Есть нерешенные проблемы с реализацией , что, как мне кажется, говорит об авторе пакета, который не очень хорошо понимает проблему. Токены JWT в своей компактной сериализации представляют собой просто серию безопасных для URL строк Base64, соединенных с .
символами.
Когда вы шифруете или подписываете новый токен, вы должны декодировать байты в строки (просто декодируйтезначение в байтах как ASCII). При проверке или дешифровании вам необходимо снова кодировать строки в байты.
Например, для кодирования значения jwt
в объекте JSON вам необходимо декодировать:
data = {'jwt': jwt.decode('ascii')}
Весь смысл веб-токена Javascript (JWT) должен передаваться другой стороне в виде текста. Библиотека соединений имеет значение, утверждая, что метод возвращает строку.
Вы можете сократить это использование кодека utf-8
по умолчанию, поскольку ASCII является подмножеством UTF-8:
data = {'jwt': jwt.decode()}
Inв обратном направлении вам придется снова кодировать компактную строку в байты:
data = json.loads(json_document)
jose.decrypt(jose.deserialize_compact(data['jwt'].encode()), priv_jwk)
Но вы в основном используете устаревшее программное обеспечение;Проект Demonware / jose не обновлялся в течение 3 лет. Он также опирается на устаревший, не поддерживаемый пакет pycrypto. Вы не хотите использовать.
Вместо этого взгляните на Authlib или JWCrypto , два модуля, которые активно поддерживаются и используйте cryptography
проект для обработки сложных криптографических примитивов (есть также pyjwt
и python-jose
, но эти проекты (пока) не поддерживают шифрование JWE, только JWS подписанотокены).
Из них Authlib предлагает самый чистый и понятный API. Например, чтобы сгенерировать пару из открытого и закрытого ключей и создать зашифрованный токен с помощью Authlib, используя алгоритм шифрования и подписи по умолчанию, выбранный Demonware / JOSE, вы должны сделать:здесь значение bytes
, поэтому вам придется декодировать и кодировать это тоже, если вы хотите дополнительно встроить это в JSON и передать данные токена из полезной нагрузки JSON обратно в метод jwt.decode()
.
Использование тех же сериализаций открытого и закрытого ключей с JWCrypto:
import json
from jwcrypto import jwt, jwk
# Create a JWK key object from the private key
jwk_key = jwk.JWK.from_pem(private_key_pem)
# create a JWT() instance to handle ecryption and serialization
header = {'enc': 'A128CBC-HS256', 'alg': 'RSA-OAEP'}
jwt_token = jwt.JWT(claims, header)
jwt_token.make_encrypted_token(jwk_key)
token = jwt_token.serialize()
# deserialize again, using a new JWT instance but with different arguments;
# Yes, this is a confusing API.
# it's always a good idea to limit what algorithms you'll accept
# note that this is a list of both *signing* and *encryption* algorithms, not
# the possible values of the "alg" key in a JOSE header.
jwt_token = jwt.JWT(key=jwk_key, jwt=token, algs=['A128CBC-HS256', 'RSA-OAEP'])
claims_from_token = json.loads(jwt_token.claims)
Обратите внимание, что эта библиотека возвращает строку при сериализации, но вы должны выполнить JSON-декодирование заявок вручную. API также смешивает сериализацию и десериализацию в один класс, создавая очень запутанную смесь аргументов, методов и свойств.