ZKAC/demo/setup_managed_demo.py
everbarry 15998edb51 .3
2026-04-16 01:02:55 +02:00

106 lines
4.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Generate credentials for the managed-registry demo.
Creates:
creds/managed_admin.json admin BBS+ issuer key + admin credential + issuance keypair
creds/managed_registry.json serialized registry state + cert (analyst + operator roles)
creds/transport.json server transport key (created if not already present)
Users request credentials through the server at runtime (E2E-encrypted issuance).
"""
from __future__ import annotations
import argparse
import base64
import json
from pathlib import Path
import zkac
ROLES = ("analyst", "operator")
def main() -> None:
ap = argparse.ArgumentParser(description="Generate managed-registry demo files.")
ap.add_argument(
"--output-dir",
type=Path,
default=Path(__file__).resolve().parent / "creds",
)
args = ap.parse_args()
out: Path = args.output_dir
out.mkdir(parents=True, exist_ok=True)
# Admin BBS+ issuer (signs credentials AND certifies registry state)
admin_issuer = zkac.BbsIssuer()
admin_pk = admin_issuer.public_key()
admin_rid = zkac.admin_role_id()
# Self-issue admin credential
req = zkac.prepare_blind_request()
sig = admin_issuer.issue_blind(req.commitment_with_proof(), admin_rid, 0)
admin_cred = zkac.Credential.finalize(
sig, req.member_secret(), req.prover_blind(), admin_rid, 0, admin_pk
)
# X25519 issuance keypair for E2E-encrypted credential requests
issuance_kp = zkac.IssuanceKeypair()
# Build registry state with roles (admin is also the issuer for all roles)
role_entries = []
for name in ROLES:
role_entries.append((zkac.role_id(name), admin_pk, 1))
state = zkac.RegistryState.build(
admin_pk, issuance_kp.public_key_bytes(), 1, b"\x00" * 32, role_entries
)
state_bytes = state.serialize()
state_cert = state.certify(admin_cred)
registry_id = state.registry_id()
# Save admin material
admin_payload = {
"admin_issuer_secret_b64": base64.b64encode(admin_issuer.secret_key_bytes()).decode(),
"admin_issuer_public_key_b64": base64.b64encode(admin_pk.to_bytes()).decode(),
"admin_member_secret_b64": base64.b64encode(req.member_secret()).decode(),
"admin_prover_blind_b64": base64.b64encode(req.prover_blind()).decode(),
"admin_blind_sig_b64": base64.b64encode(sig).decode(),
"issuance_secret_b64": base64.b64encode(issuance_kp.secret_bytes()).decode(),
"issuance_public_key_b64": base64.b64encode(issuance_kp.public_key_bytes()).decode(),
"registry_id_hex": registry_id.hex(),
}
(out / "managed_admin.json").write_text(json.dumps(admin_payload, indent=2), encoding="utf-8")
# Save registry state + cert
reg_payload = {
"registry_id_hex": registry_id.hex(),
"state_bytes_b64": base64.b64encode(state_bytes).decode(),
"state_cert_b64": base64.b64encode(bytes(state_cert)).decode(),
"admin_issuer_public_key_b64": base64.b64encode(admin_pk.to_bytes()).decode(),
"issuance_public_key_b64": base64.b64encode(issuance_kp.public_key_bytes()).decode(),
"roles": list(ROLES),
}
(out / "managed_registry.json").write_text(json.dumps(reg_payload, indent=2), encoding="utf-8")
# Transport key (create if not present)
transport_path = out / "transport.json"
if not transport_path.is_file():
server_kp = zkac.Keypair()
transport_payload = {
"server_secret_key_b64": base64.b64encode(server_kp.secret_key_bytes()).decode(),
"server_public_key_b64": base64.b64encode(server_kp.public_key().to_bytes()).decode(),
}
transport_path.write_text(json.dumps(transport_payload, indent=2), encoding="utf-8")
print(f"Wrote managed-registry demo files to {out}")
print(f"Registry ID: {registry_id.hex()}")
print(f"Roles: {', '.join(ROLES)}")
print(f"\nAdmin can issue credentials for these roles through the server.")
print(f"Users request credentials via E2E-encrypted issuance relay.")
if __name__ == "__main__":
main()