Cheatsheet#
This cheatsheet provides quick reference for the joserfc library, covering key management (JWK), signing (JWS), encryption (JWE), and tokens (JWT).
Installation#
pip install joserfc
JWK (JSON Web Key)#
Manage cryptographic keys.
Import Keys#
Import keys from various sources with jwk.import_key() method:
from joserfc import jwk
# Import generic JWK (dict) - auto-detects type
key = jwk.import_key({
"kty": "oct",
"k": "eW91ci1zZWNyZXQta2V5", # "your-secret-key" base64url encoded
"use": "sig"
})
# Import Symmetric Key (Oct) from string/bytes
oct_key = jwk.import_key("your-secret-key", "oct")
# Import RSA Key from PEM
pem_rsa = """-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlwwS7I3t2fSTawG1DcNF
Cu6NECHT3eVkr2lYXXD2hz4ILiIST2Q3/YpzNA9CrRZDseA24Ax/8UNZsMi8G1M8
Dpq1jUMKA4NrWOTrraZQmD9q4+rZLNx7M5NV8uojSoPWFYIBFwXgwzJYOZ8RVobJ
aDx6GWhWherJ1/xWrQS817mt0MwrDB9fm9RvfpBYqAKgfll6oL7MDuDTAY39yvi/
UkZGwD9b8ItdnssaiGBzqVG2inO1rUIAJ5WMK1P6K1MiSXdHRhgdSeDqMq07hFP3
IQWaOT6EWPOAEDS6E3eaHDkqNZTIrVmsVW2ScmttjRSXrmrk2U10ihiF79L9KKS/
nwIDAQAB
-----END PUBLIC KEY-----"""
rsa_key = jwk.import_key(pem_rsa, "RSA")
# Import EC Key from PEM
pem_ec = """-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEBdy4ZhgfXuBXLWgIAVfH+qqbZ4ne
opI4cgNaZ85tQM0rzghtBbXTnP9gxj49fhos3P34nBlIdShM9vaS0yQwcA==
-----END PUBLIC KEY-----"""
ec_key = jwk.import_key(pem_rsa, "EC")
# Import OKP (Ed25519/X25519) from PEM
pem_okp = """-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAqfwZCPkk+0u/GeXg10A3xt6JdNgqcLHqL3jKgBmL8Ow=
-----END PUBLIC KEY-----"""
okp_key = jwk.import_key(pem_okp, "OKP")
Import keys directly using the key type class:
from joserfc.jwk import OctKey, RSAKey, ECKey, OKPKey
oct_key = OctKey.import_key("your-secret-key")
# Import RSA Key from PEM
rsa_key = RSAKey.import_key(pem_rsa)
# Import EC Key from PEM
ec_key = ECKey.import_key(pem_ec)
# Import OKP (Ed25519/X25519) from PEM
okp_key = OKPKey.import_key(pem_okp)
Generate Keys#
from joserfc.jwk import KeyParameters
from joserfc.jwk import OctKey, RSAKey, ECKey, OKPKey
# Generate Oct (Symmetric) Key - size in bits
key = OctKey.generate_key(256) # 256 bits = 32 bytes
# Generate RSA Key
params: KeyParameters = {"use": "sig"}
rsa = RSAKey.generate_key(2048)
# Generate EC Key (P-256, P-384, P-521, secp256k1)
ec = ECKey.generate_key("P-256")
# Generate OKP Key (Ed25519, Ed448, X25519, X448)
okp = OKPKey.generate_key("Ed25519")
Use KeyParameters#
When importing a key, or generating a key, you can pass a KeyParameters
to set additional key properties.
from joserfc.jwk import KeyParameters
from joserfc.jwk import OctKey, RSAKey
params: KeyParameters = {"use": "sig"}
oct_key = OctKey.import_key("your-secret-key", params)
rsa_key = RSAKey.generate_key(2048, params)
Export Keys#
# To Dict (for JSON)
public_jwk = key.as_dict(private=False)
private_jwk = key.as_dict(private=True)
# To PEM (Asymmetric keys only)
pem_bytes = key.as_pem(private=True)
Key Sets (JWKS)#
from joserfc.jwk import KeySet
import json
# Import from file
with open("jwks.json") as f:
key_set = KeySet.import_key_set(json.load(f))
# Import from URL
# resp = requests.get("https://example.com/.well-known/jwks.json")
# key_set = KeySet.import_key_set(resp.json())
# Generate Key Set
key_set = KeySet.generate_key_set("EC", "P-256", count=4)
JWS (JSON Web Signature)#
Sign and verify data.
Compact Serialization (Most Common)#
from joserfc import jws
from joserfc.jwk import OctKey
key = OctKey.import_key("<your-secret-key>")
payload = "hello world"
# Sign
protected = {"alg": "HS256"}
token = jws.serialize_compact(protected, payload, key)
# 'eyJ...'
# Verify
obj = jws.deserialize_compact(token, key)
print(obj.payload) # b'hello world'
print(obj.protected) # {'alg': 'HS256'}
JSON Serialization (Multiple Signatures)#
from joserfc import jws
from joserfc.jwk import RSAKey, ECKey, KeySet
rsa_key = RSAKey.generate_key(2048)
ec_key = ECKey.generate_key("P-256")
# Create KeySet with both keys
private_key_set = KeySet([rsa_key, ec_key])
# Usually you would export the public keys and provide them to public
# through a URL such as https://example.com/jwks.json
public_jwks = private_key_set.as_dict(private=False)
payload = b"secure message"
# Sign with multiple keys
members = [
{"protected": {"alg": "RS256"}, "header": {"kid": rsa_key.kid}},
{"protected": {"alg": "ES256"}, "header": {"kid": ec_key.kid}}
]
# Use KeySet for private keys if multiple
value = jws.serialize_json(members, payload, private_key_set)
# Verify usually happens on the client side, clients can fetch the public keys from a URL
public_key_set = KeySet.import_key_set(public_jwks)
obj = jws.deserialize_json(value, public_key_set)
print(obj.payload) # b'secure message'
JWE (JSON Web Encryption)#
Encrypt and decrypt data.
Compact Encryption#
from joserfc import jwe
from joserfc.jwk import OctKey
# Shared secret key (must match algorithm requirements)
key = OctKey.generate_key(128) # 128 bits for A128KW
protected = {"alg": "A128KW", "enc": "A128GCM"}
plaintext = "secret message"
# Encrypt
jwe_token = jwe.encrypt_compact(protected, plaintext, key)
# Decrypt
obj = jwe.decrypt_compact(jwe_token, key)
print(obj.plaintext) # b'secret message'
JSON Encryption (Multiple Recipients)#
from joserfc import jwe
from joserfc.jwk import OctKey, RSAKey, KeySet
# General JSON Encryption builder
enc_obj = jwe.GeneralJSONEncryption({"enc": "A128GCM"}, b"payload")
# Add recipient 1
key1 = OctKey.generate_key(128)
key1.ensure_kid()
enc_obj.add_recipient({"alg": "A128KW", "kid": key1.kid})
# Add recipient 2
key2 = RSAKey.generate_key(2048)
# You use public key to encrypt and private key to decrypt
public_key = RSAKey.import_key(key2.public_key)
public_key.ensure_kid()
enc_obj.add_recipient({"alg": "RSA-OAEP", "kid": public_key.kid})
# Encrypt, we use public keys for recipients
data = jwe.encrypt_json(enc_obj, KeySet([key1, public_key]))
# Decrypt, we use private keys for decryption
obj = jwe.decrypt_json(data, KeySet([key1, key2]))
print(obj.plaintext) # b'payload'
JWT (JSON Web Token)#
Create and verify tokens with claims.
Encode (Create Token)#
from joserfc import jwt
from joserfc.jwk import OctKey
import datetime
key = OctKey.import_key("secret")
header = {"alg": "HS256"}
claims = {
"iss": "https://myapp.com",
"sub": "user123",
"exp": datetime.datetime.now(datetime.UTC) + datetime.timedelta(hours=1)
}
token = jwt.encode(header, claims, key)
Decode (Verify Token)#
# Verify and decode
# Note: decode verifies signature automatically
obj = jwt.decode(token, key)
print(obj.claims)
# {'iss': '...', 'sub': '...', 'exp': ...}
Validate Claims#
Use JWTClaimsRegistry to enforce claim rules (essential, values, format).
from joserfc.jwt import JWTClaimsRegistry
from joserfc.errors import ClaimError
# Define requirements
registry = JWTClaimsRegistry(
iss={"essential": True, "value": "https://myapp.com"},
aud={"essential": True, "values": ["my-api", "other-api"]},
role={"value": "admin"} # Custom claim check
)
token_obj = jwt.decode(token, key)
try:
registry.validate(token_obj.claims)
print("Claims valid")
except ClaimError as e:
print(f"Validation failed: {e}")
Nested JWT (JWE containing JWT)#
To create an encrypted JWT, use JWERegistry.
from joserfc import jwt, jwe
from joserfc.jwk import OctKey
key = OctKey.generate_key(128)
header = {"alg": "A128KW", "enc": "A128GCM"}
claims = {"secret": "data"}
# Pass JWERegistry to indicate JWE mode
registry = jwe.JWERegistry()
token = jwt.encode(header, claims, key, registry=registry)