Giter Club home page Giter Club logo

Comments (23)

mark-adams avatar mark-adams commented on May 21, 2024 2

Thanks @buzzrick. Generally speaking, it is safe to share the RSA public key publicly (hence the name) as long as you don't share the RSA private key. I've had a chance to look over what you sent me and I think I've figured out where the issue lies.

PyJWT's documentation talks about accepting two kinds of RSA public keys: PEM and SSH format. PEM keys start with "-----BEGIN PUBLIC KEY-----" and SSH format keys start with "ssh-rsa". The file you sent me starts with "-----BEGIN CERTIFICATE-----" indicating that it is a x509 certificate in PEM format. A certificate is actually a public key accompanied by certain statements about that key (who owns it, how long it is valid, etc.) that are together digitally signed by a third-party authority who is vouching for its authenticity. However, an x509 certificate is not exactly an RSA key in PEM format... even though it does actually contain the RSA public key. That is why you are getting an error.

I was curious so I went back to v0.3.2 (cd32cf2) and ran the following:

>>> cert = open('certificate.cer', 'r').read()
>>> import jwt
>>> jwt.prepare_RS_key(cert)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "jwt/__init__.py", line 105, in prepare_RS_key
    key = RSA.importKey(key)
  File "/home/mark/.venv/pyjwt/local/lib/python2.7/site-packages/Crypto/PublicKey/RSA.py", line 665, in importKey
    return self._importKeyDER(der)
  File "/home/mark/.venv/pyjwt/local/lib/python2.7/site-packages/Crypto/PublicKey/RSA.py", line 588, in _importKeyDER
    raise ValueError("RSA key format is not supported")
ValueError: RSA key format is not supported

It seems like the v0.3.2 also rejects x509 certificates so I'm not sure how it was working before unless something changed with regards to how you were generating your keys. At any point in time did you change from generating PEM public keys to generating PEM x509 certificates?

The good news is... there are some easy workarounds to solve this problem since the RSA public key can be extracted from the x509 certificate.

First, OpenSSL can extract the key for you in PEM format by running the following command:

openssl x509 -in certificate.cer -noout -pubkey > public_key.pem

You can then read public_key.pem in and use it as the key in PyJWT.

Second, if you like doing things in Python, cryptography can help you extract the public key from the certificate:

from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.backends import default_backend

certificate_text = open('certificate.cer', 'r').read()
certificate = load_pem_x509_certificate(certificate_text, default_backend())
publickey = certificate.public_key()

The publickey variable can then be passed in as the key to verify().

I hope that helps! I'm sorry I can't help explain why you didn't seem to run into this problem with v0.3.2 but it appears that the older version couldn't import x509 certificates either.

Also, one last recommendation: most people consider 1024-bit RSA keys to be risky now as computers have gotten better and better at being able to brute-force them. Generally, most people have begun transitioning to 2048-bit (or higher) keys. Just something to consider. :-)

cc: @jpadilla

from pyjwt.

buzzrick avatar buzzrick commented on May 21, 2024 1

Yay. I have managed to decode the public key from the certificate string as follows:

certBytes = list(unicodeCertString.encode())
certificate = load_pem_x509_certificate(certBytes, default_backend())
publicKey = certificate.public_key()

PyJWT v0.4.1 does work with this instance of the key.

Interestingly this code does NOT work with PyJWT v0.3.2. The issue just seems to be a difference in the way that the cryptography/PyCrypto dependancy works.

Thanks Mark for your assistance.

from pyjwt.

 avatar commented on May 21, 2024 1

Thanks for the explanation. I would recommend to indicate this in the example, e.g. sth. like:

encoded = jwt.encode({'header': '<jwt header>', 'claim_set': '<jwt claim set>'}, '<rsa key>', algorithm='HS256')

from pyjwt.

wild3r avatar wild3r commented on May 21, 2024 1

from signxml import *
from xml.etree import ElementTree
import base64
from lxml import etree

Good day to all friends, I want to convert .pen to base64 and I sell the following error, thanks for the help

codigo:

Send File

