python-jose icon indicating copy to clipboard operation
python-jose copied to clipboard

Problem signing JWT with ES or RS algorithm

Open troplolBE opened this issue 3 years ago • 1 comments

Hi !

I am trying to use the ES256 algorithm to sign all my token but for some reason I receive errors when I try to do that. I use Python 3.7 with python-jose 3.3.0. I tried with version 3.2.0 and python 3.8 but it doesn't change anything. Here is the code I use for sample.

I do not have the problem if I use the HS algorithm.

from jose import jwt


token = jwt.encode({'iss': 'me'}, 'secret', algorithm='ES256')
print(token)

I get the 4 following errors as a result:

/Users/troplolBE/PycharmProjects/api/venv/lib/python3.8/site-packages/jose/backends/cryptography_backend.py:18: CryptographyDeprecationWarning: int_from_bytes is deprecated, use int.from_bytes instead
  from cryptography.utils import int_from_bytes, int_to_bytes
Traceback (most recent call last):
  File "/Users/troplolBE/PycharmProjects/api/venv/lib/python3.8/site-packages/jose/backends/cryptography_backend.py", line 61, in __init__
    key = load_pem_public_key(key, self.cryptography_backend())
  File "/Users/troplolBE/PycharmProjects/api/venv/lib/python3.8/site-packages/cryptography/hazmat/primitives/serialization/base.py", line 30, in load_pem_public_key
    return ossl.load_pem_public_key(data)
  File "/Users/troplolBE/PycharmProjects/api/venv/lib/python3.8/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 853, in load_pem_public_key
    self._handle_key_loading_error()
  File "/Users/troplolBE/PycharmProjects/api/venv/lib/python3.8/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1129, in _handle_key_loading_error
    raise ValueError(
ValueError: ('Could not deserialize key data. The data may be in an incorrect format, it may be encrypted with an unsupported algorithm, or it may be an unsupported key type (e.g. EC curves with explicit parameters).', [_OpenSSLErrorWithText(code=151584876, lib=9, reason=108, reason_text=b'error:0909006C:PEM routines:get_name:no start line')])

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/troplolBE/PycharmProjects/api/venv/lib/python3.8/site-packages/jose/backends/cryptography_backend.py", line 63, in __init__
    key = load_pem_private_key(key, password=None, backend=self.cryptography_backend())
  File "/Users/troplolBE/PycharmProjects/api/venv/lib/python3.8/site-packages/cryptography/hazmat/primitives/serialization/base.py", line 22, in load_pem_private_key
    return ossl.load_pem_private_key(data, password)
  File "/Users/troplolBE/PycharmProjects/api/venv/lib/python3.8/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 823, in load_pem_private_key
    return self._load_key(
  File "/Users/troplolBE/PycharmProjects/api/venv/lib/python3.8/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1070, in _load_key
    self._handle_key_loading_error()
  File "/Users/troplolBE/PycharmProjects/api/venv/lib/python3.8/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1129, in _handle_key_loading_error
    raise ValueError(
ValueError: ('Could not deserialize key data. The data may be in an incorrect format, it may be encrypted with an unsupported algorithm, or it may be an unsupported key type (e.g. EC curves with explicit parameters).', [_OpenSSLErrorWithText(code=151584876, lib=9, reason=108, reason_text=b'error:0909006C:PEM routines:get_name:no start line')])

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/troplolBE/PycharmProjects/api/venv/lib/python3.8/site-packages/jose/jws.py", line 169, in _sign_header_and_claims
    key = jwk.construct(key_data, algorithm)
  File "/Users/troplolBE/PycharmProjects/api/venv/lib/python3.8/site-packages/jose/jwk.py", line 60, in construct
    return key_class(key_data, algorithm)
  File "/Users/troplolBE/PycharmProjects/api/venv/lib/python3.8/site-packages/jose/backends/cryptography_backend.py", line 65, in __init__
    raise JWKError(e)
jose.exceptions.JWKError: ('Could not deserialize key data. The data may be in an incorrect format, it may be encrypted with an unsupported algorithm, or it may be an unsupported key type (e.g. EC curves with explicit parameters).', [_OpenSSLErrorWithText(code=151584876, lib=9, reason=108, reason_text=b'error:0909006C:PEM routines:get_name:no start line')])

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "research.py", line 4, in <module>
    token = jwt.encode({'iss': 'me'}, 'secret', algorithm='ES256')
  File "/Users/troplolBE/PycharmProjects/api/venv/lib/python3.8/site-packages/jose/jwt.py", line 64, in encode
    return jws.sign(claims, key, headers=headers, algorithm=algorithm)
  File "/Users/troplolBE/PycharmProjects/api/venv/lib/python3.8/site-packages/jose/jws.py", line 50, in sign
    signed_output = _sign_header_and_claims(encoded_header, encoded_payload, algorithm, key)
  File "/Users/troplolBE/PycharmProjects/api/venv/lib/python3.8/site-packages/jose/jws.py", line 172, in _sign_header_and_claims
    raise JWSError(e)
jose.exceptions.JWSError: ('Could not deserialize key data. The data may be in an incorrect format, it may be encrypted with an unsupported algorithm, or it may be an unsupported key type (e.g. EC curves with explicit parameters).', [_OpenSSLErrorWithText(code=151584876, lib=9, reason=108, reason_text=b'error:0909006C:PEM routines:get_name:no start line')])

troplolBE avatar Mar 02 '22 15:03 troplolBE

HS* is an HMAC algorithm, so passing a simple string as the secret key works. RS* (RSA) and ES* (ECDSA) algorithms use asymmetric cryptography, so the secret has to be a proper private key. See https://auth0.com/blog/json-web-token-signing-algorithms-overview/ for a brief overview.

If you want to experiment with different algorithms and keys, this key generator website is quite handy: https://mkjwk.org/

If you pass "Private Key (X.509 PEM Format)" from that website as the secret, it should work. For example:

private_key = """
-----BEGIN PRIVATE KEY-----
MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCAhjKwOYyR1c8/xHS9S
OhK+LAcg27Txp/KaR+6lDRu4jg==
-----END PRIVATE KEY-----
"""

token = jwt.encode({'iss': 'me'}, private_key, algorithm='ES256')

polys avatar Dec 01 '22 16:12 polys