CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pyjwt

JSON Web Token implementation in Python with support for JWT, JWS, JWK, and JWKS

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

jwk-operations.mddocs/

JSON Web Keys (JWK)

JSON Web Key handling and cryptographic key abstraction supporting RSA, ECDSA, EdDSA, and symmetric keys. Provides key parsing, validation, algorithm detection, and integration with JWT/JWS operations for secure key management.

Capabilities

PyJWK - Individual Key Management

Represents a single JSON Web Key with automatic algorithm detection and cryptographic key parsing.

class PyJWK:
    def __init__(self, jwk_data: dict, algorithm: str = None):
        """
        Initialize PyJWK from JWK dictionary.

        Args:
            jwk_data (dict): JWK data according to RFC 7517
            algorithm (str): Force specific algorithm (optional)

        Raises:
            InvalidKeyError: Invalid key format or unsupported key type
            PyJWKError: General JWK processing error
            MissingCryptographyError: Cryptography library required
        """

    @staticmethod
    def from_dict(obj: dict, algorithm: str = None) -> 'PyJWK':
        """
        Create PyJWK from dictionary.

        Args:
            obj (dict): JWK dictionary
            algorithm (str): Optional algorithm override

        Returns:
            PyJWK: Initialized key object
        """

    @staticmethod  
    def from_json(data: str, algorithm: str = None) -> 'PyJWK':
        """
        Create PyJWK from JSON string.

        Args:
            data (str): JWK JSON string
            algorithm (str): Optional algorithm override

        Returns:
            PyJWK: Initialized key object
        """

    @property
    def key_type(self) -> str:
        """Key type (kty parameter): 'RSA', 'EC', 'oct', 'OKP'."""

    @property
    def key_id(self) -> str:
        """Key ID (kid parameter) for key identification."""

    @property
    def public_key_use(self) -> str:
        """Public key use (use parameter): 'sig', 'enc', or None."""

    @property
    def algorithm_name(self) -> str:
        """Detected or assigned algorithm name."""

    @property
    def Algorithm(self):
        """Algorithm implementation object."""

    @property
    def key(self):
        """Underlying cryptographic key object."""

Usage examples:

import jwt
from jwt import PyJWK

# RSA public key from JWK
rsa_jwk_data = {
    "kty": "RSA",
    "kid": "rsa-key-1",
    "use": "sig",
    "n": "base64url-encoded-modulus",
    "e": "AQAB"
}

jwk = PyJWK.from_dict(rsa_jwk_data)
print(f"Key type: {jwk.key_type}")
print(f"Key ID: {jwk.key_id}")
print(f"Algorithm: {jwk.algorithm_name}")

# Use with JWT decoding
token = "eyJ..."
payload = jwt.decode(token, jwk.key, algorithms=[jwk.algorithm_name])

# ECDSA key with explicit algorithm
ec_jwk_data = {
    "kty": "EC",
    "kid": "ec-key-1",
    "crv": "P-256",
    "x": "base64url-encoded-x",
    "y": "base64url-encoded-y"
}

jwk = PyJWK.from_dict(ec_jwk_data, algorithm="ES256")

# Symmetric key (HMAC)
oct_jwk_data = {
    "kty": "oct",
    "kid": "hmac-key-1",
    "k": "base64url-encoded-secret"
}

jwk = PyJWK.from_dict(oct_jwk_data)  # Defaults to HS256

PyJWKSet - Key Set Management

Manages collections of JSON Web Keys with key lookup capabilities and validation.

class PyJWKSet:
    def __init__(self, keys: list):
        """
        Initialize JWK Set from list of JWK dictionaries.

        Args:
            keys (list): List of JWK dictionaries

        Raises:
            PyJWKSetError: Invalid JWK Set or no usable keys
            MissingCryptographyError: Required for asymmetric keys
        """

    @staticmethod
    def from_dict(obj: dict) -> 'PyJWKSet':
        """
        Create PyJWKSet from JWKS dictionary.

        Args:
            obj (dict): JWKS dictionary with 'keys' array

        Returns:
            PyJWKSet: Initialized key set
        """

    @staticmethod
    def from_json(data: str) -> 'PyJWKSet':
        """
        Create PyJWKSet from JWKS JSON string.

        Args:
            data (str): JWKS JSON string

        Returns:
            PyJWKSet: Initialized key set
        """

    def __getitem__(self, kid: str) -> PyJWK:
        """
        Get key by key ID.

        Args:
            kid (str): Key ID to look up

        Returns:
            PyJWK: Matching key

        Raises:
            KeyError: No key found with given ID
        """

    @property
    def keys(self) -> list:
        """List of PyJWK objects in this set."""

Usage examples:

import jwt
from jwt import PyJWKSet

