# ZKAC Python API Reference Version 0.7.0. Cryptographic stack: **BBS+** on BLS12-381 (credentials), **X25519** + **ChaCha20-Poly1305** (transport), **Schnorr/Ristretto255** (identity), **BLAKE2b** (role IDs, signatures). ```python import zkac ``` ## Constants ### `MAX_BBS_AUTH_PROOF_BYTES` Upper bound on BBS+ proof size in an encrypted auth packet (256 KiB). Larger proofs are rejected. ## Transport identity (Ristretto255) ### `Keypair()` Generates a new random keypair (long-term identity). - `public_key() -> PublicKey` — raises `ValueError` if consumed by `Node(...)` - `sign(msg: bytes) -> bytes` — 64-byte Schnorr signature over `msg` ### `PublicKey` - `to_bytes() -> bytes` — 32 bytes - `from_bytes(bytes) -> PublicKey` - `verify(msg: bytes, signature: bytes) -> bool` — verify a 64-byte Schnorr signature - Equality, hash, `repr` supported ## BBS+ credentials ### `role_id(name: str) -> bytes` 32-byte opaque role id from a human-readable name. ### `BbsIssuer()` New random issuer. `from_secret_key(bytes)` restores from 32-byte secret. - `public_key() -> BbsPublicKey` - `secret_key_bytes() -> bytes` (confidential) - `issue_blind(commitment_with_proof, role_id, epoch) -> bytes` — `role_id` must be 32 bytes ### `BbsPublicKey` - `to_bytes() / from_bytes` ### `prepare_blind_request() -> BlindRequest` - `commitment_with_proof()`, `member_secret()`, `prover_blind()` — all return `bytes` ### `Credential.finalize(blind_sig, member_secret, prover_blind, role_id, epoch, pk) -> Credential` `role_id` and `prover_blind` must be 32 bytes. - `present(nonce) -> bytes` - `role_id() -> bytes`, `epoch() -> int` ## Server registry ### `RoleRegistry` - `register_role(role_id, pk, epoch)` — `role_id` 32 bytes - `set_epoch(role_id, epoch)` - `verify_presentation(role_id, proof_bytes, nonce) -> bool` - `has_role(role_id) -> bool` ## Node and session ### `PendingConnect` Opaque handle returned from `connect()`; passed once into a `complete_*` method (then consumed). ### `Node(keypair)` — consumes `Keypair` - `public_key() -> PublicKey` - `connect() -> (PendingConnect, bytes)` — 32-byte init message - `accept(init_msg) -> (Session, bytes)` — `init_msg` 32 bytes - `prove_identity(session) -> bytes` — server produces encrypted identity proof (Schnorr signature over transcript) - `complete_connect(pending, response_msg, identity_proof, expected_server_pk, credential) -> (Session, bytes)` — verifies server identity, then produces BBS+ auth packet (static `RoleRegistry`) - `complete_connect_anon(pending, response_msg, identity_proof, expected_server_pk) -> Session` — server identity only; no BBS+ auth packet - `complete_connect_managed(pending, response_msg, identity_proof, expected_server_pk, credential, registry_id) -> (Session, bytes)` — auth packet includes 32-byte registry id (client-managed registries) - `verify_auth(session, encrypted_auth, registry) -> bytes` — returns 32-byte `role_id` for static `RoleRegistry` - `verify_auth_managed(session, encrypted_auth, manager) -> (registry_id, role_id)` — for `RegistryManager` ### `Session` - `transcript_hash() -> bytes` — use as `nonce` for `Credential.present` - `encrypt(plaintext) -> bytes` - `decrypt(packet) -> bytes` ## Managed registries (optional) Server-side state for multiple registries and admin proofs lives in **`RegistryManager`**. Opaque **`RegistryState`** blobs are built and certified client-side, then **`registry_id(admin_issuer_pk)`** / **`admin_role_id()`** identify a registry and the fixed admin role. Methods on **`RegistryManager`** include `create` / `update` / `get` / `has_registry`, `verify_admin`, `verify_presentation(registry_id, role_id, …)`, and issuance-queue helpers (`queue_issuance_request`, `take_pending_requests`, `grant_credential`, `take_granted_credential`). **`RegistryState`** exposes `build`, `serialize` / `deserialize`, `registry_id`, `version`, `state_hash`, `certify`, and `verify_cert`. ## E2E issuance encryption (optional) **`IssuanceKeypair`** (with `encrypt` / `decrypt` on ephemeral keys) and module helpers **`encrypt_for_admin`** / **`decrypt_from_admin`** support encrypting blind-commitment material to an admin’s issuance public key. See `src/python.rs` for exact parameters. ## Typical flow 1. Issuer creates `BbsIssuer()`; server `register_role(role_id, issuer.public_key(), epoch)` (static registry), or use **`RegistryManager`** + certified **`RegistryState`** for multi-tenant / managed flows. 2. Member: `prepare_blind_request` → issuer `issue_blind` → `Credential.finalize`. 3. **Out-of-band:** client obtains server's `PublicKey` (static config, pinning, etc.). 4. Client: `connect` → server `accept` → server `prove_identity` → client `complete_connect` or `complete_connect_managed` (verifies server identity + sends BBS+ auth) → server `verify_auth` or `verify_auth_managed`. Use `complete_connect_anon` when no credential auth is needed. 5. Use `Session.encrypt` / `decrypt` for data. ## Errors Raises `ValueError` with descriptive messages for crypto failures, replay, identity verification, and bad inputs. ## Further reading [Security model and assumptions](./SECURITY.md) · [Changelog / breaking releases](../CHANGELOG.md)