IdentitySplit: SIM Swap Protection
Mobile identity credentials split across independent carriers via XorIDA threshold sharing. No single carrier holds the complete credential. Reconstruction requires consensus from a configurable number of carriers, making SIM swap attacks information-theoretically impossible.
Executive Summary
SIM swap attacks exploit the single point of failure in mobile identity: one carrier controls the complete credential binding a phone number to a subscriber. IdentitySplit uses XorIDA (threshold sharing over GF(2)) to distribute that credential across multiple independent carriers so no single entity can reconstruct the original without cooperating with others.
Two functions cover all use cases: splitIdentity() takes a mobile identity credential (SIM binding, phone number, subscriber key) and a carrier list, then outputs encrypted shares — one per carrier. reconstructIdentity() reassembles the original credential from a threshold number of shares. HMAC-SHA256 verification happens before reconstruction, rejecting any tampered or poisoned shares.
The security guarantee is information-theoretic — not computationally hard to break, but mathematically impossible. Any subset of shares below the threshold reveals zero information about the original credential. An attacker who compromises two carriers out of three learns nothing if the threshold is 2-of-3.
Designed for regulatory compliance (HIPAA, FedRAMP, SOX, GDPR, eIDAS), telecom infrastructure security, and identity protection. Runs in Node.js 20+, browsers with Web Crypto API, and Tauri desktop apps. Zero npm runtime dependencies.
The Problem: SIM Swap Attacks
A SIM swap attack succeeds when an attacker convinces a single mobile carrier employee to port the victim's phone number to a device the attacker controls. Once the number is ported, the attacker intercepts all SMS-based 2FA codes and gains access to any account protected by phone number verification.
Why SIM Swap Is Critical
Phone numbers are the de facto global identifier for mobile subscribers. Almost every online service offers phone-based 2FA: SMS, OTP apps tied to SIM, call verification. A compromised phone number is equivalent to compromised identity across all those services. The attack does not require sophisticated hacking — just social engineering of a single carrier employee.
Current Defenses Are Insufficient
- PIN protection on carrier accounts: Employees can reset PINs with a phone call and security questions.
- Email verification: Attacker already has access to email if phone number is primary recovery method.
- Carrier security audits: Detect past breaches, do not prevent future social engineering.
- Third-party 2FA apps: Still depend on phone number verification for account recovery.
| Defense | Cost | Prevents SIM Swap | Notes |
|---|---|---|---|
| Carrier PIN | None | No | Bypassed via social engineering or employee compromise |
| Email verification | None | No | Phone number often primary recovery method |
| Carrier security audit | High | No | Reactive, not preventive |
| IdentitySplit | Low | Yes | Requires threshold of carriers to cooperate; information-theoretic |
Solution Overview
IdentitySplit distributes mobile identity credentials across multiple carriers using XorIDA threshold sharing. No single carrier holds the complete credential. Reconstruction requires a threshold number of carriers to cooperate.
Core Insight
Instead of a phone number binding to a single carrier’s database, IdentitySplit creates K shares such that any K-of-N carriers can reconstruct the original credential, but any subset smaller than K reveals nothing.
Example: Split a SIM binding across AT&T, T-Mobile, and Verizon with threshold 2-of-3. An attacker who compromises one carrier (say AT&T) gains access to AT&T’s share but cannot reconstruct the credential without shares from at least one other carrier.
Architecture at a Glance
Key Properties
Data Flow
The credential flows as JSON, encoded as base64 (for transport), split via XorIDA into K shares, HMAC-tagged for integrity, and distributed to carriers. On reconstruction, shares are HMAC-verified before combining, rejecting any share that fails verification.
Real-World Use Cases
Six scenarios where IdentitySplit prevents SIM swap and mobile identity compromise.
High-net-worth individuals split their bank SIM binding across 2 or 3 carriers (AT&T, T-Mobile, Verizon). Attacker needs to compromise at least 2 to hijack banking 2FA.
splitIdentity + 2-of-3 thresholdPatient phone numbers split across carrier network to satisfy HIPAA minimum viable safeguards. No single entity holds complete PII binding.
splitIdentity + HMAC verificationFederal agencies bind employee phone numbers across private carriers + internal infrastructure with 2-of-3 or 3-of-5 thresholds for ATO compliance.
splitIdentity + custom thresholdLarge enterprises issue corporate SIM bindings split 2-of-3 to protect mobile endpoints from SIM swap during access to internal systems.
splitIdentity in corporate serverLaw firms and counsel certify mobile identity via split credentials, preventing opposing counsel from SIM-swapping witness accounts or evidence custodians.
splitIdentity + audit trailUsers traveling internationally split phone binding across local + home carrier to prevent SIM swap even if local carrier is compromised or regulations force identity hand-over.
splitIdentity + multi-regionArchitecture & Design
IdentitySplit is built on three core modules: identity splitting, reconstruction, and error handling. Data flows through encoding, XorIDA threshold sharing, HMAC integrity, and carrier routing.
Module Structure
The package exports three key modules: identity-splitter.ts (performs XorIDA split), identity-reconstructor.ts (reassembles from shares), and errors.ts (error classes and codes).
Data Types
Five core types define the API:
- IdentityCredential: The original mobile credential (credentialId, subjectId, credentialType, data bytes, timestamps).
- Carrier: A carrier entity holding one share (id, name, country).
- IdentityConfig: Split configuration (carrier list, threshold K).
- IdentityShare: One encrypted, HMAC-tagged share assigned to a carrier.
- IdentitySplitResult: Output of a split operation (credentialId, shares array, SHA-256 hash).
IdentityShare includes the original credential size so oversized payloads can be detected.
Cryptographic Flow
- Validation: Credential fields checked, carrier count vs. threshold validated.
- Encoding: Credential data encoded as base64 for transport safety.
- XorIDA Split: Encoded credential split into K shares via threshold sharing over GF(2).
- HMAC Tagging: Each share is HMAC-SHA256 signed with a per-share key derived from the original credential.
- Carrier Assignment: Each share is assigned to a carrier (AT&T, T-Mobile, etc.) and indexed.
- Result: IdentitySplitResult contains all shares, a credential hash, and metadata.
On reconstruction, the process reverses: shares are HMAC-verified first (rejecting any tampered share), then XorIDA reconstructs the original credential.
API Surface
IdentitySplit exports two main functions, plus error utilities. All operations return Result<T, E> for reliable error handling.
Core Functions
IdentityCredential (the secret to protect) and IdentityConfig (carriers + threshold). Returns IdentitySplitResult on success, or error code on failure.
Uint8Array on success, or error code on failure.
Error Utilities
IdentitySplitError instance. Enables safe error handling in catch blocks.
Quick Start Example
import { splitIdentity, reconstructIdentity } from '@private.me/identitysplit'; // 1. Create credential const credential = { credentialId: 'CRED-2026-42', subjectId: 'USER-12345', credentialType: 'sim-binding', data: new Uint8Array([/* 256-byte SIM binding */]), issuedAt: Date.now(), expiresAt: Date.now() + 365 * 24 * 60 * 60 * 1000, }; // 2. Configure carriers and threshold const config = { carriers: [ { id: 'ATT', name: 'AT&T', country: 'US' }, { id: 'TMO', name: 'T-Mobile', country: 'US' }, { id: 'VZW', name: 'Verizon', country: 'US' }, ], threshold: 2, // 2-of-3 required to reconstruct }; // 3. Split the credential const splitResult = await splitIdentity(credential, config); if (!splitResult.ok) { console.error('Split failed:', splitResult.error.message); return; } // Each carrier now holds one share const { shares } = splitResult.value; console.log(`Created ${shares.length} shares`); // 4. Distribute shares to carriers (e.g., via HTTPS to carrier APIs) // 5. Later, reconstruct from any 2 of 3 shares const twoShares = [shares[0], shares[1]]; const reconstructed = await reconstructIdentity(twoShares); if (!reconstructed.ok) { console.error('Reconstruction failed:', reconstructed.error.message); return; } // reconstructed.value is the original Uint8Array console.log('Credential recovered');
Integration Guide
Three steps to integrate IdentitySplit into your telecom or identity platform: split at enrollment, distribute shares, reconstruct on demand.
Step 1: Split at Enrollment
When a user registers their mobile number in your system, create a credential object and split it across carriers immediately. Store the split result (credential hash, carrier assignments, share metadata) in your database for future reconstruction.
Step 2: Distribute Shares to Carriers
Each carrier operates a secure API endpoint that accepts an IdentityShare. You make HTTPS requests to each carrier’s endpoint, passing the appropriate share. Carriers store shares in encrypted vaults with access controls. No carrier ever sees shares from other carriers.
Step 3: Reconstruct on Demand
When the user needs to verify their identity (e.g., during SIM swap recovery), query K carriers for their shares, HMAC-verify each, and reconstruct. The reconstructed credential is never persisted — use immediately and discard.
Deployment Checklist
- ✓ Integrate
splitIdentity()into user enrollment flow - ✓ Configure carrier list and threshold for your compliance model
- ✓ Implement carrier integration layer (REST client to each carrier’s share endpoint)
- ✓ Add recovery flow: query carriers, reconstruct, verify identity
- ✓ Log all split/reconstruction events for audit trail
- ✓ Test threshold scenarios (2-of-3, 3-of-5, custom)
- ✓ Run security review of carrier APIs and data handling
Security Model
IdentitySplit is built on information-theoretic security, not computational hardness. An attacker with unbounded compute cannot recover the original credential from fewer than K shares.
Information-Theoretic Guarantee
XorIDA threshold sharing guarantees that any subset of shares smaller than the threshold K carries zero information about the original credential. This is not a computational assumption (like breaking AES-256) but a mathematical certainty based on properties of finite fields.
HMAC-SHA256 Integrity
Each share is protected by a 256-bit HMAC computed over the share data using a key derived from the original credential. During reconstruction, every share is HMAC-verified before combining. Any tampering is immediately detected and the reconstruction aborted.
Threat Model
| Threat | Attacker Capability | IdentitySplit Defense |
|---|---|---|
| SIM swap at 1 carrier | Compromise 1 share | Threshold prevents reconstruction |
| Compromise 2 of 3 carriers | Obtain 2 shares | With threshold 3-of-3, fails; 2-of-3, succeeds (by design) |
| Share tampering in transit | Modify one share data | HMAC verification detects tampering |
| Share replay attack | Reuse an old share | Credential timestamps mitigate (old shares have expired expiresAt) |
| Brute-force reconstruction | Try all possible credentials | Share size (256+ bytes) makes brute-force infeasible |
Assumptions
- Web Crypto API is secure: Implementation relies on browser/Node.js crypto.subtle for HMAC-SHA256.
- Carriers are partially trusted: Each carrier stores one share. We assume not all carriers are compromised simultaneously.
- HTTPS channels are secure: Share distribution uses HTTPS. Network eavesdropping is not a threat if HTTPS is properly enforced.
- No side channels: Timing attacks on HMAC verification are out of scope; use constant-time comparison in production.
Performance Characteristics
IdentitySplit is lightweight. XorIDA splitting and HMAC verification complete in microseconds for typical credential sizes.
Benchmark Results
Measured on Node.js 20 (Intel i7, single thread). Credentials range from 128 bytes (minimal SIM binding) to 1024 bytes (full identity envelope).
| Operation | Payload Size | Time | Threshold |
|---|---|---|---|
| splitIdentity() | 256 bytes | <200µs | 2-of-3 |
| splitIdentity() | 512 bytes | <400µs | 2-of-3 |
| splitIdentity() | 1024 bytes | <800µs | 2-of-3 |
| reconstructIdentity() | 256 bytes | <180µs | 2-of-3 |
| HMAC verification (per share) | 256 bytes | <50µs | N/A |
Memory Usage
Splitting allocates one output buffer per share (~2-3× payload size for encoding + HMAC). Reconstruction allocates the original credential size once, plus temporary buffers during XorIDA combine. No memory leaks or unbounded growth.
Limitations & Honest Assessment
IdentitySplit is powerful but not a silver bullet. Understanding its boundaries is critical for correct deployment.
Does NOT Protect Against
- Compromised reconstruction: If reconstruction happens on a compromised device, the attacker sees the original credential in plaintext.
- Carrier collusion threshold ≤ 1: A 1-of-3 split offers no protection; one carrier alone can reconstruct.
- Share leakage before threshold: If fewer than K shares are leaked, XorIDA guarantees no information leakage. But if K or more shares are compromised, original is recovered.
- Regulatory enforcement: IdentitySplit is a technical control. Compliance still requires regulatory framework, audits, and incident response.
- SIM swap at reconstruction time: If the user tries to reconstruct their credential and the attacker simultaneously performs a SIM swap on one carrier, the swap succeeds. Defense is organizational (alerting, challenge-response) not technical.
Deployment Risks
Threshold misconfiguration: A 2-of-2 threshold requires both carriers; if one is unreachable, reconstruction fails (single point of failure). A 1-of-3 threshold is not better than unprotected credentials. Correct threshold depends on your trust model.
Carrier availability: Reconstruction requires K out of N carriers to be reachable. Plan for outages, bankruptcies, and carrier API deprecations.
Credential expiration: Credentials with expiresAt timestamps cannot be reconstructed after expiry. Implement credential refresh/rotation policies.
Future Considerations
- Share rotation: No built-in mechanism to rotate shares without reconstructing. Planned for v0.2.
- Distributed reconstruction: Reconstruction currently requires K shares to be available simultaneously. Future versions may support incremental reconstruction.
- Post-quantum upgrade: HMAC-SHA256 is quantum-safe. XorIDA is quantum-safe. Future versions may support ML-KEM for hybrid PQ key encapsulation.
Error Handling & Codes
IdentitySplit uses a Result<T, E> pattern with 7 error codes covering configuration, integrity, and cryptographic failures.
Error Code Reference
| Code | Category | Description |
|---|---|---|
| INVALID_CONFIG | Config | Threshold exceeds carrier count or is zero. E.g., threshold: 4 with 3 carriers. |
| INVALID_CREDENTIAL | Validation | Credential missing required fields (id, data) or data is empty. |
| SPLIT_FAILED | Crypto | XorIDA split operation failed (rare; usually indicates memory exhaustion). |
| HMAC_FAILURE | Integrity | Share HMAC verification failed during reconstruction. Share is tampered or corrupted. |
| INSUFFICIENT_SHARES | Input | Fewer than K shares provided for reconstruction. |
| INVALID_SHARE | Validation | Share data malformed (bad base64, missing fields, wrong index range). |
| RECONSTRUCTION_FAILED | Crypto | XorIDA reconstruction failed (inconsistent share indices or data corruption). |
Error Class Hierarchy
class IdentitySplitError extends Error { code: string; subCode?: string; docUrl?: string; } class IdentityConfigError extends IdentitySplitError {} class IdentityCredentialError extends IdentitySplitError {} class IdentityIntegrityError extends IdentitySplitError {}
Error Handling Pattern
const result = await splitIdentity(credential, config); if (!result.ok) { const { code, message } = result.error; switch (code) { case 'INVALID_CONFIG': console.error('Fix threshold/carrier config'); break; case 'INVALID_CREDENTIAL': console.error('Credential missing required fields'); break; default: console.error('Unexpected error:', message); } return; } // splitResult.value is safe to use here const { shares } = result.value;
Exception-Based Alternative
If your codebase uses try/catch, convert error codes to typed exceptions using toIdentitySplitError():
import { toIdentitySplitError } from '@private.me/identitysplit'; try { const result = await splitIdentity(credential, config); if (!result.ok) { throw toIdentitySplitError(result.error.code); } return result.value; } catch (err) { if (isIdentitySplitError(err)) { console.error(`Error [${err.code}]: ${err.message}`); } else { throw err; } }
XorIDA Mechanics
Understanding the threshold sharing algorithm at the heart of IdentitySplit.
XorIDA: Threshold Sharing over GF(2)
XorIDA (XOR-based Information Dispersal Algorithm) works in the finite field GF(2), where addition is XOR and multiplication is AND. To create a K-of-N scheme:
- Generate N-1 random shares from a cryptographically secure RNG.
- XOR them together to derive the final share such that XORing all N shares recovers the original credential.
- Any K shares are combined via XOR to reconstruct.
- Any subset < K shares, when XORed, produce random noise (no information about original).
The property that makes XorIDA information-theoretic is: without all N shares, or at least K shares if you know which K to select, you cannot determine the original. This is true even with infinite computational power, because the problem is not computationally hard—it's combinatorially impossible.
Why XorIDA, Not Shamir's?
Shamir's Secret Sharing (polynomial-based) is also K-of-N and information-theoretic. However, XorIDA is 500-2000× faster for typical payload sizes (200-1000 bytes) because it operates on bits, not modular arithmetic. IdentitySplit uses XorIDA for sub-millisecond split/reconstruct times. Shamir's is not implemented.
HMAC Verification Before Reconstruction
Why integrity checks must happen before combining shares.
The Critical Rule
HMAC verification MUST occur before XorIDA reconstruction. This prevents an attacker from injecting a forged share that corrupts the reconstructed credential.
Attack Scenario
Suppose an attacker obtains a legitimate share (e.g., stolen from AT&T's vault). The attacker modifies one bit and resubmits it as if it came from T-Mobile. During reconstruction:
- Without HMAC verification: The forged share is XORed with legitimate shares. The result is corrupted, but the error is silent (no exception thrown, just wrong data).
- With HMAC verification first: The forged share fails HMAC check immediately. Reconstruction aborts, and an error is returned.
Implementation
Each share is tagged with an HMAC derived from the original credential data and the share index. During reconstruction, every share’s HMAC is verified against a recomputed HMAC using the same key and index. Only shares that pass are used in XorIDA combination.
Codebase Statistics
Package structure and metrics at a glance.
Module Organization
- src/index.ts – Public API barrel export (functions + types + error classes).
- src/types.ts – IdentityCredential, Carrier, IdentityConfig, IdentityShare, error types.
- src/identity-splitter.ts – splitIdentity() implementation (validation, encoding, XorIDA, HMAC, carrier assignment).
- src/identity-reconstructor.ts – reconstructIdentity() implementation (HMAC verification, XorIDA combine, output).
- src/errors.ts – IdentitySplitError class hierarchy and toIdentitySplitError() utility.
Test Coverage
- identitysplit.test.ts – Happy path, threshold validation, carrier count vs. threshold, expiration, encoding.
- abuse.test.ts – Out-of-range indices, tampered HMAC, insufficient shares, malformed data, replay attacks.
Metrics
Quality Standards
- ✓ TypeScript strict mode, no `any` types
- ✓ 100% HMAC verification on all reconstruction paths
- ✓ Result<T, E> pattern (no thrown exceptions in public API)
- ✓ Zero npm runtime dependencies
- ✓ Web Crypto API only (no crypto.getRandomValues() misuse)
- ✓ Comprehensive error codes and messages
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/identitysplit- 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 identitySplit 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.