# JWKS from dictionary
jwks_data = {
    "keys": [
        {
            "kty": "RSA",
            "kid": "rsa-key-1",
            "use": "sig",
            "n": "modulus...",
            "e": "AQAB"
        },
        {
            "kty": "EC", 
            "kid": "ec-key-1",
            "crv": "P-256",
            "x": "x-coordinate...",
            "y": "y-coordinate..."
        }
    ]
}

jwk_set = PyJWKSet.from_dict(jwks_data)

# Get specific key by ID
key = jwk_set['rsa-key-1']
print(f"Found key: {key.algorithm_name}")

# Iterate through all keys
for jwk in jwk_set.keys:
    print(f"Key {jwk.key_id}: {jwk.algorithm_name}")

# From JSON string
jwks_json = '''{"keys": [...]}'''
jwk_set = PyJWKSet.from_json(jwks_json)

# Use with JWT verification
def verify_jwt_with_jwks(token, jwk_set):
    # Extract key ID from token header
    unverified_header = jwt.get_unverified_header(token)
    kid = unverified_header.get('kid')
    
    if not kid:
        raise ValueError("Token missing key ID")
    
    # Get the appropriate key
    key = jwk_set[kid]
    
    # Verify token
    return jwt.decode(token, key.key, algorithms=[key.algorithm_name])

Key Type Support

PyJWK supports all standard JSON Web Key types:

RSA Keys (kty: "RSA")

# RSA public key
rsa_public_jwk = {
    "kty": "RSA",
    "kid": "rsa-pub-1",
    "use": "sig",
    "n": "modulus-base64url",     # Required
    "e": "exponent-base64url"    # Required
}

# RSA private key (includes all public parameters plus private)
rsa_private_jwk = {
    "kty": "RSA",
    "kid": "rsa-priv-1", 
    "use": "sig",
    "n": "modulus-base64url",
    "e": "exponent-base64url",
    "d": "private-exponent-base64url",  # Private key
    # Optional CRT parameters: p, q, dp, dq, qi
}

Elliptic Curve Keys (kty: "EC")

# ECDSA P-256 public key
ec_p256_jwk = {
    "kty": "EC",
    "kid": "ec-p256-1",
    "crv": "P-256",              # Curve: P-256, P-384, P-521, secp256k1
    "x": "x-coordinate-base64url",
    "y": "y-coordinate-base64url"
}

# ECDSA private key (includes 'd' parameter)
ec_private_jwk = {
    "kty": "EC",
    "kid": "ec-priv-1",
    "crv": "P-256",
    "x": "x-coordinate-base64url",
    "y": "y-coordinate-base64url", 
    "d": "private-key-base64url"  # Private key
}

Symmetric Keys (kty: "oct")

# HMAC symmetric key
oct_jwk = {
    "kty": "oct",
    "kid": "hmac-1",
    "k": "symmetric-key-base64url"  # The symmetric key material
}

EdDSA Keys (kty: "OKP")

# Ed25519 public key
ed25519_jwk = {
    "kty": "OKP",
    "kid": "ed25519-1",
    "crv": "Ed25519",            # Or "Ed448"
    "x": "public-key-base64url"
}

# Ed25519 private key
ed25519_private_jwk = {
    "kty": "OKP", 
    "kid": "ed25519-priv-1",
    "crv": "Ed25519",
    "x": "public-key-base64url",
    "d": "private-key-base64url"  # Private key
}

Algorithm Detection

PyJWK automatically detects appropriate algorithms based on key type and curve:

Key TypeCurve/SizeDefault Algorithm
RSAAnyRS256
ECP-256ES256
ECP-384ES384
ECP-521ES512
ECsecp256k1ES256K
octAnyHS256
OKPEd25519EdDSA
OKPEd448EdDSA
# Algorithm detection examples
rsa_jwk = PyJWK.from_dict({"kty": "RSA", "n": "...", "e": "AQAB"})
print(rsa_jwk.algorithm_name)  # "RS256"

ec_jwk = PyJWK.from_dict({"kty": "EC", "crv": "P-384", "x": "...", "y": "..."})
print(ec_jwk.algorithm_name)  # "ES384"

# Override automatic detection
forced_jwk = PyJWK.from_dict(rsa_jwk_data, algorithm="PS256")
print(forced_jwk.algorithm_name)  # "PS256"

Error Handling

Common JWK-related exceptions:

import jwt
from jwt.exceptions import PyJWKError, InvalidKeyError, MissingCryptographyError

try:
    jwk = PyJWK.from_dict(invalid_jwk_data)
except InvalidKeyError as e:
    print(f"Invalid key format: {e}")
except MissingCryptographyError as e:
    print(f"Install cryptography: {e}")
except PyJWKError as e:
    print(f"JWK error: {e}")

try:
    key = jwk_set['nonexistent-kid']
except KeyError as e:
    print(f"Key not found: {e}")

Install with Tessl CLI

npx tessl i tessl/pypi-pyjwt

docs

algorithm-management.md

index.md

jwk-operations.md

jwks-client.md

jws-operations.md

jwt-operations.md

tile.json