v bump
This commit is contained in:
parent
2ede94fa2f
commit
44fa5e6a2f
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -748,7 +748,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zkac"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"blake2",
|
||||
"chacha20poly1305",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "zkac"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
edition = "2021"
|
||||
description = "Zero-Knowledge Access Control: BBS+ anonymous credentials (BLS12-381) with encrypted transport (X25519/ChaCha20-Poly1305)"
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "zkac-node"
|
||||
version = "0.2.1"
|
||||
version = "0.6.0"
|
||||
requires-python = ">=3.10"
|
||||
dependencies = ["zkac"]
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
Metadata-Version: 2.4
|
||||
Name: zkac-node
|
||||
Version: 0.2.1
|
||||
Version: 0.6.0
|
||||
Requires-Python: >=3.10
|
||||
Requires-Dist: zkac
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# ZKAC Python API Reference
|
||||
|
||||
Version 0.5.1. Cryptographic stack: **BBS+** on BLS12-381 (credentials), **X25519** + **ChaCha20-Poly1305** (transport), **Schnorr/Ristretto255** (identity), **BLAKE2b** (role IDs, signatures).
|
||||
Version 0.6.0. Cryptographic stack: **BBS+** on BLS12-381 (credentials), **X25519** + **ChaCha20-Poly1305** (transport), **Schnorr/Ristretto255** (identity), **BLAKE2b** (role IDs, signatures).
|
||||
|
||||
```python
|
||||
import zkac
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# Security model (ZKAC 0.5.1)
|
||||
# Security model (ZKAC 0.6.0)
|
||||
|
||||
This document summarizes the direct peer-to-peer grant model, with transcript-bound BBS+ authorization (Option C).
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ build-backend = "maturin"
|
||||
|
||||
[project]
|
||||
name = "zkac"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
description = "Zero-Knowledge Access Control: BBS+ anonymous credentials with encrypted transport"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
|
||||
@ -4,7 +4,7 @@ ZKAC — Zero-Knowledge Access Control
|
||||
BBS+ anonymous credentials (BLS12-381) with encrypted transport (Ristretto255 / X25519).
|
||||
"""
|
||||
|
||||
__version__ = "0.5.1"
|
||||
__version__ = "0.6.0"
|
||||
|
||||
from zkac._zkac import (
|
||||
MAX_BBS_AUTH_PROOF_BYTES,
|
||||
|
||||
@ -1,246 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
E2E smoke + timing: one server, clients A (admin) and B (recipient).
|
||||
|
||||
1. A creates a registry with 3 roles
|
||||
2. A posts one or more grants to B (same role ``beta``)
|
||||
3. Time B's mailbox fetch and permission-style checks (same phases as
|
||||
``zkac-node credentials list B --server …``: local creds, list_pending, has_credential)
|
||||
|
||||
Default (no args): one grant, asserts one pending ``beta`` grant.
|
||||
|
||||
Scaling: ``--sizes 2,5,25,50`` runs a fresh server + pool for each size (all grants
|
||||
to B), prints a timing table (``list_pending`` = tags + PIR full-row decode per match).
|
||||
|
||||
Run from repo root, e.g.:
|
||||
|
||||
uv run python scripts/e2e_two_clients_timing.py
|
||||
uv run python scripts/e2e_two_clients_timing.py --sizes 2,5,25,50
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import os
|
||||
import socket
|
||||
import sys
|
||||
import tempfile
|
||||
import threading
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
sys.path.insert(0, str(ROOT / "python"))
|
||||
sys.path.insert(0, str(ROOT / "cli"))
|
||||
|
||||
|
||||
def _free_port() -> int:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.bind(("127.0.0.1", 0))
|
||||
_, port = s.getsockname()
|
||||
s.close()
|
||||
return port
|
||||
|
||||
|
||||
def _run_scaled_sizes(sizes: list[int]) -> int:
|
||||
from zkac_cli import client, store
|
||||
from zkac_cli.server import _ServerStore, serve
|
||||
|
||||
def log(msg: str) -> None:
|
||||
print(msg, flush=True)
|
||||
|
||||
rows: list[tuple[int, float, float, float, float, float, float]] = []
|
||||
|
||||
for n in sizes:
|
||||
td = tempfile.mkdtemp(prefix="zkac-e2e-")
|
||||
os.environ["ZKAC_HOME"] = td
|
||||
port = _free_port()
|
||||
server = f"127.0.0.1:{port}"
|
||||
server_dd = Path(td) / "srv"
|
||||
server_dd.mkdir(parents=True)
|
||||
|
||||
ss = _ServerStore(server_dd)
|
||||
kp = ss.load_or_create_keypair()
|
||||
pk_b64 = base64.b64encode(kp.public_key().to_bytes()).decode()
|
||||
|
||||
store.create_user("A")
|
||||
store.create_user("B")
|
||||
store.pin_server("A", server, pk_b64)
|
||||
store.pin_server("B", server, pk_b64)
|
||||
|
||||
t_srv = threading.Thread(
|
||||
target=lambda: serve(str(server_dd), "127.0.0.1", port),
|
||||
daemon=True,
|
||||
)
|
||||
t_srv.start()
|
||||
time.sleep(0.25)
|
||||
|
||||
t_setup0 = time.perf_counter()
|
||||
rid = client.create_registry("A", server, ["alpha", "beta", "gamma"])
|
||||
t_after_create = time.perf_counter()
|
||||
b_pk = store.load_identity("B")["issuance_pk"].hex()
|
||||
for _ in range(n):
|
||||
client.grant("A", server, rid, "beta", b_pk)
|
||||
t_gr1 = time.perf_counter()
|
||||
|
||||
t_loc0 = time.perf_counter()
|
||||
local_creds = store.list_credentials("B")
|
||||
t_loc1 = time.perf_counter()
|
||||
|
||||
t_mail0 = time.perf_counter()
|
||||
pending = client.list_pending("B", server)
|
||||
t_mail1 = time.perf_counter()
|
||||
|
||||
t_perm0 = time.perf_counter()
|
||||
for g in pending:
|
||||
r = g.get("registry_id")
|
||||
role = g.get("role_name")
|
||||
if r not in (None, "?") and role not in (None, "?"):
|
||||
store.has_credential("B", r, role)
|
||||
t_perm1 = time.perf_counter()
|
||||
|
||||
create_ms = (t_after_create - t_setup0) * 1000
|
||||
grant_ms = (t_gr1 - t_after_create) * 1000
|
||||
local_ms = (t_loc1 - t_loc0) * 1000
|
||||
mail_ms = (t_mail1 - t_mail0) * 1000
|
||||
perm_ms = (t_perm1 - t_perm0) * 1000
|
||||
total_ms = (t_perm1 - t_loc0) * 1000
|
||||
|
||||
rows.append((n, create_ms, grant_ms, local_ms, mail_ms, perm_ms, total_ms))
|
||||
|
||||
log(
|
||||
f"n={n}: create_registry={create_ms:.0f} ms N×grant={grant_ms:.0f} ms "
|
||||
f"list_pending={mail_ms:.0f} ms pending={len(pending)} ZKAC_HOME={td}"
|
||||
)
|
||||
if len(pending) != n:
|
||||
print(f"ERROR: expected {n} pending, got {len(pending)}", flush=True)
|
||||
return 1
|
||||
for p in pending:
|
||||
if p.get("role_name") != "beta" or p.get("registry_id") != rid:
|
||||
print(f"ERROR: bad pending row {p!r}", flush=True)
|
||||
return 1
|
||||
|
||||
print()
|
||||
print(
|
||||
"pool_n | create_registry (ms) | N×grant (ms) | list_local (ms) | "
|
||||
"list_pending mailbox (ms) | has_cred (ms) | cred_list_total (ms)"
|
||||
)
|
||||
print("-" * 120)
|
||||
for n, create_ms, grant_ms, local_ms, mail_ms, perm_ms, total_ms in rows:
|
||||
print(
|
||||
f"{n:6d} | {create_ms:20.1f} | {grant_ms:12.1f} | {local_ms:15.3f} | "
|
||||
f"{mail_ms:25.1f} | {perm_ms:12.3f} | {total_ms:20.1f}"
|
||||
)
|
||||
print("OK")
|
||||
return 0
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description="ZKAC e2e timing (mailbox / credentials list)")
|
||||
parser.add_argument(
|
||||
"--sizes",
|
||||
default=None,
|
||||
metavar="N,N,...",
|
||||
help="comma-separated pool sizes (each run: fresh server, N grants to B, then list_pending)",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.sizes is not None:
|
||||
sizes = [int(x.strip()) for x in args.sizes.split(",") if x.strip()]
|
||||
if not sizes or any(x < 1 for x in sizes):
|
||||
print("error: --sizes must be positive integers", file=sys.stderr)
|
||||
return 2
|
||||
return _run_scaled_sizes(sizes)
|
||||
|
||||
from zkac_cli import client, store
|
||||
from zkac_cli.server import _ServerStore, serve
|
||||
|
||||
def log(msg: str) -> None:
|
||||
print(msg, flush=True)
|
||||
|
||||
td = tempfile.mkdtemp(prefix="zkac-e2e-")
|
||||
os.environ["ZKAC_HOME"] = td
|
||||
port = _free_port()
|
||||
server = f"127.0.0.1:{port}"
|
||||
server_dd = Path(td) / "srv"
|
||||
server_dd.mkdir(parents=True)
|
||||
|
||||
ss = _ServerStore(server_dd)
|
||||
kp = ss.load_or_create_keypair()
|
||||
pk_b64 = base64.b64encode(kp.public_key().to_bytes()).decode()
|
||||
|
||||
store.create_user("A")
|
||||
store.create_user("B")
|
||||
store.pin_server("A", server, pk_b64)
|
||||
store.pin_server("B", server, pk_b64)
|
||||
|
||||
t_srv = threading.Thread(
|
||||
target=lambda: serve(str(server_dd), "127.0.0.1", port),
|
||||
daemon=True,
|
||||
)
|
||||
t_srv.start()
|
||||
time.sleep(0.25)
|
||||
log("server thread up")
|
||||
|
||||
t0 = time.perf_counter()
|
||||
rid = client.create_registry("A", server, ["alpha", "beta", "gamma"])
|
||||
t_create = time.perf_counter()
|
||||
log(f"registry created ({(t_create - t0) * 1000:.0f} ms)")
|
||||
|
||||
b_pk = store.load_identity("B")["issuance_pk"].hex()
|
||||
client.grant("A", server, rid, "beta", b_pk)
|
||||
t_grant = time.perf_counter()
|
||||
log(f"grant posted ({(t_grant - t_create) * 1000:.0f} ms)")
|
||||
|
||||
log("B mailbox + permission-style checks (same work as `credentials list`) …")
|
||||
t_loc0 = time.perf_counter()
|
||||
local_creds = store.list_credentials("B")
|
||||
t_loc1 = time.perf_counter()
|
||||
|
||||
t_mail0 = time.perf_counter()
|
||||
pending = client.list_pending("B", server)
|
||||
t_mail1 = time.perf_counter()
|
||||
|
||||
t_perm0 = time.perf_counter()
|
||||
for g in pending:
|
||||
r = g.get("registry_id")
|
||||
role = g.get("role_name")
|
||||
if r not in (None, "?") and role not in (None, "?"):
|
||||
store.has_credential("B", r, role)
|
||||
t_perm1 = time.perf_counter()
|
||||
|
||||
log(f"ZKAC_HOME={td}")
|
||||
log(f"server={server} registry={rid[:24]}…")
|
||||
print(f"create_registry: {(t_create - t0) * 1000:.1f} ms")
|
||||
print(f"grant: {(t_grant - t_create) * 1000:.1f} ms")
|
||||
print(
|
||||
f"list_local_creds(B): {(t_loc1 - t_loc0) * 1000:.3f} ms ({len(local_creds)} on disk)"
|
||||
)
|
||||
print(
|
||||
f"list_pending(mailbox): {(t_mail1 - t_mail0) * 1000:.1f} ms "
|
||||
f"({len(pending)} match(es); tags + PIR row + decrypt)"
|
||||
)
|
||||
print(
|
||||
f"has_credential checks: {(t_perm1 - t_perm0) * 1000:.3f} ms "
|
||||
f"({len(pending)} grant(s))"
|
||||
)
|
||||
print(
|
||||
f"credentials_list_total: {(t_perm1 - t_loc0) * 1000:.1f} ms "
|
||||
"(local + mailbox + permission flags)"
|
||||
)
|
||||
for p in pending:
|
||||
print(
|
||||
f" pending: registry={p.get('registry_id', '?')[:16]}… "
|
||||
f"role={p.get('role_name')} idx={p.get('pool_index')}"
|
||||
)
|
||||
|
||||
assert len(pending) == 1, pending
|
||||
assert pending[0].get("role_name") == "beta"
|
||||
assert pending[0].get("registry_id") == rid
|
||||
print("OK")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
4
uv.lock
generated
4
uv.lock
generated
@ -1918,7 +1918,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "zkac"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "ipykernel" },
|
||||
@ -1964,7 +1964,7 @@ dev = [
|
||||
|
||||
[[package]]
|
||||
name = "zkac-node"
|
||||
version = "0.2.1"
|
||||
version = "0.6.0"
|
||||
source = { editable = "cli" }
|
||||
dependencies = [
|
||||
{ name = "zkac" },
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user