2015-04-15 5 views
10

Starałem się, aby PyJWT 1.1.0 zweryfikować JWT z kluczem publicznym. Klucze te są domyślnie dostarczane z Keycloak. Najprawdopodobniej problem jest związany z tworzeniem tajnego klucza, ale nie znalazłem żadnych przykładów tworzenia klucza bez certyfikatu z kluczem prywatnym i publicznym.Jak zweryfikować JWT za pomocą python PyJWT z kluczem publicznym

Oto moje próby, aby to działało. Niektóre z poniższych testów narzekają na nieprawidłowy klucz, a niektóre z nich narzekają, że token nie został poprawnie zweryfikowany w odniesieniu do klucza.

import jwt 

from cryptography.hazmat.backends import default_backend 
from itsdangerous import base64_decode 
from Crypto.PublicKey import RSA 


secret = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCIE6a1NyEFe7qCDFrvWFZiAlY1ttE5596w5dLjNSaHlKGv8AXbKg/f8yKY9fKAJ5BKoeWEkPPjpn1t9QQAZYzqH9KNOFigMU8pSaRUxjI2dDvwmu8ZH6EExY+RfrPjQGmeliK18iFzFgBtf0eH3NAW3Pf71OZZz+cuNnVtE9lrYQIDAQAB" 
secretDer = base64_decode(secret) 
sshrsaSecret = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCIE6a1NyEFe7qCDFrvWFZiAlY1ttE5596w5dLjNSaHlKGv8AXbKg/f8yKY9fKAJ5BKoeWEkPPjpn1t9QQAZYzqH9KNOFigMU8pSaRUxjI2dDvwmu8ZH6EExY+RfrPjQGmeliK18iFzFgBtf0eH3NAW3Pf71OZZz+cuNnVtE9lrYQ==" 
secretPEM = "-----BEGIN PUBLIC KEY-----\n" + secret + "\n-----END PUBLIC KEY-----" 
access_token = "eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiIzM2ZhZGYzMS04MzZmLTQzYWUtODM4MS01OGJhM2RhMDMwYTciLCJleHAiOjE0MjkwNzYyNTYsIm5iZiI6MCwiaWF0IjoxNDI5MDc2MTk2LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODEvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjoic2VjdXJpdHktYWRtaW4tY29uc29sZSIsInN1YiI6ImMzNWJlODAyLTcyOGUtNGMyNC1iMjQ1LTQxMWIwMDRmZTc2NSIsImF6cCI6InNlY3VyaXR5LWFkbWluLWNvbnNvbGUiLCJzZXNzaW9uX3N0YXRlIjoiYmRjOGM0ZDgtYzUwNy00MDQ2LWE4NDctYmRlY2QxNDVmZTNiIiwiY2xpZW50X3Nlc3Npb24iOiI0OTI5YmRjNi0xOWFhLTQ3MDYtYTU1Mi1lOWI0MGFhMDg5ZTYiLCJhbGxvd2VkLW9yaWdpbnMiOltdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiYWRtaW4iLCJjcmVhdGUtcmVhbG0iXX0sInJlc291cmNlX2FjY2VzcyI6eyJtYXN0ZXItcmVhbG0iOnsicm9sZXMiOlsibWFuYWdlLWV2ZW50cyIsIm1hbmFnZS1jbGllbnRzIiwidmlldy1yZWFsbSIsInZpZXctZXZlbnRzIiwibWFuYWdlLWlkZW50aXR5LXByb3ZpZGVycyIsInZpZXctaWRlbnRpdHktcHJvdmlkZXJzIiwidmlldy11c2VycyIsInZpZXctY2xpZW50cyIsIm1hbmFnZS11c2VycyIsIm1hbmFnZS1yZWFsbSJdfX0sIm5hbWUiOiIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiJ9.O7e8dkv0k-2HCjMdZFXIxLhypVyRPwIdrQsYTMwC1996wbsjIw1L3OjDSzJKXcx0U9YrVeRM4yMVlFg40uJDC-9IsKZ8nr5dl_da8SzgpAkempxpas3girST2U9uvY56m2Spp6-EFInvMSb6k4t1L49_Q7R2g0DOlKzxgQd87LY" 

############### Test using PEM key (with ----- lines) 
try: 
    access_token_json = jwt.decode(access_token, key=secretPEM) 
except Exception as e: 
    print "Not working using PEM key with ----: ", e 
else: 
    print "It worked!" 

############### Test using PEM key (without ----- lines) 
try: 
    access_token_json = jwt.decode(access_token, key=secret) 
except Exception as e: 
    print "Not working using PEM key without ----: ", e 
else: 
    print "It worked!" 

############### Test using DER key 
try: 
    access_token_json = jwt.decode(access_token, key=secretDer) 
