micropython-lib/python-ecosys/pyjwt/jwt.py

80 wiersze
2.1 KiB
Python

import binascii
import hashlib
import hmac
import json
from time import time
def _to_b64url(data):
return (
binascii.b2a_base64(data)
.rstrip(b"\n")
.rstrip(b"=")
.replace(b"+", b"-")
.replace(b"/", b"_")
)
def _from_b64url(data):
return binascii.a2b_base64(data.replace(b"-", b"+").replace(b"_", b"/") + b"===")
class exceptions:
class PyJWTError(Exception):
pass
class InvalidTokenError(PyJWTError):
pass
class InvalidAlgorithmError(PyJWTError):
pass
class InvalidSignatureError(PyJWTError):
pass
class ExpiredSignatureError(PyJWTError):
pass
def encode(payload, key, algorithm="HS256"):
if algorithm != "HS256":
raise exceptions.InvalidAlgorithmError
if isinstance(key, str):
key = key.encode()
header = _to_b64url(json.dumps({"typ": "JWT", "alg": algorithm}).encode())
payload = _to_b64url(json.dumps(payload).encode())
signature = _to_b64url(hmac.new(key, header + b"." + payload, hashlib.sha256).digest())
return (header + b"." + payload + b"." + signature).decode()
def decode(token, key, algorithms=["HS256"]):
if "HS256" not in algorithms:
raise exceptions.InvalidAlgorithmError
parts = token.encode().split(b".")
if len(parts) != 3:
raise exceptions.InvalidTokenError
try:
header = json.loads(_from_b64url(parts[0]).decode())
payload = json.loads(_from_b64url(parts[1]).decode())
signature = _from_b64url(parts[2])
except Exception:
raise exceptions.InvalidTokenError
if header["alg"] not in algorithms or header["alg"] != "HS256":
raise exceptions.InvalidAlgorithmError
if isinstance(key, str):
key = key.encode()
calculated_signature = hmac.new(key, parts[0] + b"." + parts[1], hashlib.sha256).digest()
if signature != calculated_signature:
raise exceptions.InvalidSignatureError
if "exp" in payload:
if time() > payload["exp"]:
raise exceptions.ExpiredSignatureError
return payload