Reputation: 81
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
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:
Install Cryptography: First, ensure you have the cryptography library installed:
pip install cryptography
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
jwt-key
).jwt-key.pub
.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
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()
Import the following dependencies
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
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 aserialized object
as thesecret
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
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
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())
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