jpadilla / pyjwt

JSON Web Token implementation in Python
https://pyjwt.readthedocs.io
MIT License
5.11k stars 684 forks source link

When using RS512, the library attempts to call verify on an `_RSAPrivateKey` object from `cryptography` #879

Closed mrussek closed 1 year ago

mrussek commented 1 year ago

Decoding JWTs using the RS512 algorithm (and presumably all RSA algorithms), fails upon trying to call verify on a _RSAPrivateKey instance.

import jwt
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa

private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
)

pem = private_key.private_bytes(encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption())

print(jwt.decode(jwt.encode({"some": "data here"}, pem, algorithm="RS512"), pem, algorithms="RS512"))

Expected Result

{'some': 'data here'}

Actual Result

Traceback (most recent call last):
  File "<REDACTED>/example.py", line 12, in <module>
    print(jwt.decode(jwt.encode({"some": "data here"}, pem, algorithm="RS512"), pem, algorithms="RS512"))
  File "<REDACTED>/code/pyjwt/jwt/api_jwt.py", line 207, in decode
    decoded = self.decode_complete(
  File "<REDACTED>/code/pyjwt/jwt/api_jwt.py", line 148, in decode_complete
    decoded = api_jws.decode_complete(
  File "<REDACTED>/code/pyjwt/jwt/api_jws.py", line 206, in decode_complete
    self._verify_signature(signing_input, header, signature, key, algorithms)
  File "<REDACTED>/code/pyjwt/jwt/api_jws.py", line 306, in _verify_signature
    if not alg_obj.verify(signing_input, key, signature):
  File "<REDACTED>/code/pyjwt/jwt/algorithms.py", line 420, in verify
    key.verify(sig, msg, padding.PKCS1v15(), self.hash_alg())
AttributeError: '_RSAPrivateKey' object has no attribute 'verify'

Reproduction Steps

import jwt
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa

private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=2048,
)

pem = private_key.private_bytes(encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption())

print(jwt.decode(jwt.encode({"some": "data here"}, pem, algorithm="RS512"), pem, algorithms="RS512"))

System Information

$ python -m jwt.help
{
  "cryptography": {
    "version": "3.4.7"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.9.5"
  },
  "platform": {
    "release": "21.6.0",
    "system": "Darwin"
  },
  "pyjwt": {
    "version": "2.6.0"
  }
}

This command is only available on PyJWT v1.6.3 and greater. Otherwise, please provide some basic information about your system.

mrussek commented 1 year ago

Whoops, forgot I needed to pass the public key in to decode 😅