Loading...
private.me Docs
Get xRite
PRIVATE.ME · Technical White Paper

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.

v0.1.0 K-of-N threshold HMAC audit chain QR Base45 0 deps Dual ESM/CJS
Section 01

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.

Section 02

Developer Experience

Xrite provides structured error codes with actionable hints and field attribution to simplify debugging in high-stakes corporate environments.

Quick Start

Initialize a 2-of-3 ceremony
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.

Structured error detail
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
COMPLETE ERROR REFERENCE
See Appendix A1: Error Codes for the complete list of error codes and sub-codes with detailed descriptions.
Section 03

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

HSM $50K equipment weeks to deploy NOTARY $5K per ceremony days to schedule PAPER LOG manual audit trail no tamper evidence VENDOR LOCK-IN Proprietary HSM protocols SCHEDULE DELAYS Executives + notary availability TAMPER RISK Paper logs can be altered Single point of failure: custody chain breaks invalidate ceremony

The New Way

INIT CEREMONY XorIDA K-of-N split QR shares SCAN SHARES TrustRegistry roster HMAC chain COMPLETE Root key + audit log ZERO COST No HSMs, no notaries INSTANT 5-minute ceremony TAMPER-PROOF HMAC-SHA256 chain Courts verify authenticity by recomputing hash chain — no vendor trust required
Section 04

Real-World Use Cases

Six scenarios where Xrite replaces traditional HSM-based key ceremonies with threshold splitting and cryptographic audit trails.

🏦
Financial
Root CA Rotation

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 })
🔒
Healthcare
Encryption Key Escrow

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 validation
🏛
Government
Classified Key Ceremony

Military 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 audit
Legal
Law Firm Escrow

Managing partners hold shares of client file encryption key. 2-of-4 threshold for emergency succession. Audit log provides malpractice insurance evidence.

Audit log + court admissibility
💼
Enterprise
Disaster Recovery

C-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 tolerance
🔍
Compliance
Audit Trail Generation

Compliance officer witnesses ceremony. HMAC chain provides cryptographic proof for auditors. Satisfies NIST 800-57 key management requirements.

HMAC chain + NIST compliance
Section 05

Solution Architecture

Five composable components. Each can be used independently or orchestrated through the ceremony workflow.

Xformat Envelope
Binary serialization
XRITE product type (32-bit magic)
Session UUID for isolation
Share ID + total shares metadata
Base45 QR
Compact encoding
Printable QR codes
Smaller than Base64 (20% savings)
Mobile scanner compatible
TrustRegistry
Roster validation
DID roster lookup
Rejects unauthorized participants
Pluggable endpoint (HTTP or static)
Session State
Lifecycle management
PENDING → IN_PROGRESS → COMPLETE
Timeout enforcement (default 1 hour)
Duplicate detection (share + participant)

Ceremony Flow

1. INIT CEREMONY Generate 32-byte root key → PKCS#7 pad → HMAC → XorIDA split → Xformat envelope → Base45 QR Audit event: CEREMONY_INIT (initiator DID, timestamp, location) 2. SUBMIT SHARES (K times) Participant scans QR → Base45 decode → Xformat parse → validate product type + UUID Check TrustRegistry roster → reject duplicates (share ID + participant DID) Audit event: SHARE_SUBMITTED (participant DID, share ID, timestamp) with HMAC chain 3. COMPLETE CEREMONY Check K shares submitted → XorIDA reconstruct → HMAC verify (fail-closed) PKCS#7 unpad → deserialize → return 32-byte key + complete audit log Audit event: CEREMONY_COMPLETE (session ID, participant list, completion timestamp) ROOT KEY Uint8Array (32 bytes) AUDIT LOG HMAC-chained events

Session States

State transitions
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.

Audit entry structure
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.

Section 06

Integration

Xrite integrates with existing TrustRegistry infrastructure or operates standalone. Zero external dependencies beyond Web Crypto API.

Installation

npm install
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.

HTTP registry endpoint
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.

Generate printable QR codes
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.

Persist audit log
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 WARNING
Never persist plaintext key material to disk. The root key exists in memory only during the ceremony. Immediately encrypt it with a separate key or use it to derive child keys via HKDF before wiping from memory.
Section 07

Security Guarantees

Xrite provides cryptographic tamper evidence, threshold reconstruction, and roster validation. Five security principles govern the design.

HMAC-256
Audit chain
K-of-N
Threshold
0
Plaintext storage
1 hour
Default timeout

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.

POST-QUANTUM SECURITY
Xrite inherits information-theoretic security from XorIDA. K-1 shares reveal zero information about the root key regardless of computing power, including quantum computers. No computational assumption required.
Section 08

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.

Section 09

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.

NOT A COMPLETE HSM REPLACEMENT
Xrite replaces the key splitting and audit logging components of traditional HSM ceremonies. It does NOT replace physical tamper resistance, hardware entropy sources, or FIPS 140-2 certification. For scenarios requiring FIPS compliance, integrate Xrite with FIPS-validated entropy sources.
Advanced Topics

Deep Dive: Error Codes, API Surface, Enterprise CLI

Complete reference for production deployments, enterprise integrations, and custom ceremony orchestration.

Appendix A1

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.

Appendix A2

Full API Surface

Three core functions, four types, and one error hierarchy.

initCeremony(config: CeremonyConfig, initiatorDid?: string): Promise<Result<{ session: CeremonySession; qrShares: string[] }, CeremonyError>>

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.

submitShare(sessionId: string, qrData: string, participantDid: string): Promise<Result<CeremonySession, CeremonyError>>

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.

completeCeremony(sessionId: string): Promise<Result<CeremonyResult, CeremonyError>>

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

Core 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
}
Appendix A3

Enterprise CLI

Xrite includes a companion CLI (keyceremony-cli) for enterprise deployments. Runs on port 3900 with REST API endpoints for ceremony orchestration.

Installation

Install CLI
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
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
View Pricing →
📦

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
Get Started →
🏢

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
Enterprise CLI →