Advanced Signing — Aquilia Documentation
Comprehensive guide and documentation for Advanced Signing in the Aquilia framework. View API reference, examples, and implementation patterns.
SIGNING SYSTEM / ADVANCED SIGNING Advanced Cryptographic Patterns Discover transparent key rotation, compact zlib payload compression, and custom signer backends for asymmetric cryptography. Key Rotation When rotation keys in production, old tokens must remain valid until they naturally expire. The RotatingSigner class solves this: it always signs using the first secret key in the provided secrets array, but attempts verification against all configured keys in order. class RotatingSigner: def __init__(self, secrets: Sequence[str | bytes], *, salt: str = "aquilia.signing", sep: str = ":", algorithm: str = "HS256", timestamp: bool = False) def sign(self, value: str) -> str: """Signs using the current (first) secret key.""" def unsign(self, signed_value: str, max_age: float | int | timedelta | None = None) -> str: """Tries each secret in order. Returns verified value or raises BadSignature.""" Structured Serialization (Dumps & Loads) The dumps and loads helper functions serialize dictionaries and objects to URL-safe strings. If compress=True is set, the engine compresses the payload via zlib and adds a header byte (\x01) to indicate compression. def dumps(obj: Any, *, secret: str | bytes | None = None, salt: str = "aquilia.signing.dumps", algorithm: str = "HS256", compress: bool = False, max_age: float | int | timedelta | None = None, timestamp: bool = True) -> str: """Serialise a JSON-compatible object to a signed URL-safe string.""" def loads(token: str, *, secret: str | bytes | None = None, salt: str = "aquilia.signing.dumps", algorithm: str = "HS256", max_age: float | int | timedelta | None = None) -> Any: """Verify and deserialise a token back to its original object format.""" Custom Backends & Asymmetric Signing You can extend the signature generation mechanism by implementing the abstract SignerBackend base class. This enables integration with cloud KMS, hardware security modules (HSM), or asymmetric keys. Aquilia features a built-in AsymmetricSignerBackend that supports RS256, ES256, and EdDSA signatures (requires pip install cryptography). class SignerBackend(ABC): @abstractmethod def sign(self, message: bytes) -> bytes: ... @abstractmethod def verify(self, message: bytes, signature: bytes) -> bool: ... @property @abstractmethod def algorithm(self) -> str: ... class AsymmetricSignerBackend(SignerBackend): def __init__(self, algorithm: str, *, private_key_pem: str | None = None, public_key_pem: str | None = None) Scenario Walkthroughs Scenario 1: Zero-Downtime Key Rotation Retire old keys without logging users out or invalidating outstanding links: from aquilia.signing import RotatingSigner # secrets[0] = active key for new signatures # secrets[1:] = backup keys used for verifying old tokens keys = ["new_master_key_2026_32_bytes_min", "old_retired_key_2025_32_bytes_min"] signer = RotatingSigner(secrets=keys) # New signatures use the active key new_token = signer.sign("hello") # Verification succeeds on old tokens signed with the old key old_token = "hello:oldSignatureHexOrB64" value = signer.unsign(old_token) # returns "hello" Scenario 2: Signed Payload Serialization with Compression Serialize complex nested lists or dictionaries, compressing them with zlib to keep cookies or URLs compact: from aquilia.signing import dumps, loads session_data = # Serialize, compress payload, and generate signature token = dumps( session_data, secret="my-super-secret-key-32-bytes-minimum", compress=True ) # Decode, verify, and decompress payload data = loads( token, secret="my-super-secret-key-32-bytes-minimum", max_age=3600 ) Scenario 3: Asymmetric Signature Verification Utilize ES256 (ECDSA P-256) asymmetric signatures for verification, where the public key is distributed but private key is held securely on the auth server: from aquilia.signing import Signer, AsymmetricSignerBackend private_pem = """-----BEGIN PRIVATE KEY----- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg... -----END PRIVATE KEY-----""" public_pem = """-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE... -----END PUBLIC KEY-----""" # 1. Create a backend with the ES256 algorithm backend = AsymmetricSignerBackend( algorithm="ES256", private_key_pem=private_pem, public_key_pem=public_pem ) # 2. Attach backend to the Signer signer = Signer(backend=backend) token = signer.sign("asymmetric_payload") Specialized Signers Fault System )
Go to Homepage