Skip to content

Instantly share code, notes, and snippets.

@kingbuzzman
Last active February 29, 2024 15:59
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save kingbuzzman/3912cc66896be0a06bf0eb23bb1e1999 to your computer and use it in GitHub Desktop.
Save kingbuzzman/3912cc66896be0a06bf0eb23bb1e1999 to your computer and use it in GitHub Desktop.
JWT test with private/public keys
import jwt
import time
import datetime
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
try:
print(f'decoded with another public key: {jwt.decode(jwt_token, not_my_public_key)}')
raise Exception('Something went wrong.. VERY wrong')
except jwt.exceptions.DecodeError as e:
print(f'YUP, failed: {e}')
# Lets put a time limit on the token -- just incase
data = {'user_id': 1, 'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=5)}
jwt_token = jwt.encode(data, key=private_key, algorithm='RS256')
print('sleeping for 3 seconds... (ensure that we can still read the token)')
time.sleep(3)
# Token should still be able to be read
print(f'decoded with public key (external): {jwt.decode(jwt_token, public_key)}')
print('sleeping for 3 seconds... (waiting for the token to expire)')
time.sleep(3)
# This should crash because the token is expired
try:
print(f'decoded with public key (external): {jwt.decode(jwt_token, public_key)}')
raise Exception('Something went wrong.. VERY wrong')
except jwt.exceptions.ExpiredSignatureError as e:
print(f'YUP, failed: {e}')
@kingbuzzman
Copy link
Author

To run this:

  1. docker
  2. locally you need openssl
  3. desire to learn

The following script you can run EXACTLY as written, copy and paste directly into your terminal it will setup all dependencies and execute the code above. DON'T FORGET TO COPY THE (...) THEY ARE EXTREMELY IMPORTANT

( \
  cd /tmp; `: lets go to /tmp so we dont pollute your file system` \
  mkdir -p testinggrounds; `: again -- no pollution` \
  cd testinggrounds; \
  curl -s https://gist.githubusercontent.com/kingbuzzman/3912cc66896be0a06bf0eb23bb1e1999/raw/jwt_test.py > jwt_test.py; `: download the script above` \
  openssl genpkey -out mykey.pem -algorithm rsa -pkeyopt rsa_keygen_bits:2048; `: lets create a key to sign these tokens with` \
  openssl rsa -in mykey.pem -out mykey.pub -pubout; `: lets generate a public key for it...` \
  openssl genpkey -out notmykey.pem -algorithm rsa -pkeyopt rsa_keygen_bits:2048; `: make another key so we can test that we cannot decode from it` \
  openssl rsa -in notmykey.pem -out notmykey.pub -pubout; `: this is really the key we would be using to try to check the signature` \
  docker run --rm -it -v $(pwd):/code python:3.6 sh -c "cd code; pip install pyjwt pycrypto cryptography; python jwt_test.py" `: lets run the tests....` \
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment