Keysplit: Cryptographic Key Split Custody
Cryptographic keys are the ultimate single point of failure. Keysplit splits any key into shares distributed across independent custodians via XorIDA threshold sharing over GF(2). No single custodian holds a usable key. Information-theoretic security. 2-of-3, 2-of-5, K-of-N. HMAC-verified shares. Supports signing, encryption, root CA, and TLS keys. Zero npm dependencies.
Executive Summary
Keys are the crown jewels of cryptographic infrastructure. A compromised root CA key, TLS private key, or signing key can undermine an entire security posture overnight. Keysplit eliminates single points of failure by distributing keys across independent custodians using threshold secret sharing.
The approach is mathematically elegant: split a key into N shares such that any K shares (K ≤ N) can reconstruct it, but K-1 shares reveal zero information — no matter how much computing power an attacker has. This is information-theoretic security, not computational security. It doesn't depend on the hardness of factoring, discrete log, or any other mathematical assumption. It's a law of mathematics.
Keysplit uses XorIDA (threshold sharing over GF(2)) — the same core cryptographic engine that powers the entire PRIVATE.ME platform. Split/reconstruct operations complete in microseconds. Every share carries an HMAC-SHA256 signature verified before reconstruction (fail closed). Supports 4 key types: signing keys, encryption keys, root CA keys, and TLS keys, each with extensible metadata for audit trails.
Two functions handle all use cases: splitKey() distributes a key across custodians; reconstructKey() recovers it from a threshold quorum. Zero npm dependencies. Runs on Node.js 20+, browsers, Deno, Bun, Cloudflare Workers.
The Problem: Keys as Single Points of Failure
In traditional PKI, a single private key is the crown jewel. Lose it, and you've lost the identity behind it. Compromise it, and an attacker can forge signatures, impersonate you, or decrypt years of past traffic (if it was stored in ciphertext).
Current Approaches and Their Gaps
| Approach | Strengths | Weaknesses |
|---|---|---|
| Single key on disk | Simple | One breach = total loss. No fault tolerance. |
| Hardware Security Module (HSM) | Physical tamper resistance. Audit logs. | Single point of failure. Vendor lock-in. High cost ($2K+/yr). |
| Multiple copies | Redundancy against loss | Each copy is a full key. Compromise any one = breach all. |
| Shamir's Secret Sharing | Threshold-based security | Computationally expensive (500–2000x slower than XorIDA). Limited to ~256 shares practical max. Not used in production. |
| Key escrow + recovery | Recovery capability | Trusted escrow agent is a single point of failure. Creates backdoor risk. |
What Keysplit Solves
Keysplit eliminates the single point of failure by design. A key is split into N shares. Any K shares can reconstruct it. Any K-1 shares (or fewer) reveal absolutely nothing.
Keysplit's security does not depend on the computational difficulty of any problem. An attacker with infinite computing power, a quantum computer, or a magic 8-ball cannot extract information from fewer than K shares. The security is a mathematical guarantee, not a bet on hardness assumptions.
Fault tolerance: If one custodian loses their share (hardware failure, forgot password, moved to a different organization), the key is still recoverable from the remaining shares as long as K custodians are available.
No trusted third party. A traditional key escrow requires a trusted agent who can decrypt recovered keys. Keysplit requires only a threshold quorum of custodians, none of whom can act alone. This is strictly stronger security.
How Keysplit Works
Keysplit splits a cryptographic key into shares across custodians. It's a three-step pipeline: pad the key, compute an HMAC for integrity, split via XorIDA, and distribute shares to custodians.
Quick Start
import { splitKey, reconstructKey } from '@private.me/keysplit'; // Define custodians const custodians = [ { id: 'cust-1', name: 'Security Officer', role: 'primary' }, { id: 'cust-2', name: 'CTO', role: 'executive' }, { id: 'cust-3', name: 'External Auditor', role: 'auditor' }, ]; // Create split config (2-of-3 threshold) const config = { custodians, threshold: 2 }; // Split the root CA key const keyData = { keyId: 'ROOT-CA-2026', keyType: 'root-ca', algorithm: 'RSA-4096', data: privateKeyBytes, // Uint8Array metadata: { purpose: 'Certificate authority root' } }; const split = await splitKey(keyData, config); if (!split.ok) throw new Error(split.error.message); // Distribute split.value.shares[0] to cust-1, [1] to cust-2, [2] to cust-3... // Later: reconstruct from any 2 shares const shares = [split.value.shares[0], split.value.shares[2]]; const restored = await reconstructKey(shares); if (!restored.ok) throw new Error(restored.error.message); // restored.value => original Uint8Array (RSA-4096 key bytes)
That's it. Two function calls, two objects, and you have split key custody.
Use Cases
Root Certificate Authority
A root CA's private key is the most critical key in an organization. One compromise can issue false certificates for the entire Internet. Split the root key across 5 custodians (security, CTO, legal, board representative, external auditor). Any 3 can perform root signing ceremonies. No single person can issue a certificate.
Regulated Financial Infrastructure
SEC, SOX, and PCI-DSS require key split custody for critical cryptographic operations. Keysplit enables compliance without expensive HSM deployments. Split encryption keys across 3 regional custodians (East, Central, West). Regional outage doesn't prevent key recovery from the other 2 regions.
Classified Government Systems
NIST FIPS 140-3 and EO 14028 demand multi-custodian controls. Split signal intelligence (SIGINT) encryption keys across 2-of-3 vaults (NSA, DOD, NRO). No single vault can decrypt archived classified communications.
Enterprise Key Lifecycle Management
Split keys for subordinate CAs, TLS certificates, and SAML signing keys. Store shares in geographically distributed vaults (e.g., AWS KMS, Azure Key Vault, on-premises HSM). One vault compromise doesn't leak the key.
Zero-Knowledge Authentication at Scale
Biometric systems require a master seed to derive per-verifier identifiers. Split the seed across custody tiers (device, server, escrow). No single system can derive all identities.
Blockchain and DeFi
Cryptocurrency exchanges and protocols use Keysplit to split hot-wallet signing keys across signatories. M-of-N multisig is transparent but costly. Keysplit enables private M-of-N semantics without on-chain overhead.
Architecture
Keysplit's architecture is organized around three core operations: configuration validation, XorIDA splitting, and HMAC-verified reconstruction.
Split Pipeline
Step 1: Validation. Verify that the key is non-empty and the configuration is valid. A threshold of K requires at least K custodians. Reject threshold of 1 (no single-custodian keys).
Step 2: PKCS#7 Padding. Pad the key to a multiple of (nextOddPrime(N) - 1). This block size ensures XorIDA can work with arbitrary-length keys. Mandatory minimum of one byte padding, preventing padding oracle attacks.
Step 3: HMAC Integrity. Compute HMAC-SHA256 of the padded payload. Generate a random HMAC key. Distribute both the key and signature with each share. This enables post-reconstruction verification.
Step 4: XorIDA Split. Call splitXorIDA(padded, N, K) to generate N shares. Uses GF(2) arithmetic — no field inversion, no modular reduction, pure XOR operations.
Step 5: Package and Format. Each share is wrapped in a KeyShare object: base64-encoded data, HMAC signature, HMAC key, and metadata (keyId, custodianId, index, total, threshold). Data is formatted with the IDA5 branded header for provenance tracking (Xecret trademark, PRIVATE.ME mark, IDA5 magic, plaintext wrapper).
Xecret (TM) -> PRIVATE .ME (R) -> IDA5 -> Encrypted:// [base64 share data] => Generated by Xecret (TM)
This format is derived from US Patent 11,972,000 and must never be modified. The parser extracts data between "Encrypted://" and "=> Generated by Xecret".
Reconstruction Pipeline
Step 1: Validation. Verify that all shares have the same keyId, total, and threshold. Ensure the number of shares meets the threshold requirement.
Step 2: Extract Raw Data. Decode the base64 share data and strip the IDA5 header. Extract share indices from each KeyShare object.
Step 3: XorIDA Reconstruction. Call reconstructXorIDA(shares, indices, N, K). Returns the padded key bytes.
Step 4: HMAC Verification (FAIL CLOSED). Extract the HMAC key and signature from the first share. Verify the signature over the reconstructed padded payload. If verification fails, reject the entire result. Do not proceed to unpadding.
Step 5: PKCS#7 Unpadding. Strip the padding. If unpadding fails, reject.
Step 6: Return. Return the original key bytes.
Keysplit ALWAYS verifies the HMAC before unpadding. This is a fail-closed design: if shares are tampered with or corrupted, the signature check catches it before the key is returned. Never skip or delay HMAC verification.
API Reference
splitKey()
async function splitKey( key: CryptoKeyData, config: KeySplitConfig ): Promise<Result<KeySplitResult, KeySplitError>>
Splits a cryptographic key across custodians using XorIDA threshold sharing. Returns a Result with either a KeySplitResult (containing shares array) or a KeySplitError.
reconstructKey()
async function reconstructKey( shares: readonly KeyShare[] ): Promise<Result<Uint8Array, KeySplitError>>
Reconstructs a cryptographic key from a threshold quorum of shares. Verifies HMAC integrity before returning. Returns a Result with either the original key bytes or an error.
Type System
KeyType
type KeyType = 'signing' | 'encryption' | 'root-ca' | 'tls';
Discriminator for cryptographic key purpose. Used for audit trails and custody policy enforcement. signing for Ed25519, ECDSA, RSA-PSS. encryption for AES, X25519. root-ca for root certificate authority keys. tls for TLS/SSL private keys.
CryptoKeyData
interface CryptoKeyData { readonly keyId: string; readonly keyType: KeyType; readonly algorithm: string; readonly data: Uint8Array; readonly metadata?: Readonly<Record<string, string>>; }
A cryptographic key to be split. keyId is a user-supplied identifier (e.g., "ROOT-CA-2026"). data is the raw key bytes in Uint8Array format. metadata is optional and never encrypted; it's for audit trails and policy enforcement.
KeyCustodian
interface KeyCustodian { readonly id: string; readonly name: string; readonly role: string; }
A custodian who holds a share of a split key. id is a unique identifier. role is a free-form string for policy (e.g., "primary", "executive", "auditor").
KeyShare
interface KeyShare { readonly keyId: string; readonly custodianId: string; readonly index: number; readonly total: number; readonly threshold: number; readonly data: string; readonly hmac: string; readonly hmacKey: string; readonly originalSize: number; }
A single share of a split key. data, hmac, and hmacKey are all base64-encoded. originalSize is the size of the unpadded key in bytes (used for validation during reconstruction).
Security Model
Information-Theoretic Security
Keysplit uses XorIDA (XorIDA over GF(2)) to split keys. This is not "hard to break"; it is mathematically impossible to break with fewer than K shares, regardless of computational power.
Formally: Given K-1 shares, an attacker cannot distinguish between two different keys that were split with the same configuration. Every possible key is equally consistent with the observed shares. This is the definition of information-theoretic security.
HMAC Integrity
Every share carries an HMAC-SHA256 signature computed over the padded key. The HMAC key is random and distributed with each share.
Verification happens before unpadding. If a share is tampered with (corrupted over the network, by a malicious custodian, or by disk bit-flip), the HMAC verification will fail during reconstruction. The operation fails closed — no partial key is returned.
No Trusted Third Party
Traditional key escrow requires a trusted escrow agent who encrypts and stores backup copies. Keysplit requires no such trust: a threshold quorum of custodians is sufficient. No single custodian can act unilaterally.
PKCS#7 Padding
Mandatory minimum of one byte padding prevents padding oracle attacks. Padding is verified through HMAC, not by side-channel timing.
Randomness
Keysplit uses only crypto.getRandomValues() for randomness. Math.random() is never called. Cryptographically strong randomness.
Share Indices Are Validated
XorIDA reconstruction requires that share indices be within the valid range [0, N). Out-of-range indices are rejected. Shares from different keys (different keyId) are rejected.
No Plaintext Logging
The original key material is never logged, printed, or sent to analytics. Only metadata (keyId, key type, algorithm, original size) is observable.
Performance
Keysplit is fast. XorIDA operations on typical cryptographic keys (32–256 bytes) complete in microseconds. Larger keys (e.g., 4096-bit RSA = 512 bytes) take milliseconds.
Microbenchmarks (3-of-3 threshold)
| Key Size | Split Time | Reconstruct Time | Total |
|---|---|---|---|
| 32 bytes (Ed25519) | ~12 µs | ~18 µs | ~30 µs |
| 64 bytes (P-521) | ~22 µs | ~35 µs | ~57 µs |
| 256 bytes (AES-256 + metadata) | ~78 µs | ~110 µs | ~188 µs |
| 512 bytes (RSA-4096) | ~145 µs | ~210 µs | ~355 µs |
| 2048 bytes (RSA-16384) | ~580 µs | ~840 µs | ~1.42 ms |
Times measured on Node.js 20 LTS (M1 MacBook Pro). Web Crypto operations (HMAC, digest) account for most time in typical scenarios; XorIDA itself is negligible for keys under 1KB.
Scaling
Time scales linearly with key size. Threshold (K) and custodian count (N) have minimal impact — both are small integers in practice. A 2-of-3 split takes the same time as a 5-of-7 split for the same key size.
No iteration cost. Unlike Shamir's Secret Sharing (which requires polynomial interpolation and modular arithmetic), XorIDA is pure XOR — all branches have identical cost, making it timing-attack resistant.
Limitations
Shares Must Be Kept Confidential
A key is only as secure as its shares. Each share must be stored securely. If K shares are compromised, the key is compromised. Keysplit does not provide confidentiality for shares — it assumes each custodian stores their share in a secure location (HSM, encrypted storage, air-gapped machine).
Transport. Share delivery between custodians must use encrypted channels (TLS, or Xlink for M2M scenarios).
No Automatic Recovery
Keysplit does not provide automatic key recovery mechanisms. If a custodian loses their share, reconstruction requires the other custodians to retrieve their shares and coordinate with you. This is intentional — automatic recovery would require storing shares in a way that's accessible to the recovery mechanism, introducing new attack surface.
Share Indices Are Public
The share index (which position in the XorIDA split) is stored in plaintext in the KeyShare object. An attacker who observes all N shares knows which custodian held which share, but this is unavoidable in a practical system. What matters is that the key itself remains secure.
Metadata Is Not Encrypted
The metadata field on a KeyShare is not encrypted. Do not store sensitive information (private notes, location data) in metadata. Metadata is for operational purposes only (e.g., "Root CA 2026", "HSM backup").
No Forward Secrecy
If all N shares are ever stored in the same location or network, an attacker who accesses that location can reconstruct the key. Keysplit assumes custodians store shares in geographically or administratively separate locations. This is your responsibility.
Timestamp and Custody Chain Not Tracked
Keysplit doesn't track when a share was created or who held it at what time. For audit purposes, store this metadata separately. Keysplit itself provides no audit trail.
Post-Quantum Security
Keysplit's core security (XorIDA) is unconditionally post-quantum-safe. But the keys you split may rely on algorithms that will be broken by quantum computers.
XorIDA Is Quantum-Safe
XorIDA works over GF(2) with pure XOR operations. There is no mathematical assumption (discrete log, factoring, lattice hardness) that could be broken by a quantum computer. The information-theoretic security holds even if quantum computers become practical.
Keys Themselves May Not Be
If you split an RSA-4096 key, Keysplit protects the key's privacy (fewer than K shares reveal nothing). But the key's security depends on the hardness of factoring 4096-bit numbers, which a sufficiently powerful quantum computer could break.
Solution: Use post-quantum algorithms for keys you intend to split. NIST PQC finalists (ML-KEM, ML-DSA, SLH-DSA) are suitable. The PRIVATE.ME platform already uses ML-KEM-768 and ML-DSA-65 for transport-layer encryption and signatures.
Or, split FIPS 140-3 approved keys (AES-256 for symmetric encryption, or hybrid ECC+PQC keypairs). Keysplit doesn't care what kind of key you split — it just protects the bits.
Recommendation
For new key generation, use post-quantum algorithms (ML-KEM for key exchange, ML-DSA or SLH-DSA for signing). Split them with Keysplit. You get both:
- Information-theoretic security from Keysplit (unconditionally unbreakable)
- Post-quantum resistant crypto from the key algorithm itself (defended against quantum computers)
Integration & Deployment
Installation
pnpm add @private.me/keysplit
Environment Requirements
| Platform | Requirement | Status |
|---|---|---|
| Node.js 20+ | Web Crypto API available | Supported |
| Deno 1.40+ | Web Crypto available | Supported |
| Bun 1.0+ | Web Crypto available | Supported |
| Browsers (Chromium 113+, Firefox 130+, Safari 17+) | Ed25519 in Web Crypto | Supported |
| Cloudflare Workers | Web Crypto available | Supported |
Error Handling
All operations return a Result<T, KeySplitError> type. Check the ok field and use the error code for programmatic handling.
const result = await splitKey(key, config); if (!result.ok) { switch (result.error.code) { case 'INVALID_KEY': // Handle empty or malformed key break; case 'THRESHOLD_EXCEEDS_CUSTODIANS': // Handle configuration error break; case 'SPLIT_FAILED': // Handle cryptographic failure break; default: // Handle unknown error break; } throw new Error(result.error.message); }
Error Codes
| Code | Meaning | Recoverable |
|---|---|---|
INVALID_KEY |
Key data is empty or malformed | Yes — provide a non-empty key |
INVALID_CONFIG |
Configuration is malformed (bad threshold) | Yes — adjust threshold/custodians |
INSUFFICIENT_CUSTODIANS |
Fewer than 2 custodians configured | Yes — add more custodians |
THRESHOLD_EXCEEDS_CUSTODIANS |
Threshold K > number of custodians N | Yes — lower threshold or add custodians |
SPLIT_FAILED |
XorIDA split operation failed (rare) | No — check key size and retry |
HMAC_FAILURE |
Share HMAC verification failed during reconstruction | No — share was tampered with or corrupted |
RECONSTRUCTION_FAILED |
Reconstruction produced invalid data | No — shares are inconsistent |
INSUFFICIENT_SHARES |
Fewer shares provided than threshold requires | Yes — provide more shares |
SHARE_MISMATCH |
Shares belong to different keys | Yes — provide shares from the same split |
Production Deployment Example
A typical deployment for a root CA would:
- Generate the root CA key (RSA-4096 or ML-DSA).
- Call
splitKey()with a 3-of-5 configuration (3 shares needed, 5 total custodians). - Distribute each share to a custodian on a secure device (hardware security module, encrypted USB, or air-gapped machine).
- Store the share metadata (keyId, custodianId, index) in a secure database for audit purposes.
- When a certificate signing ceremony is needed, gather 3 custodians (any combination of the 5).
- Call
reconstructKey()with their 3 shares to recover the root key in memory. - Use the key to sign the certificate.
- Immediately discard the key from memory (no persisting to disk).
Never persist the reconstructed key to disk or non-volatile storage. Use it in memory only, then discard. The entire point of split custody is that the full key never rests on a single machine.
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
- Enterprise SLA available
SDK Integration
Embed directly in your application. Runs in your codebase with full programmatic control.
npm install @private.me/keysplit- TypeScript/JavaScript SDK
- Full source access
- Enterprise support available
On-Premise Upon Request
Enterprise CLI for compliance, air-gap, or data residency requirements.
- Complete data sovereignty
- Air-gap capable deployment
- Custom SLA + dedicated support
- Professional services included
Enterprise On-Premise Deployment
While keySplit is primarily delivered as SaaS or SDK, we build dedicated on-premise infrastructure for customers with:
- Regulatory mandates — HIPAA, SOX, FedRAMP, CMMC requiring self-hosted processing
- Air-gapped environments — SCIF, classified networks, offline operations
- Data residency requirements — EU GDPR, China data laws, government mandates
- Custom integration needs — Embed in proprietary platforms, specialized workflows
Includes: Enterprise CLI, Docker/Kubernetes orchestration, RBAC, audit logging, and dedicated support.