jpadilla / pyjwt

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

TypeError: sign() takes 3 positional arguments but 4 were given #429

Closed PiotrNestor closed 2 years ago

PiotrNestor commented 5 years ago

I'm getting: TypeError: sign() takes 3 positional arguments but 4 were given

Expected Result

Token is returned

Actual Result

TypeError: sign() takes 3 positional arguments but 4 were given

   File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/jwt/api_jwt.py", line 65, in encode
    json_payload, key, algorithm, headers, json_encoder
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/jwt/api_jws.py", line 114, in encode
    signature = alg_obj.sign(signing_input, key)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/jwt/algorithms.py", line 313, in sign
    return key.sign(msg, padding.PKCS1v15(), self.hash_alg())
TypeError: sign() takes 3 positional arguments but 4 were given

Reproduction Steps

import jwt

private_key = b'''-----BEGIN EC PRIVATE KEY-----
...
-----END EC PRIVATE KEY-----'''
claim2 = { "Keyid": "abcdefg"}
token = jwt.encode(claim2, private_key, algorithm='RS256')

System Information

$ python -m jwt.help
{
  "cryptography": {
    "version": "2.7"
  },
  "implementation": {
    "name": "CPython",
    "version": "3.7.3"
  },
  "platform": {
    "release": "18.6.0",
    "system": "Darwin"
  },
  "pyjwt": {
    "version": "1.7.1"
  }
}

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

PiotrNestor commented 5 years ago

This is on MacOS: uname -a Darwin EU-EXT-CKY 18.6.0 Darwin Kernel Version 18.6.0: Thu Apr 25 23:16:27 PDT 2019; root:xnu-4903.261.4~2/RELEASE_X86_64 x86_64

drbitboy commented 5 years ago

Hi Piotr et al.,

Summary

The Reproduction Steps example has a mismatch between the Elliptic Curve private_key argument and the algorithm='RS256' keyword argument, which mismatch generates an exception; that exception, though less than helpful, is correct behavior.

Suggestion

To be more informative, the prepare_key methods of the various Algorithm sub-classes could check the types of their return values before returning them, and throw an exception for a mismatch between the key and the algorithm, allowing a more informative traceback e.g.

assert isinstance(key, RSAPrivateKey) or isinstance(key, RSAPublicKey),'Key type mismatch:  {0} is not RSAPrivateKey or RSAPublicKey'.format(str(type(key)))
Traceback (most recent call last):
  [...]
AssertionError: Key type mismatch:  <class 'cryptography.hazmat.backends.openssl.ec._EllipticCurvePrivateKey'> is not RSAPrivateKey or RSAPublicKey

Details

The algorithm should be ES256, because

sign(data, signature_algorithm) method of cryptography.hazmat.backends.openssl.ec._EllipticCurvePrivateKey instance


Here is a successful call:

jwt.encode(claim2,private_key,algorithm='ES256') b'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJLZXlpZCI6ImFiY2RlZmcifQ.SZIVRIO3Rpp1AgmPpZiqppFwOAunznvjr-xRPo8JzTHpWwICF9Gs4pdP1vf5wfiS9w93pmEXnnLct-ozB_N4Gw'


I generated my own Elliptic Curve ```private_key``` with ```% openssl ecparam -name secp256k1 -genkey```
schumannd commented 4 years ago

Can you give an example of successfully using "RS256" as an encoding algorithm, or does that not work?

github-actions[bot] commented 2 years ago

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days