如何使用 python PyJWT 和 public PEM 证书来验证 JWT?
How to verify a JWT using python PyJWT with a public PEM cert?
我最近从 PyJWT 0.4.1 升级到 1.0.1,但我不知道如何验证使用 public 密钥签名的 JWT。
我的代码如下所示:
import jwt
cert_string = "-----BEGIN CERTIFICATE-----\nMIICITCCAYqgAwIBAgIIBEsUSxL..."
token_string = "eyJhbGciOiJSUzI1NiIsImtpZCI6I..."
jwt.decode(token_string, cert_string, algorithms=['RS256'])
我得到的错误是:
File "<stdin>", line 1, in <module>
File "~/.virtualenvs/project/lib/python2.7/site-packages/jwt/api.py", line 117, in decode
key, algorithms, **kwargs)
File "~/.virtualenvs/project/lib/python2.7/site-packages/jwt/api.py", line 176, in _verify_signature
key = alg_obj.prepare_key(key)
File "~/.virtualenvs/project/lib/python2.7/site-packages/jwt/algorithms.py", line 165, in prepare_key
key = load_pem_public_key(key, backend=default_backend())
File "~/.virtualenvs/project/lib/python2.7/site-packages/cryptography/hazmat/primitives/serialization.py", line 24, in load_pem_public_key
return backend.load_pem_public_key(data)
File "~/.virtualenvs/project/lib/python2.7/site-packages/cryptography/hazmat/backends/multibackend.py", line 285, in load_pem_public_key
return b.load_pem_public_key(data)
File "~/.virtualenvs/project/lib/python2.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 716, in load_pem_public_key
self._handle_key_loading_error()
File "~/.virtualenvs/project/lib/python2.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 912, in _handle_key_loading_error
raise ValueError("Could not unserialize key data.")
ValueError: Could not unserialize key data.
我相信我的 cert_string 和令牌都很好。以下代码运行正常:
from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.backends import default_backend
load_pem_x509_certificate(cert_string, default_backend())
我的用于 0.4.1 的代码如下所示:
cert_string = "".join(cert_string.strip().split("\n")[1:-1])
der = a2b_base64(cert_string)
cert = DerSequence()
cert.decode(der)
tbsCertificate = DerSequence()
tbsCertificate.decode(cert[0])
subjectPublicKeyInfo = tbsCertificate[6]
pub_key = RSA.importKey(subjectPublicKeyInfo)
jwt.decode(token_string, pub_key)
如有任何帮助,我们将不胜感激。
您需要将 public 密钥而不是完整证书传递给解码方法。所以从证书中提取密钥以便使用它:
from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.backends import default_backend
cert_str = "-----BEGIN CERTIFICATE-----MIIDETCCAfm..."
cert_obj = load_pem_x509_certificate(cert_str, default_backend())
public_key = cert_obj.public_key()
然后:
token_string = "eyJhbGciOiJSUzI1NiIsImtpZCI6I..."
jwt.decode(token_string, public_key, algorithms=['RS256'])
如果密钥文件是使用ssh-keygen -t rsa
(RFC4716)生成的,可以直接使用该文件。
编码:
import jwt
pemfile = open("id_rsa", 'r')
keystring = pemfile.read()
pemfile.close()
token = jwt.encode(payload, keystring, algorithm='RS256')
解码:
import jwt
pemfile = open("id_rsa.pub", 'r')
keystring = pemfile.read()
pemfile.close()
payload = jwt.decode(toekn, keystring, verify=True)
不要忘记捕获 jwt.ExpiredSignatureError
等错误
我正在使用 python 3.6
import jwt
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
key = b"""-----BEGIN PUBLIC KEY-----
MIIBI....<<Your public key basically>>
-----END PUBLIC KEY-----"""
public_key = serialization.load_pem_public_key(key, backend=default_backend())
print(jwt.decode(token, public_key))
这对我来说就像一个魅力。
我最近从 PyJWT 0.4.1 升级到 1.0.1,但我不知道如何验证使用 public 密钥签名的 JWT。
我的代码如下所示:
import jwt
cert_string = "-----BEGIN CERTIFICATE-----\nMIICITCCAYqgAwIBAgIIBEsUSxL..."
token_string = "eyJhbGciOiJSUzI1NiIsImtpZCI6I..."
jwt.decode(token_string, cert_string, algorithms=['RS256'])
我得到的错误是:
File "<stdin>", line 1, in <module>
File "~/.virtualenvs/project/lib/python2.7/site-packages/jwt/api.py", line 117, in decode
key, algorithms, **kwargs)
File "~/.virtualenvs/project/lib/python2.7/site-packages/jwt/api.py", line 176, in _verify_signature
key = alg_obj.prepare_key(key)
File "~/.virtualenvs/project/lib/python2.7/site-packages/jwt/algorithms.py", line 165, in prepare_key
key = load_pem_public_key(key, backend=default_backend())
File "~/.virtualenvs/project/lib/python2.7/site-packages/cryptography/hazmat/primitives/serialization.py", line 24, in load_pem_public_key
return backend.load_pem_public_key(data)
File "~/.virtualenvs/project/lib/python2.7/site-packages/cryptography/hazmat/backends/multibackend.py", line 285, in load_pem_public_key
return b.load_pem_public_key(data)
File "~/.virtualenvs/project/lib/python2.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 716, in load_pem_public_key
self._handle_key_loading_error()
File "~/.virtualenvs/project/lib/python2.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 912, in _handle_key_loading_error
raise ValueError("Could not unserialize key data.")
ValueError: Could not unserialize key data.
我相信我的 cert_string 和令牌都很好。以下代码运行正常:
from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.backends import default_backend
load_pem_x509_certificate(cert_string, default_backend())
我的用于 0.4.1 的代码如下所示:
cert_string = "".join(cert_string.strip().split("\n")[1:-1])
der = a2b_base64(cert_string)
cert = DerSequence()
cert.decode(der)
tbsCertificate = DerSequence()
tbsCertificate.decode(cert[0])
subjectPublicKeyInfo = tbsCertificate[6]
pub_key = RSA.importKey(subjectPublicKeyInfo)
jwt.decode(token_string, pub_key)
如有任何帮助,我们将不胜感激。
您需要将 public 密钥而不是完整证书传递给解码方法。所以从证书中提取密钥以便使用它:
from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.backends import default_backend
cert_str = "-----BEGIN CERTIFICATE-----MIIDETCCAfm..."
cert_obj = load_pem_x509_certificate(cert_str, default_backend())
public_key = cert_obj.public_key()
然后:
token_string = "eyJhbGciOiJSUzI1NiIsImtpZCI6I..."
jwt.decode(token_string, public_key, algorithms=['RS256'])
如果密钥文件是使用ssh-keygen -t rsa
(RFC4716)生成的,可以直接使用该文件。
编码:
import jwt
pemfile = open("id_rsa", 'r')
keystring = pemfile.read()
pemfile.close()
token = jwt.encode(payload, keystring, algorithm='RS256')
解码:
import jwt
pemfile = open("id_rsa.pub", 'r')
keystring = pemfile.read()
pemfile.close()
payload = jwt.decode(toekn, keystring, verify=True)
不要忘记捕获 jwt.ExpiredSignatureError
等错误
我正在使用 python 3.6
import jwt
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
key = b"""-----BEGIN PUBLIC KEY-----
MIIBI....<<Your public key basically>>
-----END PUBLIC KEY-----"""
public_key = serialization.load_pem_public_key(key, backend=default_backend())
print(jwt.decode(token, public_key))
这对我来说就像一个魅力。