Generate mnemonic (BIP39)
Derive seed
PBKDF2-SHA512(mnemonic, salt, 2048)
Derive public key (PK)
pk = clamp(SHA-512(sk)[0:32]) · G
Sign transaction
sig = Ed25519.sign(tx_bytes, sk)
PQ-NIZK Proof
π = PQ-NIZK.prove(w, x)
stmt: ∃ s: Derive(s)=pk ∧ sk=SLIP10(s,path)
witness: (s, sk)
Phase 3: Validate & Confirm
Verify signature
Ed25519.verify(tx,sig,pk) → ✓
Verify sig → ✓
Verify π → ✓
AND
✓
Phase 2: Threshold Sign (2-of-3)
Node 1 & Node 2 active — Node 3 offline
Aggregate sig=Combine(σ1,σ2)
Batch PQ-NIZK Proof
π = BatchProve({seedi,pki})
stmt: ∀ i∈{1,2}: Derive(si)=pki
Verify sig Ed25519.verify → ✓
Verify sig → ✓
Verify π (batch) → ✓
AND
✓
Phase 1: Key Provisioning
Generate mnemonic (BIP39)
HSM ENCLAVE — FIPS 140-2
🔒 Keys never leave this boundary
Seed → SK (inside HSM)
PBKDF2 → seed → SLIP10() → sk
sk: [sealed]
PK (exportable)
pk = clamp(SHA-512(sk)) · G
pk: [exported]
Phase 2: Sign Transaction
HSM SIGNING
🔒 sk used internally, never exposed
sig = Ed25519.sign(tx_bytes, sk)
PQ-NIZK Proof (outside HSM)
π = PQ-NIZK.prove(w, x)
stmt: ∃ s: Derive(s)=pk ∧ sk=SLIP10(s,path)
witness: (s, sk)
Verify sig Ed25519.verify → ✓
Verify sig → ✓
Verify π → ✓
AND
✓