Hesbon
Hesbon

Reputation: 81

ValueError: Could not deserialize key data during jwt encoding

I am trying to generate a token using jwt and I'm passing the payload, secret_key, and algorithm ('RS256'). Here is the section of the code

secret_key = AppConfig.JWT_SECRET_KEY
public_key = AppConfig.JWT_PUBLIC_KEY
payload = {'UserInfo': user_one.to_dict()}
payload['UserInfo']['picture'] = 'https://someimage.url'
payload.__setitem__('exp', exp) if exp is not None else ''
token = jwt.encode(payload, secret_key, algorithm='RS256').decode(CHARSET)

I'm getting this error

  File "/root/.pyenv/versions/3.6.5/lib/python3.6/code.py", line 91, in runcode
    exec(code, self.locals)
  File "<console>", line 1, in <module>
  File "/activo-api/tests/helpers/generate_token.py", line 30, in generate_token
    token = jwt.encode(payload, secret_key, algorithm='RS256').decode(CHARSET)
  File "/root/.local/share/virtualenvs/activo-api-lpKgDXk8/lib/python3.6/site-packages/jwt/api_jwt.py", line 65, in encode
    json_payload, key, algorithm, headers, json_encoder
  File "/root/.local/share/virtualenvs/activo-api-lpKgDXk8/lib/python3.6/site-packages/jwt/api_jws.py", line 113, in encode
    key = alg_obj.prepare_key(key)
  File "/root/.local/share/virtualenvs/activo-api-lpKgDXk8/lib/python3.6/site-packages/jwt/algorithms.py", line 207, in prepare_key
    key = load_pem_public_key(key, backend=default_backend())
  File "/root/.local/share/virtualenvs/activo-api-lpKgDXk8/lib/python3.6/site-packages/cryptography/hazmat/primitives/serialization/base.py", line 20, in load_pem_public_key
    return backend.load_pem_public_key(data)
  File "/root/.local/share/virtualenvs/activo-api-lpKgDXk8/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1071, in load_pem_public_key
    self._handle_key_loading_error()
  File "/root/.local/share/virtualenvs/activo-api-lpKgDXk8/lib/python3.6/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1329, in _handle_key_loading_error
    raise ValueError("Could not deserialize key data.")
ValueError: Could not deserialize key data.

When I use HS256 algorithm, a token is generated, but when I use RS256 algorithm, I get the error above. I have tried almost all the solutions provided online but I'm still getting the same error.

My secret key has this format:

-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA3Tz2mr7SZiAMfQyuvBjM9Oi
RK+Lh9x5eJPo5CAZ3/ANBE0sTK0ZsDGMak2m1g7
wnLe4nOb7/eEJbDPkk05ShhBrJGBKKxb8n104o/
...........
5A13wiLitEO7nco2WfyYkQzaxCw0AwzlkVHiIyC
DtkpjGHQzPF6vOe907y5NQLvVFGXUq/FIJZxB8d==
-----END RSA PRIVATE KEY-----

The expected output should be a token

Upvotes: 2

Views: 12540

Answers (2)

Javad Asoodeh
Javad Asoodeh

Reputation: 318

It seems like you're encountering a ValueError: Could not deserialize key data during JWT encoding. This error typically indicates an issue with the format or compatibility of the key being used with the RS256 algorithm. Here's how you can resolve this:

  1. Install Cryptography: First, ensure you have the cryptography library installed:

    pip install cryptography
    
  2. Generate RSA Keys Using OpenSSL: You need to create new RSA keys that are compatible with your encoding process:

    openssl genrsa -out jwt-key 4096
    openssl rsa -in jwt-key -pubout > jwt-key.pub
    
    • The first command generates a 4096-bit RSA private key (jwt-key).
    • The second command extracts the public key from the private key and saves it as jwt-key.pub.
  3. Update Your Code: After generating these keys, update your code to use jwt-key for the secret_key and jwt-key.pub for the public_key. Ensure that these keys are properly loaded and formatted according to the requirements of the PyJWT library.

This process should solve the issue with the RS256 algorithm. When using RS256, you sign the token with the private key and verify it with the public key. Ensure that the keys are stored and used securely.

Reference: Link

Upvotes: 2

Hesbon
Hesbon

Reputation: 81

So, the string PEM keys were not working for me.

So I decided to serialize them. There are several common schemes for serializing asymmetric private and public keys to bytes. They generally support the encryption of private keys and additional key metadata. The steps for the solution is as follows:

When generating the token using jwt.encode()

  1. Import the following dependencies

    • from cryptography.hazmat.backends import default_backend
    • from cryptography.hazmat.primitives import serialization
  2. Instead of passing a string format of the PEM private key when encoding, serialize it as follows

    secret_key = serialization.load_pem_private_key(
        secret_key_string.encode(), password=None, backend=default_backend())
    payload = {'UserInfo': {"name":"name", "email":"[email protected]"}
    payload.__setitem__('exp', exp) if exp is not None else ''
    token = jwt.encode(payload, secret_key, algorithm='RS256').decode(CHARSET)```
    

Usually, the jwt.encode() method takes secret (string) as one of it's parameters. In our case above, we are passing a serialized object as the secret

When decoding the token using jwt.decode()

Deserialize a public key from PEM encoded data to one of the supported asymmetric public key types. In order to decode the token successfully, follow the steps below

  1. Import the following dependencies
    • from cryptography.hazmat.backends import default_backend
    • from cryptography.hazmat.primitives import serialization
  2. Encode the PEM public key using utf-8 and pass ifload_pem_public_key() method as a parameter in order to serialize it as follows

    public_key = AppConfig.JWT_PUBLIC_KEY public_key_obj = serialization.load_pem_public_key( public_key.encode(), backend=default_backend())

  3. Decode the token by passing the serialized public key object into the jwt.decode() method as follows

    decoded_token = jwt.decode(token,public_key_obj, algorithms=['RS256'], options={ 'verify_signature': True, 'verify_exp': True })

You can find more information about serializing PEM public and PEM private keys Here

Upvotes: 1

Related Questions