Xrite: Physical Key Ceremony
Multi-party threshold key generation for executive teams. K executives scan QR shares in a boardroom. XorIDA threshold splitting + TrustRegistry roster validation + HMAC-chained tamper-evident audit log. Produces legally admissible proof of ceremony completion. Zero plaintext persistence.
Executive Summary
Xrite orchestrates physical key generation ceremonies where K-of-N executives scan QR-encoded shares to reconstruct a root key. The ceremony produces a cryptographically verifiable, legally admissible audit trail.
Traditional key ceremonies require HSMs, notaries, and custody chains. Xrite replaces all of that with three functions: initCeremony() generates a 32-byte root key, splits it via XorIDA (threshold sharing over GF(2)), wraps shares in Xformat envelopes, and encodes them as printable QR codes. submitShare() validates participant identity against a TrustRegistry roster, rejects duplicates, and appends an HMAC-chained audit entry. completeCeremony() reconstructs the root key from K shares, verifies HMAC integrity, and returns the key material with a complete audit log.
The audit log is a tamper-evident chain. Every event (init, share submission, completion) is linked to the previous via HMAC-SHA256. Breaking any link invalidates the entire chain. Courts can verify authenticity by recomputing HMAC hashes without access to the root key.
Zero npm dependencies. Runs anywhere Web Crypto API is available. Dual ESM/CJS build. Integrates with existing TrustRegistry infrastructure or operates standalone with static rosters.
Developer Experience
Xrite provides structured error codes with actionable hints and field attribution to simplify debugging in high-stakes corporate environments.
Quick Start
import { initCeremony, submitShare, completeCeremony, } from '@private.me/keyceremony'; // 1. Initialize ceremony const init = await initCeremony( { n: 3, k: 2, label: 'Q1 2026 Root Key Rotation', registryEndpoint: 'https://trust.example.com/registry', location: 'NYC HQ Boardroom 4A', }, 'did:key:z6MkInitiator...', ); if (!init.ok) throw new Error(init.error); const { session, qrShares } = init.value; // Print qrShares as QR codes for participants // 2. Participants scan shares await submitShare(session.sessionId, qrShares[0], 'did:key:z6MkAlice...'); await submitShare(session.sessionId, qrShares[1], 'did:key:z6MkBob...'); // 3. Complete ceremony const result = await completeCeremony(session.sessionId); if (!result.ok) throw new Error(result.error); console.log(result.value.keyMaterial); // Uint8Array (32 bytes) console.log(result.value.auditLog); // CeremonyAuditEntry[] console.log(result.value.participants); // DIDs of all participants
Error Handling
Xrite uses Result<T, E> pattern with detailed error structures. Every error includes a machine-readable code, human-readable message, field attribution, and actionable hint.
const result = await submitShare(sessionId, qrData, participantDid); if (!result.ok) { console.error(result.error.code); // 'DUPLICATE_PARTICIPANT' console.error(result.error.message); // 'Participant already submitted a share' console.error(result.error.hint); // 'Check roster for duplicate DID' console.error(result.error.field); // 'participantDid' }
Error Categories
| Category | Example Codes | When |
|---|---|---|
| Config | INVALID_CONFIG, K_EXCEEDS_N | Ceremony initialization validation |
| Session | SESSION_NOT_FOUND, SESSION_TIMED_OUT | Session state transitions, timeout enforcement |
| Share | INVALID_SHARE, DUPLICATE_SHARE | QR decode, envelope validation, duplicate detection |
| Registry | PARTICIPANT_NOT_IN_ROSTER, REGISTRY_UNREACHABLE | TrustRegistry roster validation |
| Reconstruction | HMAC_MISMATCH, INSUFFICIENT_SHARES | XorIDA reconstruction, HMAC verification |
| Audit | HMAC_CHAIN_BROKEN | Audit log integrity verification |
The Problem
Corporate key ceremonies today require HSMs, notaries, physical custody chains, and manual audit logs. Each ceremony costs tens of thousands of dollars and produces paper trails that courts struggle to verify.
HSMs are expensive. Hardware Security Modules cost $5,000–$50,000 per unit. Enterprise key ceremonies require multiple HSMs for redundancy. Procurement, setup, and maintenance require specialized vendors and multi-month timelines.
Notaries add delay. Every key custody transfer requires a notary signature. Coordinating schedules across executives, legal, and notaries can take weeks. Notary fees add up across multiple ceremonies per year.
Paper audit logs are fragile. Manual logs are vulnerable to tampering, loss, and human error. Courts must trust that timestamps are accurate and that no entries were altered. Cryptographic verification is impossible.
Custody chains are complex. Tracking who held which key share, when, and where requires meticulous record-keeping. A single broken link invalidates the entire chain. Compliance officers spend hours reconstructing custody histories.
| Property | HSM + Notary | Manual Ceremony | Xrite |
|---|---|---|---|
| Initial cost | $50K+ equipment | $5K+ notary fees | $0 |
| Setup time | Weeks | Days | 5 minutes |
| Audit trail | Proprietary logs | Paper forms | HMAC-chained |
| Tamper evidence | Hardware seals | None | Cryptographic |
| Court admissibility | Vendor attestation | Notary affidavit | Hash chain |
| Threshold splitting | Proprietary | None | XorIDA |
| Roster validation | Manual check | Manual check | TrustRegistry |
| Recurring cost | HSM maintenance | Notary per ceremony | $0 |
The Old Way
The New Way
Real-World Use Cases
Six scenarios where Xrite replaces traditional HSM-based key ceremonies with threshold splitting and cryptographic audit trails.
CFO, CTO, and CISO scan shares to reconstruct the root CA signing key. 2-of-3 threshold ensures any two can rotate in an emergency. HMAC audit log satisfies SOX 404 compliance.
initCeremony({ k: 2, n: 3 })Hospital board members hold shares of the patient data encryption key. 3-of-5 threshold required for emergency access. TrustRegistry enforces board roster validation.
registryEndpoint + roster validationMilitary command shares for classified communications root key. Physical ceremony in SCIF. QR shares printed on air-gapped printer. HMAC chain stored in secure archive.
Air-gapped + HMAC auditManaging partners hold shares of client file encryption key. 2-of-4 threshold for emergency succession. Audit log provides malpractice insurance evidence.
Audit log + court admissibilityC-suite holds shares of backup encryption key. 3-of-6 threshold survives departure or unavailability of any three executives. Annual rotation ceremony.
K-of-N fault toleranceCompliance officer witnesses ceremony. HMAC chain provides cryptographic proof for auditors. Satisfies NIST 800-57 key management requirements.
HMAC chain + NIST complianceSolution Architecture
Five composable components. Each can be used independently or orchestrated through the ceremony workflow.
Ceremony Flow
Session States
PENDING --> IN_PROGRESS --> COMPLETE | | +---> TIMED_OUT | | +---> ABORTED (HMAC failure / deserialization failure)
Sessions start in PENDING state. First share submission transitions to IN_PROGRESS. Successful reconstruction transitions to COMPLETE. Timeout or integrity failure transitions to TIMED_OUT or ABORTED.
HMAC Audit Chain
Every ceremony event is recorded as a CeremonyAuditEntry with an HMAC-SHA256 chain hash linking it to the previous entry. The chain is seeded with a 64-character zero hash and a random 32-byte chain key.
interface CeremonyAuditEntry { timestamp: string; // ISO 8601 eventType: 'CEREMONY_INIT' | 'SHARE_SUBMITTED' | 'CEREMONY_COMPLETE' | ...; sessionId: string; // UUID actorDid?: string; // Participant or initiator DID shareId?: number; // Share index (1-based) previousHash: string; // HMAC-SHA256 of previous entry currentHash: string; // HMAC-SHA256 of this entry }
Courts verify authenticity by recomputing HMAC hashes from the audit log without access to the root key. If any entry was tampered with, hash recomputation will fail, invalidating the entire chain.
Integration
Xrite integrates with existing TrustRegistry infrastructure or operates standalone. Zero external dependencies beyond Web Crypto API.
Installation
npm install @private.me/keyceremony
TrustRegistry Integration
Xrite validates participant DIDs against a TrustRegistry roster. The registry can be a static list, an HTTP endpoint, or a did:web resolver.
const init = await initCeremony({ n: 3, k: 2, label: 'Q1 2026 Root Key', registryEndpoint: 'https://trust.example.com/registry', }, 'did:key:z6MkInitiator...'); // Registry must return JSON array of DIDs: // GET /registry → ["did:key:z6MkAlice...", "did:key:z6MkBob...", ...]
QR Code Generation
Xrite returns Base45-encoded strings. Use any QR library to generate printable codes. Recommended: qrcode npm package for server-side, qrcode.react for React.
import QRCode from 'qrcode'; const { qrShares } = init.value; for (let i = 0; i < qrShares.length; i++) { const png = await QRCode.toBuffer(qrShares[i], { errorCorrectionLevel: 'H', width: 300, }); fs.writeFileSync(`share-${i + 1}.png`, png); }
Audit Log Persistence
The audit log is returned as a JSON-serializable array. Store it in a database, append to a JSONL file, or submit to a blockchain for immutability.
const result = await completeCeremony(sessionId); if (!result.ok) throw new Error(result.error); const { auditLog, keyMaterial } = result.value; // Store audit log in database await db.ceremonies.insert({ sessionId: session.sessionId, auditLog: JSON.stringify(auditLog), completedAt: new Date(), }); // Use keyMaterial for encryption/signing // NEVER persist plaintext keyMaterial to disk
Security Guarantees
Xrite provides cryptographic tamper evidence, threshold reconstruction, and roster validation. Five security principles govern the design.
1. HMAC-Chained Audit Log
Every ceremony event is linked to the previous via HMAC-SHA256. Tampering with any entry invalidates the entire chain, producing legally admissible tamper-evidence. The chain is seeded with a 64-character zero hash and a random 32-byte chain key generated via crypto.getRandomValues().
2. TrustRegistry Roster Validation
Only participants whose DIDs appear in the TrustRegistry roster may submit shares. Unauthorized participants are rejected before their share data is processed. The registry endpoint is configurable (HTTP, static list, or did:web).
3. HMAC Before Reconstruction
All shares are HMAC-SHA256 verified before XorIDA reconstruction. Tampered shares are rejected immediately. If HMAC verification fails, the ceremony transitions to ABORTED state and cannot be resumed.
4. Session Isolation
Each ceremony session has a unique UUID. Shares from different sessions cannot be mixed. Session state transitions are strictly ordered (PENDING → IN_PROGRESS → COMPLETE). Duplicate share indices and participant DIDs are rejected.
5. Timeout Enforcement
Ceremonies have a configurable timeout (default 1 hour). Timed-out sessions cannot accept new shares, preventing indefinite session hijacking. Every submitShare() and completeCeremony() call checks the deadline before proceeding.
Benchmarks
Xrite ceremony operations complete in milliseconds. Benchmarks measured on M2 MacBook Pro (Node.js 22).
| Operation | Time | Notes |
|---|---|---|
| initCeremony (2-of-3) | ~2ms | Key generation + XorIDA split + Base45 encode |
| submitShare | ~0.5ms | Base45 decode + Xformat parse + HMAC chain append |
| completeCeremony (2-of-3) | ~1ms | XorIDA reconstruct + HMAC verify + PKCS#7 unpad |
| QR generation (qrcode lib) | ~10ms per QR | 300x300 PNG with error correction level H |
| TrustRegistry HTTP lookup | Variable | Network latency dependent |
Memory Usage
Ceremony sessions are stored in memory. Each session consumes approximately 2KB (session metadata + audit log). For 100 concurrent ceremonies, memory usage is ~200KB. Sessions are garbage-collected after completion or timeout.
Scalability
Xrite supports up to 255 participants (N ≤ 255) and 255 shares (K ≤ N). For typical corporate ceremonies (2-of-3 to 5-of-7), performance is constant-time. Larger N values (50+) may require additional Base45 encoding time for QR generation.
Honest Limitations
Xrite is not a complete HSM replacement. Five known limitations.
1. In-Memory Session State
Ceremony sessions are stored in memory. Process restart loses all active sessions. Persistent session storage is the consumer's responsibility. For production deployments, integrate with Redis or a database to survive process restarts.
2. No Ceremony Abort Authentication
Any caller can abort a ceremony by calling abortCeremony(sessionId). Authentication for abort operations should be implemented at the application layer. In a production environment, wrap abort calls with role-based access control.
3. Registry Availability
If the TrustRegistry is unreachable during a ceremony, share submissions are rejected. Network partitions can stall ceremonies. For air-gapped deployments, use a static roster instead of an HTTP endpoint.
4. Clock Dependency
Audit log timestamps rely on the system clock. Clock manipulation could produce misleading audit entries. NTP synchronization is recommended for production deployments. For compliance scenarios, consider integrating with a trusted time source (RFC 3161 timestamping).
5. Physical Security
Xrite does not enforce physical security of the ceremony location. An attacker with physical access to all K participants could coerce share submission. Boardroom physical security, video recording, and witness attestation are the consumer's responsibility.
Deep Dive: Error Codes, API Surface, Enterprise CLI
Complete reference for production deployments, enterprise integrations, and custom ceremony orchestration.
Error Codes
Complete error taxonomy with 25+ codes across 6 categories.
| Code | Sub-code | Cause |
|---|---|---|
| INVALID_CONFIG | — | Generic config validation failure |
| N_TOO_SMALL | n < 2 or not an integer | |
| K_TOO_SMALL | k < 2 or not an integer | |
| K_EXCEEDS_N | k > n | |
| MISSING_LABEL | Empty, missing, or oversized label | |
| MISSING_REGISTRY | Empty or missing registry endpoint | |
| SESSION_NOT_FOUND | — | No session with the given ID |
| SESSION_TIMED_OUT | — | Ceremony exceeded timeout window |
| SESSION_ABORTED | — | Ceremony aborted (integrity failure) |
| SESSION_ALREADY_COMPLETE | — | Ceremony already finished |
| INVALID_SHARE | — | Generic share validation failure |
| BAD_QR_DATA | Base45 decode, envelope parse, product type, or UUID mismatch | |
| MISSING_DID | Empty or missing participant DID | |
| DUPLICATE_SHARE | — | Share ID already submitted |
| DUPLICATE_PARTICIPANT | — | Participant DID already submitted a share |
| PARTICIPANT_NOT_IN_ROSTER | — | Participant not found in TrustRegistry roster |
| REGISTRY_UNREACHABLE | — | TrustRegistry endpoint unavailable |
| HMAC_CHAIN_BROKEN | — | Audit log chain hash verification failed |
| RECONSTRUCT_FAILED | — | Generic reconstruction failure |
| HMAC_MISMATCH | HMAC verification failed after XorIDA reconstruction | |
| INSUFFICIENT_SHARES | Fewer than k shares submitted | |
| DESERIALIZE | Unpadding or binary deserialization failed |
All functions return Result<T, CeremonyError>. Errors are values, not thrown exceptions.
Full API Surface
Three core functions, four types, and one error hierarchy.
Initialize a new key ceremony session. Generates a 32-byte root key, splits it into N QR-printable shares via XorIDA, and returns the session metadata with Base45-encoded QR strings.
Submit a scanned QR share to an active ceremony. Validates participant identity against TrustRegistry roster, rejects duplicates, and appends an HMAC-chained audit entry. Returns updated session state.
Complete the ceremony by reconstructing the root key from submitted shares. Requires at least K shares. Performs XorIDA reconstruction, HMAC verification (fail-closed), PKCS#7 unpad, and deserialization. Returns key material and complete audit log.
Types
interface CeremonyConfig { n: number; // Total shares (2-255) k: number; // Threshold (2-n) label: string; // Human-readable ceremony label registryEndpoint: string; // TrustRegistry URL or DID timeoutMs?: number; // Max duration (default 3,600,000) location?: string; // Physical location for audit log } interface CeremonySession { sessionId: string; // UUID state: 'PENDING' | 'IN_PROGRESS' | 'COMPLETE' | 'TIMED_OUT' | 'ABORTED'; config: CeremonyConfig; submittedShares: number; // Count of shares submitted participants: string[]; // DIDs of participants createdAt: string; // ISO 8601 deadline: string; // ISO 8601 } interface CeremonyResult { sessionId: string; keyMaterial: Uint8Array; // 32-byte root key auditLog: CeremonyAuditEntry[]; completedAt: string; // ISO 8601 participants: string[]; // DIDs of all participants } interface CeremonyAuditEntry { timestamp: string; // ISO 8601 eventType: 'CEREMONY_INIT' | 'SHARE_SUBMITTED' | 'CEREMONY_COMPLETE' | ...; sessionId: string; actorDid?: string; shareId?: number; previousHash: string; // HMAC-SHA256 currentHash: string; // HMAC-SHA256 }
Enterprise CLI
Xrite includes a companion CLI (keyceremony-cli) for enterprise deployments. Runs on port 3900 with REST API endpoints for ceremony orchestration.
Installation
npm install -g @private.me/keyceremony-cli keyceremony-cli start --port 3900
Endpoints
| Endpoint | Method | Description |
|---|---|---|
| /ceremony/init | POST | Initialize new ceremony session |
| /ceremony/:id/share | POST | Submit QR share to active ceremony |
| /ceremony/:id/complete | POST | Complete ceremony and retrieve key material |
| /ceremony/:id | GET | Query ceremony session state |
| /ceremony/:id/audit | GET | Retrieve audit log |
Docker Deployment
docker compose up keyceremony-cli
# Service available at http://localhost:3900
The CLI includes rate limiting (10 req/min per IP), CORS configuration, and audit log persistence to JSONL files. For production deployments, integrate with Redis for distributed session state.
Deployment Options
SaaS Recommended
Fully managed infrastructure. Call our REST API, we handle scaling, updates, and operations.
- Zero infrastructure setup
- Automatic updates
- 99.9% uptime SLA
- Pay per use
SDK Integration
Embed directly in your application. Runs in your codebase with full programmatic control.
npm install @private.me/keyceremony- TypeScript/JavaScript SDK
- Full source access
- Enterprise support available
On-Premise Enterprise
Self-hosted infrastructure for air-gapped, compliance, or data residency requirements.
- Complete data sovereignty
- Air-gap capable
- Docker + Kubernetes ready
- RBAC + audit logs included