f = open('/home/carlos/invoice/certifica/20600995805-01-FF11-00000027.xml', 'rb')
xml_content = f.read()
cert = open('/home/carlos/invoice/certifica/CERTIFICADO.pem').read()
key = open('/home/carlos/invoice/certifica/CERTIFICADO.key').read()

cert = base64.decodestring(cert)
key = base64.b64decode(key)

error;

File "example.py", line 14, in
cert = base64.decodestring(cert)
File "/usr/lib/python2.7/base64.py", line 321, in decodestring
return binascii.a2b_base64(s)
binascii.Error: Incorrect padding

from pyjwt.

jpadilla avatar jpadilla commented on May 21, 2024

@mark-adams would you happen to know what might be going on here?

from pyjwt.

mark-adams avatar mark-adams commented on May 21, 2024

I'll take a look today

from pyjwt.

mark-adams avatar mark-adams commented on May 21, 2024

@buzzrick Can you provide an example JWT?

from pyjwt.

mark-adams avatar mark-adams commented on May 21, 2024

@buzzrick It looks like the test is failing because the key is not in a valid format. We have tests that cover both types (PEM & SSH) of public key. Can you attach the public key that is being used to verify so that we can see why its failing?

from pyjwt.

buzzrick avatar buzzrick commented on May 21, 2024