except Exception as e: 
    print "Not working using DER key: ", e 
else: 
    print "It worked!" 

############### Test using DER key #2 
try: 
    public_key = default_backend().load_der_public_key(secretDer) 
    access_token_json = jwt.decode(access_token, key=public_key) 
except Exception as e: 
    print "Not working using DER key #2: ", e 
else: 
    print "It worked!" 

############### Test using SSH style key 
try: 
    access_token_json = jwt.decode(access_token, key=sshrsaSecret) 
except Exception as e: 
    print "Not working using SSH style key: ", e 
else: 
    print "It worked!" 

############### Test using RSA numbers 
class Numbers: 
    pass 

numbers = Numbers() 
public_key = RSA.importKey(secretDer) 
numbers.e = public_key.key.e 
numbers.n = public_key.key.n 
# yet another way to generated valid key object 
public_key = default_backend().load_rsa_public_numbers(numbers) 
print public_key 
try: 
    access_token_json = jwt.decode(access_token, key=public_key) 
except Exception as e: 
    print "Not working using RSA numbers: ", e 
else: 
    print "It worked!" 
############### 

Sprawdziłem, czy token i klucz współpracują z implementacją Java, patrz poniżej.

import org.springframework.security.jwt.JwtHelper; 
import org.springframework.security.jwt.crypto.sign.RsaVerifier; 
import org.springframework.security.jwt.crypto.sign.SignatureVerifier; 

public class JWTTest { 
    public static final void main(String[] argv) { 
     String token = "eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiIzM2ZhZGYzMS04MzZmLTQzYWUtODM4MS01OGJhM2RhMDMwYTciLCJleHAiOjE0MjkwNzYyNTYsIm5iZiI6MCwiaWF0IjoxNDI5MDc2MTk2LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODEvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjoic2VjdXJpdHktYWRtaW4tY29uc29sZSIsInN1YiI6ImMzNWJlODAyLTcyOGUtNGMyNC1iMjQ1LTQxMWIwMDRmZTc2NSIsImF6cCI6InNlY3VyaXR5LWFkbWluLWNvbnNvbGUiLCJzZXNzaW9uX3N0YXRlIjoiYmRjOGM0ZDgtYzUwNy00MDQ2LWE4NDctYmRlY2QxNDVmZTNiIiwiY2xpZW50X3Nlc3Npb24iOiI0OTI5YmRjNi0xOWFhLTQ3MDYtYTU1Mi1lOWI0MGFhMDg5ZTYiLCJhbGxvd2VkLW9yaWdpbnMiOltdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiYWRtaW4iLCJjcmVhdGUtcmVhbG0iXX0sInJlc291cmNlX2FjY2VzcyI6eyJtYXN0ZXItcmVhbG0iOnsicm9sZXMiOlsibWFuYWdlLWV2ZW50cyIsIm1hbmFnZS1jbGllbnRzIiwidmlldy1yZWFsbSIsInZpZXctZXZlbnRzIiwibWFuYWdlLWlkZW50aXR5LXByb3ZpZGVycyIsInZpZXctaWRlbnRpdHktcHJvdmlkZXJzIiwidmlldy11c2VycyIsInZpZXctY2xpZW50cyIsIm1hbmFnZS11c2VycyIsIm1hbmFnZS1yZWFsbSJdfX0sIm5hbWUiOiIiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhZG1pbiJ9.O7e8dkv0k-2HCjMdZFXIxLhypVyRPwIdrQsYTMwC1996wbsjIw1L3OjDSzJKXcx0U9YrVeRM4yMVlFg40uJDC-9IsKZ8nr5dl_da8SzgpAkempxpas3girST2U9uvY56m2Spp6-EFInvMSb6k4t1L49_Q7R2g0DOlKzxgQd87LY"; 
     String key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCHJUdDw1bPg/tZBY+kDDZZQnAp1mVr0CMyE+VzvJ+n2v6SHBdjjuWEw+LfLd69evg8ndr1RRPWZ1ryKgWS/NKTNqH+UhHkK9NToDucJI9Bi/scCpBps+/X/S7gZtcBMdfd4IB+LPCsP8v2RT/H9VjeCP4sWuqNwAMtCMyGr1Vw9wIDAQAB"; 
     String verifierKey = "-----BEGIN PUBLIC KEY-----\n" + key + "\n-----END PUBLIC KEY-----"; 
     SignatureVerifier verifier = new RsaVerifier(verifierKey); 
     System.out.println(JwtHelper.decodeAndVerify(token, verifier)); 
    } 
} 

