"""Serialize / restore BBS+ member credentials and transport keys.""" from __future__ import annotations import base64 import json from pathlib import Path from typing import Any import zkac def save_json(path: Path, obj: Any) -> None: path.parent.mkdir(parents=True, exist_ok=True) path.write_text(json.dumps(obj, indent=2), encoding="utf-8") def load_json(path: Path) -> Any: return json.loads(path.read_text(encoding="utf-8")) def member_payload( blind_sig: bytes, req: zkac.BlindRequest, role_id: bytes, epoch: int, issuer_pk: zkac.BbsPublicKey, ) -> dict[str, Any]: return { "role_id_hex": role_id.hex(), "epoch": epoch, "blind_sig_b64": base64.b64encode(blind_sig).decode(), "member_secret_b64": base64.b64encode(req.member_secret()).decode(), "prover_blind_b64": base64.b64encode(req.prover_blind()).decode(), "issuer_public_key_b64": base64.b64encode(issuer_pk.to_bytes()).decode(), } def load_member_credential(data: dict[str, Any]) -> zkac.Credential: pk = zkac.BbsPublicKey.from_bytes(base64.b64decode(data["issuer_public_key_b64"])) rid = bytes.fromhex(data["role_id_hex"]) return zkac.Credential.finalize( base64.b64decode(data["blind_sig_b64"]), base64.b64decode(data["member_secret_b64"]), base64.b64decode(data["prover_blind_b64"]), rid, int(data["epoch"]), pk, ) def save_transport_keypair(path: Path, kp: zkac.Keypair) -> None: save_json( path, { "secret_key_b64": base64.b64encode(kp.secret_key_bytes()).decode(), "public_key_b64": base64.b64encode(kp.public_key().to_bytes()).decode(), }, ) def load_transport_keypair(path: Path) -> zkac.Keypair: t = load_json(path) return zkac.Keypair.from_secret_key(base64.b64decode(t["secret_key_b64"])) def save_server_transport(path: Path, kp: zkac.Keypair) -> None: save_json( path, { "server_secret_key_b64": base64.b64encode(kp.secret_key_bytes()).decode(), "server_public_key_b64": base64.b64encode(kp.public_key().to_bytes()).decode(), }, ) def load_server_public_key(path: Path) -> zkac.PublicKey: t = load_json(path) return zkac.PublicKey.from_bytes(base64.b64decode(t["server_public_key_b64"])) def load_server_keypair(path: Path) -> zkac.Keypair: t = load_json(path) return zkac.Keypair.from_secret_key(base64.b64decode(t["server_secret_key_b64"]))