I have sent an email to mark-adams with an example JWT and certificate (I'm not sure whether it is a good idea to paste the details in public here).

from pyjwt.

buzzrick avatar buzzrick commented on May 21, 2024

Darn, sorry, i should have mentioned that we do decode the certificate, and extract the public key component of it, which we use to verify the signature.
I didn't post the public key, because it is a binary blob, not a string.

we use the following code snippet to do extract the public key:

                    lines = certificates[certKey].replace(" ",'').split()
                    der = a2b_base64(''.join(lines[1:-1]))

                    # Extract subjectPublicKeyInfo field from X.509 certificate (see RFC3280)
                    cert = DerSequence()
                    cert.decode(der)
                    tbsCertificate = DerSequence()
                    tbsCertificate.decode(cert[0])
                    subjectPublicKeyInfo = tbsCertificate[6]

from pyjwt.

mark-adams avatar mark-adams commented on May 21, 2024

How are you extracting the public key? Is it possible for you to try one of the methods above? Maybe the format you're extracting into was accidentally readable by the old version but not the new? I know that the docs have always said PEM and SSH and that's what we did when we ported over from PyCrypto to cryptography but its possible maybe another format was allowed by PyCrypto.

from pyjwt.

buzzrick avatar buzzrick commented on May 21, 2024

I'm getting the public key as per my updated comment above. I've had a quick attempt at using the following method

from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.backends import default_backend

certificate_text = open('certificate.cer', 'r').read()
certificate = load_pem_x509_certificate(certificate_text, default_backend())
publickey = certificate.public_key()

Unfortunately, our cert is stored as a string in a database, not in a file, so i'm getting an initializer for ctype 'char[]' must be a str or list or tuple, not unicode error. I'll have another shot at it this afternoon once i've finished some other pressing tasks, and get back to you.

from pyjwt.

mark-adams avatar mark-adams commented on May 21, 2024

Yea, PyCrypto and cryptography have two totally different representations of the RSA key so the example code using load_pem_x509_certificate would definitely not work with any pre-cryptography versions (like 0.3.2)

I'm glad the workaround is working for you! Thanks for reaching out!

from pyjwt.

jpadilla avatar jpadilla commented on May 21, 2024

@mark-adams thanks again for stepping and helping out!

from pyjwt.

 avatar commented on May 21, 2024

Should this be fixed? I am getting the same error:

ValueError: Could not unserialize key data.

Following packages installed:

PyJWT==1.4.0
cryptography==1.4

Running:

encoded = jwt.encode({'some': 'payload'}, 'secret', algorithm='RS256')

from pyjwt.

mark-adams avatar mark-adams commented on May 21, 2024

@kevart You must use an actual RSA key as the secret= argument. When the algorithm is specified as 'RS256', PyJWT tries to convert the argument into a crytography RSA key object. If the value you are passing in is not an RSA key, you'll receive a ValueErrro.

In your case, if you're literally using the string 'secret' as the value, it won't work because the word 'secret' is not a valid RSA key.

from pyjwt.

DylanVerstraete avatar DylanVerstraete commented on May 21, 2024

@buzzrick I'm getting initializer for ctype 'char' must be a bytes of length 1, not int
when using

cert = "-----BEGIN PUBLIC KEY-----MHYwEAYHKoZIzj0CAQ...."
certBytes = list(cert.encode())
certificate = load_pem_x509_certificate(certBytes, default_backend())
publicKey = certificate.public_key()

print(jwt.decode(jsonWt, publicKey, algorithms=["ES384"]))

from pyjwt.

fbartolom avatar fbartolom commented on May 21, 2024

I have this code:

import jwt
import time
from hyper import HTTPConnection
ALGORITHM = 'ES256'
APNS_KEY_ID = 'H6Q3X7RYZG'
APNS_AUTH_KEY = 'APNsAuthKey_H6Q3X7RYZG.p8'
TEAM_ID = 'GF9PQ87F68'
REGISTRATION_ID = '713d3a9f4d932ac824caf9373a2f182b2dfa710fb7b6214e3bd405ae1e32d0aa'
BUNDLE_ID = 'com.meditation.iPujaPro'
f = open(APNS_AUTH_KEY)
secret = f.read()
token = jwt.encode(
{
'iss': TEAM_ID,
'iat': time.time()
},
secret,
algorithm= ALGORITHM,
headers={
'alg': ALGORITHM,
'kid': APNS_KEY_ID,
}
)
and I am getting error:
Traceback (most recent call last):
File "simpleNotification.py", line 24, in
'kid': APNS_KEY_ID,
File "/usr/lib64/python2.7/site-packages/jwt/api_jwt.py", line 56, in encode
json_payload, key, algorithm, headers, json_encoder
File "/usr/lib64/python2.7/site-packages/jwt/api_jws.py", line 98, in encode
key = alg_obj.prepare_key(key)
File "/usr/lib64/python2.7/site-packages/jwt/algorithms.py", line 226, in prepare_key
key = load_pem_private_key(key, password=None, backend=default_backend())
File "/usr/lib64/python2.7/site-packages/cryptography/hazmat/primitives/serialization.py", line 20, in load_pem_private_key
return backend.load_pem_private_key(data, password)
File "/usr/lib64/python2.7/site-packages/cryptography/hazmat/backends/multibackend.py", line 305, in load_pem_private_key
return b.load_pem_private_key(data, password)
File "/usr/lib64/python2.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1084, in load_pem_private_key
password,
File "/usr/lib64/python2.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1253, in _load_key
self._handle_key_loading_error()
File "/usr/lib64/python2.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1325, in _handle_key_loading_error
raise ValueError("Could not unserialize key data.")
ValueError: Could not unserialize key data.
[fabrizio@localhost push]$ !!
python simpleNotification.py
Traceback (most recent call last):
File "simpleNotification.py", line 24, in
'kid': APNS_KEY_ID,
File "/usr/lib64/python2.7/site-packages/jwt/api_jwt.py", line 56, in encode
json_payload, key, algorithm, headers, json_encoder
File "/usr/lib64/python2.7/site-packages/jwt/api_jws.py", line 98, in encode
key = alg_obj.prepare_key(key)
File "/usr/lib64/python2.7/site-packages/jwt/algorithms.py", line 226, in prepare_key
key = load_pem_private_key(key, password=None, backend=default_backend())
File "/usr/lib64/python2.7/site-packages/cryptography/hazmat/primitives/serialization.py", line 20, in load_pem_private_key
return backend.load_pem_private_key(data, password)
File "/usr/lib64/python2.7/site-packages/cryptography/hazmat/backends/multibackend.py", line 305, in load_pem_private_key
return b.load_pem_private_key(data, password)
File "/usr/lib64/python2.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1084, in load_pem_private_key
password,
File "/usr/lib64/python2.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1253, in _load_key
self._handle_key_loading_error()
File "/usr/lib64/python2.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1325, in _handle_key_loading_error
raise ValueError("Could not unserialize key data.")
ValueError: Could not unserialize key data.
[fabrizio@localhost push]$ !!
python simpleNotification.py
Traceback (most recent call last):
File "simpleNotification.py", line 25, in
'kid': APNS_KEY_ID,
File "/usr/lib64/python2.7/site-packages/jwt/api_jwt.py", line 56, in encode
json_payload, key, algorithm, headers, json_encoder
File "/usr/lib64/python2.7/site-packages/jwt/api_jws.py", line 98, in encode
key = alg_obj.prepare_key(key)
File "/usr/lib64/python2.7/site-packages/jwt/algorithms.py", line 226, in prepare_key
key = load_pem_private_key(key, password=None, backend=default_backend())
File "/usr/lib64/python2.7/site-packages/cryptography/hazmat/primitives/serialization.py", line 20, in load_pem_private_key
return backend.load_pem_private_key(data, password)
File "/usr/lib64/python2.7/site-packages/cryptography/hazmat/backends/multibackend.py", line 305, in load_pem_private_key
return b.load_pem_private_key(data, password)
File "/usr/lib64/python2.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1084, in load_pem_private_key
password,
File "/usr/lib64/python2.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1253, in _load_key
self._handle_key_loading_error()
File "/usr/lib64/python2.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1325, in _handle_key_loading_error
raise ValueError("Could not unserialize key data.")
ValueError: Could not unserialize key data.

from pyjwt.

mark-adams avatar mark-adams commented on May 21, 2024

Your key is in the wrong format. PyJWT expects an RSA key to be in PEM format. If you convert your key to PEM format, that should resolve the issue.

from pyjwt.

fbartolom avatar fbartolom commented on May 21, 2024

Good to know, thanks. But how do I modify my python code in order to do what you suggest? I am no crypto expert and I just copied the script without much understanding of what it did.

from pyjwt.

fbartolom avatar fbartolom commented on May 21, 2024

If I execute:
openssl pkcs8 -inform DER -nocrypt -in APNsAuthKey_H6Q3X7RYZG.p8 -out APNsAuthKey_H6Q3X7RYZG.pem
I get:
Error decrypting key
139845397403552:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:1343:
139845397403552:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:tasn_dec.c:393:Type=PKCS8_PRIV_KEY_INFO

from pyjwt.

tema85 avatar tema85 commented on May 21, 2024

I had the Cryptography error, I've installed cryptography with command "easy_install cryptography"
now I have this error:

Traceback (most recent call last):
File "D:/ITIS/Thesis/Token/pyjwt-master/Run-token.py", line 22, in
encoded = jwt.encode(input1, private_key, algorithm='RS256')
File "D:\ITIS\Thesis\Token\pyjwt-master\jwt\api_jwt.py", line 59, in encode
json_payload, key, algorithm, headers, json_encoder
File "D:\ITIS\Thesis\Token\pyjwt-master\jwt\api_jws.py", line 127, in encode
key = alg_obj.prepare_key(key)
File "D:\ITIS\Thesis\Token\pyjwt-master\jwt\algorithms.py", line 207, in prepare_key
key = load_pem_public_key(key, backend=default_backend())
File "C:\Python27\lib\site-packages\cryptography-2.2.2-py2.7-win-amd64.egg\cryptography\hazmat\primitives\serialization.py", line 24, in load_pem_public_key
return backend.load_pem_public_key(data)
File "C:\Python27\lib\site-packages\cryptography-2.2.2-py2.7-win-amd64.egg\cryptography\hazmat\backends\openssl\backend.py", line 1040, in load_pem_public_key
self._handle_key_loading_error()
File "C:\Python27\lib\site-packages\cryptography-2.2.2-py2.7-win-amd64.egg\cryptography\hazmat\backends\openssl\backend.py", line 1291, in _handle_key_loading_error
raise ValueError("Could not deserialize key data.")
ValueError: Could not deserialize key data.

thanks for your helps in advance

from pyjwt.

pavelsuk avatar pavelsuk commented on May 21, 2024

I tried the example from #82 (comment) and it requires little bugfix - the file should be opened as binary:

certificate_text = open('certificate.cer', 'rb').read()

So complete code is:

from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.backends import default_backend

certificate_text = open('certificate.cer', 'rb').read()
certificate = load_pem_x509_certificate(certificate_text, default_backend())
publickey = certificate.public_key()

from pyjwt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.