Aktualizacja: jestem w stanie podpisać token poprawnie z HS256 (zweryfikowane z http://jwt.io/) za pomocą następującego kodu. Nie mogę jednak rozszyfrować tokena podpisanego przez PyJWT przy użyciu PyJWT. Interfejs jest naprawdę dziwny. Oto przykład (tajemnica jest taka sama, jak w powyższych przykładach):

some_token = jwt.encode(access_token_json, secret) 
# verified some_token to be valid with jwt.io 
# the code below does not validate the token correctly 
jwt.decode(some_token, key=secret) 

Aktualizacja 2: Działa

from jwt.algorithms import HMACAlgorithm, RSAAlgorithm 
access_token_json = jwt.decode(access_token, verify=False) 
algo = HMACAlgorithm(HMACAlgorithm.SHA256) 
shakey = algo.prepare_key(secret) 
testtoken = jwt.encode(access_token_json, key=shakey, algorithm='HS256') 
options={'verify_exp': False, # Skipping expiration date check 
     'verify_aud': False } # Skipping audience check 
print jwt.decode(testtoken, key=shakey, options=options) 

Jednak to nie

from jwt.algorithms import HMACAlgorithm, RSAAlgorithm 
algo = RSAAlgorithm(RSAAlgorithm.SHA256) 
shakey = algo.prepare_key(sshrsaSecret) 
options={'verify_exp': False, # Skipping expiration date check 
     'verify_aud': False } # Skipping audience check 
print jwt.decode(access_token, key=shakey, options=options) 
+2

Doskonała praca przy rozwiązywaniu własnego problemu. W celu uzyskania dalszych informacji zachęcamy do odpowiedzi na własne pytanie zamiast edytowania pola pytania http://stackoverflow.com/help/self-answer –

+0

W aktualizacji 2 wydaje się, że dekodowanie działa po użyciu testtoken, ale w tym, który nie działa, jest to kod dostępu próbujący zostać zdekodowany. – Efren

Odpowiedz

0

Umieszczę to tutaj dla następnej osoby takiej jak ja, która jej szuka.

Potrzebowałem:

  1. Klucz prywatny że mogę trzymać się za usługi (myślę AWS API bramka) i generuje tokeny JWT bezpiecznie i przekazać je do niższych usług.
  2. klucz Public że mogę dać żadnej z moich usług mikro/cokolwiek innego, co może potwierdzić, że token JWT jest ważny BEZ znając moje Prywatna kluczową

Setup:

# lets create a key to sign these tokens with 
    openssl genpkey -out mykey.pem -algorithm rsa -pkeyopt rsa_keygen_bits:2048 
    # lets generate a public key for it... 
    openssl rsa -in mykey.pem -out mykey.pub -pubout 
    # make another key so we can test that we cannot decode from it 
    openssl genpkey -out notmykey.pem -algorithm rsa -pkeyopt rsa_keygen_bits:2048 
    # this is really the key we would be using to try to check the signature 
    openssl rsa -in notmykey.pem -out notmykey.pub -pubout 

Kod:

import jwt 

from cryptography.hazmat.backends import default_backend 
from cryptography.hazmat.primitives import serialization 

# Load the key we created 
with open("mykey.pem", "rb") as key_file: 
    private_key = serialization.load_pem_private_key(
     key_file.read(), 
     password=None, 
     backend=default_backend() 
    ) 

# The data we're trying to pass along from place to place 
data = {'user_id': 1} 

# Lets create the JWT token -- this is a byte array, meant to be sent as an HTTP header 
jwt_token = jwt.encode(data, key=private_key, algorithm='RS256') 

print(f'data {data}') 
print(f'jwt_token {jwt_token}') 

# Load the public key to run another test... 
with open("mykey.pub", "rb") as key_file: 
    public_key = serialization.load_pem_public_key(
     key_file.read(), 
     backend=default_backend() 
    ) 

# This will prove that the derived public-from-private key is valid 
print(f'decoded with public key (internal): {jwt.decode(jwt_token, private_key.public_key())}') 
# This will prove that an external service consuming this JWT token can trust the token 
# because this is the only key it will have to validate the token. 
print(f'decoded with public key (external): {jwt.decode(jwt_token, public_key)}') 

# Lets load another public key to see if we can load the data successfuly 
with open("notmykey.pub", "rb") as key_file: 
    not_my_public_key = serialization.load_pem_public_key(
     key_file.read(), 
     backend=default_backend() 
    ) 

# THIS WILL FAIL!!!!!!!!!!!!!!!!!!!!!!! 
# Finally, this will not work and cause an exception 
print(f'decoded with another public key: {jwt.decode(jwt_token, not_my_public_key)}') 

Więcej informacji tutaj: https://gist.github.com/kingbuzzman/3912cc66896be0a06bf0eb23bb1e1999 - wraz z przykładem dokowania, jak szybko to uruchomić

Powiązane problemy