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

Xrecall: Physical MFA Recovery

Authentication credentials lost forever when phones die. Xrecall backs up TOTP seeds, OAuth tokens, passkeys, recovery codes, API keys, and certificates as K-of-N XorIDA QR shares. Print them, store them physically, scan to recover. Information-theoretically secure. No cloud, no server, no electronic backup.

v0.1.0 6 credential types QR code optimized K-of-N threshold Base45 + Xformat
Section 01

Executive Summary

MFA and authentication credentials die with your phone. Xrecall backs them up as printed QR codes using information-theoretically secure XorIDA threshold sharing.

Two functions cover all use cases: backupCredentials() splits an array of credentials (TOTP seeds, OAuth refresh tokens, passkeys, recovery codes, API keys, certificates) into K-of-N QR-printable shares using XorIDA. Each share is wrapped in an Xformat binary envelope and Base45-encoded for QR alphanumeric mode. restoreCredentials() scans any K QR codes, validates integrity via HMAC-SHA256, reconstructs the plaintext via XorIDA, and deserializes the credentials.

With N=3 and K=2, you print three QR codes and store them in separate physical locations (safe, bank vault, trusted family). Any two reconstruct all credentials. One lost share is tolerated. An attacker who compromises any single share learns mathematically nothing about the plaintext — not computationally hard to break, but impossible regardless of computational power.

No cloud backup. No server. No phone restore. No App Store. Just paper and a QR scanner.

Section 02

Developer Experience

Xrecall provides structured error codes with actionable hints to help developers build reliable credential recovery flows.

Error Categories

Xrecall organizes 20+ error codes across 7 categories:

Category Example Codes When
Configuration INVALID_CONFIG, N_TOO_SMALL, K_EXCEEDS_N Split configuration validation (n, k, ownerDid)
Credential INVALID_CREDENTIAL, EMPTY_SECRET, UNKNOWN_TYPE Credential field validation (type, issuer, account, secret)
Encryption ENCRYPT_FAILED, PASSPHRASE_DERIVATION Optional AES-256-GCM passphrase layer
Split SPLIT_FAILED, HMAC_FAILED XorIDA split or HMAC generation
Reconstruct HMAC_MISMATCH, INSUFFICIENT_SHARES Share validation, HMAC verification, reconstruction
Deserialize RECONSTRUCT_FAILED:DESERIALIZE JSON parsing or PKCS#7 unpad failure
Decrypt DECRYPT, BAD_PASSPHRASE Optional AES-256-GCM decryption
RESULT PATTERN
All functions return Result<T, RecoveryError>. Errors are values, not thrown exceptions. This enables exhaustive error handling and makes error cases explicit in the type system.
Error handling example
const restore = await restoreCredentials(qrShares);

if (!restore.ok) {
  switch (restore.error) {
    case 'RECONSTRUCT_FAILED:HMAC_MISMATCH':
      console.error('Share data corrupted or tampered.');
      break;
    case 'RECONSTRUCT_FAILED:INSUFFICIENT_SHARES':
      console.error('Not enough shares. Need at least k.');
      break;
    case 'RECONSTRUCT_FAILED:BAD_PASSPHRASE':
      console.error('Incorrect passphrase.');
      break;
    default:
      console.error(`Reconstruction failed: ${restore.error}`);
  }
  return;
}

console.log(restore.value.credentials);
Section 03

The Problem

Authentication credentials are locked in your phone. When the phone dies, your credentials die with it.

Lost phones mean lost access. TOTP seeds, OAuth refresh tokens, passkeys, recovery codes — all gone. Most MFA apps don't offer backup. The ones that do rely on cloud sync, which creates a centralized target and requires trust in the provider.

Cloud backup is a single point of failure. Apple Keychain, Google Authenticator sync, 1Password — one compromise exposes all credentials. One rogue employee, one server breach, one legal subpoena, and your entire authentication stack is exposed.

Recovery codes are brittle. Paper printouts fade. Digital copies on your laptop aren't airgapped. Storing them in a password manager defeats the purpose of multi-factor authentication.

Physical security tokens lock you in. YubiKeys cost money per device. If you lose it, you're locked out. Backup keys double the attack surface.

Method Backup Cloud Required Fault Tolerance Information-Theoretic
Google Authenticator Sync Cloud Yes No No
Apple Keychain iCloud Yes No No
1Password Cloud Yes No No
Paper recovery codes Physical No No No
YubiKey Physical No Manual dups No
Xrecall Physical QR No K-of-N XorIDA

The Old Way

GOOGLE CLOUD single point of failure SERVER BREACH All TOTP seeds exposed LEGAL SUBPOENA Forced disclosure

The New Way

QR Share 1 Home safe QR Share 2 Bank vault QR Share 3 Family member Any 2 reconstruct all credentials Zero electronic backup
Section 04

Real-World Use Cases

Six scenarios where Xrecall replaces cloud MFA backup with physical QR shares.

🔐
Enterprise IT
Executive Recovery

Executive loses phone during travel. IT scans 2 of 3 QR codes from company safe and restores all corporate MFA seeds within minutes. No account lockout, no support ticket escalation.

2-of-3 TOTP seeds
💼
Personal Security
Personal Backup

Print 3 QR codes for personal accounts (Gmail, banking, crypto). Store one at home, one in bank vault, one with family. Phone theft or loss is recoverable without cloud dependency.

3-of-5 all credential types
⚖️
Legal / Compliance
Attorney-Client Privilege

Law firm backs up OAuth refresh tokens for document management systems. Shares distributed across partner offices. Cloud backup would waive privilege under some jurisdictions.

2-of-3 OAuth tokens
🏦
Financial
Trading Desk Recovery

Trading desk API keys backed up as QR shares. Keys for Bloomberg Terminal, exchanges, internal systems. Physical distribution across secured locations ensures regulatory compliance.

API keys + certificates
🔑
DevOps
Infrastructure Access

DevOps team backs up passkeys and recovery codes for production infrastructure. Shares distributed to on-call engineers. Hardware token loss doesn't block incident response.

Passkeys + recovery codes
🏥
Healthcare
EHR Access Recovery

Hospital staff TOTP seeds for EHR access. Shares stored in facility security office. HIPAA compliance requires no cloud transmission of authentication credentials.

2-of-2 TOTP seeds
Section 05

Solution Architecture

Four building blocks compose to deliver physical credential recovery with information-theoretic security.

HMAC-SHA256 Integrity
Building Block #2
32-byte HMAC key generated per backup
32-byte signature over padded data
Key + signature prepended before split
Verification before reconstruction
Xformat Binary Envelope
Universal Routing
26-byte header: magic + version + product + K/N + UUID
Product type: XRECALL
UUID links shares from same backup
Consistency validation during restore
Base45 QR Encoding
RFC 9285
Alphanumeric QR mode (4.5 bits/char)
Smaller QR codes vs Base64 (6 bits/char)
Charset: 0-9 A-Z $%*+-./:
Optimized for offline scanning
BACKUP PIPELINE
Credentials → JSON serialize → PKCS#7 pad → HMAC sign → XorIDA split → Xformat envelope per share → Base45 encode → QR data
RESTORE PIPELINE
QR data → Base45 decode → Xformat deserialize → validate consistency → XorIDA reconstruct → HMAC verify → PKCS#7 unpad → JSON parse → Credentials
Section 06

Integration Guide

Install, backup, print, and restore in under 20 lines of code.

Installation

npm / pnpm / yarn
npm install @private.me/authrecovery

Backup Credentials

TypeScript
import { backupCredentials } from '@private.me/authrecovery';

// 1. Define credentials to back up
const credentials = [
  {
    type: 'TOTP_SEED',
    issuer: 'GitHub',
    account: 'dev@github.com',
    secret: new Uint8Array([72, 101, 108, 108, 111]),
  },
  {
    type: 'API_KEY',
    issuer: 'Stripe',
    account: 'acct_123',
    secret: new TextEncoder().encode('sk_live_xyzabc'),
    label: 'Production key',
    expiresAt: '2027-12-31T23:59:59Z',
  },
];

// 2. Split into 3 shares, any 2 reconstruct (2-of-3)
const config = {
  n: 3,
  k: 2,
  ownerDid: 'did:key:z6MkOwner123',
};

const backup = await backupCredentials(credentials, config);
if (!backup.ok) throw new Error(backup.error);

// 3. Print each share as a QR code
for (const share of backup.value.shares) {
  console.log(`Share ${share.shareId}/${share.n}: ${share.qrData}`);
  // Use a QR library like 'qrcode' to generate printable QR images
}

Restore Credentials

TypeScript
import { restoreCredentials } from '@private.me/authrecovery';

// 1. Scan any K QR codes
const scannedQrStrings = [
  backup.value.shares[0].qrData,
  backup.value.shares[2].qrData,
];

// 2. Restore credentials
const restore = await restoreCredentials(scannedQrStrings);
if (!restore.ok) throw new Error(restore.error);

console.log(restore.value.credentials);
// [{ type: 'TOTP_SEED', issuer: 'GitHub', ... }, { type: 'API_KEY', ... }]

Optional Passphrase Layer

TypeScript
// Add AES-256-GCM encryption before splitting
const config = {
  n: 3,
  k: 2,
  ownerDid: 'did:key:z6MkOwner123',
  passphrase: 'correct-horse-battery-staple', // PBKDF2 derived
};

const backup = await backupCredentials(credentials, config);
Section 07

Security Model

Six cryptographic guarantees deliver credential recovery with information-theoretic security.

Information-Theoretic Security

XorIDA threshold sharing over GF(2) provides unconditional security. Fewer than K shares reveal zero information about the plaintext, regardless of computational power. This is not "hard to break" — it is mathematically impossible to extract any credential data from K-1 shares, even with infinite compute.

HMAC Before Reconstruction

HMAC-SHA256 integrity verification runs before any credential data is deserialized. The HMAC key and signature are prepended to the padded data before splitting, so they travel with the shares. During restore, the HMAC is verified immediately after reconstruction. Corrupted or tampered shares are rejected before JSON parsing or unpadding. This prevents maliciously crafted shares from triggering parser vulnerabilities.

No Plaintext Persistence

Credentials exist in memory only during backup and restore operations. The library never writes plaintext to disk, network, or any persistent storage. Shares are Base45-encoded for QR code printing, which happens outside the library (via user-provided QR generation tools). The only outputs are in-memory JavaScript values.

Xformat Envelope Routing

Each share is wrapped in a standard Xformat binary envelope with the XRECALL product type. The envelope header contains the IDA5 magic bytes, version, product type, K/N parameters, and a UUID. During restore, all shares must have the same UUID, product type, n, and k. Shares from different backups cannot be mixed. Mismatched product types are rejected before reconstruction.

Consistency Validation

The restore function validates that all provided shares are consistent:

  • → Same UUID (shares from the same backup operation)
  • → Same n and k (same threshold configuration)
  • → Same product type (XRECALL only)
  • → No duplicate share indices

Providing the same share twice is detected and rejected before reconstruction. Mixing shares from different backups returns RECONSTRUCT_FAILED with a mismatch hint.

Optional Passphrase Layer

If a passphrase is provided in the RecoveryConfig, the serialized credentials are encrypted with AES-256-GCM before splitting. The passphrase is derived using PBKDF2 with 600,000 iterations and a random salt. The salt and nonce are prepended to the ciphertext before splitting. During restore, the passphrase is required for decryption. Incorrect passphrase returns RECONSTRUCT_FAILED:BAD_PASSPHRASE.

PHYSICAL SECURITY
Xrecall provides cryptographic security, not physical security. If all K shares are stored in the same physical location, an attacker with physical access can reconstruct the credentials. Distribute shares across geographically and organizationally separate locations (home safe, bank vault, trusted family member, attorney, offshore secure facility).
Section 08

Performance Benchmarks

Sub-millisecond splits for typical credential sets. QR code generation is the bottleneck, not XorIDA.

<1ms
5 credentials, 2-of-3
~2ms
20 credentials, 3-of-5
~8ms
100 credentials, 2-of-2
Credential Count K-of-N Backup Time Restore Time
5 2-of-3 <1ms <1ms
10 2-of-3 ~1ms ~1ms
20 3-of-5 ~2ms ~2ms
50 2-of-2 ~4ms ~4ms
100 2-of-2 ~8ms ~8ms

Benchmarked on Node.js 22.x on Apple M2. QR code generation (via external libraries like qrcode) adds ~10-50ms per share depending on error correction level and size. Base45 encoding is sub-millisecond for all tested payloads.

Section 09

Honest Limitations

Xrecall solves credential recovery. It does not solve physical security, QR code durability, or user error.

Physical Security

If all K shares are stored in the same location, an attacker with physical access can reconstruct the credentials. XorIDA provides information-theoretic security against partial compromise (fewer than K shares), but cannot protect against full compromise (K or more shares from the same backup).

QR Code Durability

Printed QR codes fade over time. Ink degrades, paper yellows, thermal printers fade in months. Use archival-quality paper and ink (acid-free, pigment-based) for long-term storage. Laminating QR codes extends durability but introduces risk of adhesive degradation. Test scannability annually.

No Automatic Rotation

Xrecall backs up credentials as they exist at the moment of backup. If a TOTP seed is rotated or an API key is revoked after backup, the QR shares become stale. Users must manually create new backups after credential rotation. There is no automatic synchronization or update mechanism.

User Error

Xrecall cannot prevent users from storing all shares in one location, printing on thermal paper, or losing K shares simultaneously. The library provides cryptographic guarantees, not operational discipline. Physical distribution and share management are the user's responsibility.

QR Scanner Availability

Restore requires a QR code scanner (smartphone camera, dedicated scanner, webcam with QR library). If no scanner is available during an emergency, the shares cannot be read. Consider storing at least one share in a format that can be manually transcribed (Base45 alphanumeric text is human-readable, though error-prone).

No Cloud Sync

Xrecall has no server, no cloud sync, no remote backup. This is a design feature for privacy, but it means recovery is only possible with physical access to K shares. Lost shares are permanently lost. If K shares are destroyed (fire, flood, theft), the credentials are permanently unrecoverable.

RECOMMENDATION
Use N > K to provide fault tolerance. A 2-of-3 configuration tolerates one lost share. A 3-of-5 configuration tolerates two lost shares. Higher N increases operational complexity but provides more resilience against accidental loss.
Advanced Topics

Developer Reference

Complete error taxonomy and API surface documentation.

Appendix A1

Error Taxonomy

Complete list of error codes, causes, and recovery actions.

Error Code Category Cause
INVALID_CONFIG Configuration General configuration validation error
INVALID_CONFIG:N_TOO_SMALL Configuration n < 2 (minimum 2 shares required)
INVALID_CONFIG:K_TOO_SMALL Configuration k < 2 (minimum 2-of-n threshold)
INVALID_CONFIG:K_EXCEEDS_N Configuration k > n (threshold exceeds total shares)
INVALID_CONFIG:MISSING_OWNER Configuration Empty or whitespace-only ownerDid
INVALID_CREDENTIAL Credential General credential validation error
INVALID_CREDENTIAL:EMPTY_SECRET Credential Credential secret is zero-length Uint8Array
INVALID_CREDENTIAL:MISSING_ISSUER Credential Empty or whitespace-only issuer field
INVALID_CREDENTIAL:MISSING_ACCOUNT Credential Empty or whitespace-only account field
INVALID_CREDENTIAL:UNKNOWN_TYPE Credential Credential type not in valid set (TOTP_SEED, OAUTH_REFRESH, PASSKEY, RECOVERY_CODE, API_KEY, CERTIFICATE)
NO_CREDENTIALS Credential Empty credential array passed to backupCredentials
ENCRYPT_FAILED Encryption AES-256-GCM encryption failure (passphrase mode)
ENCRYPT_FAILED:PASSPHRASE_DERIVATION Encryption PBKDF2 key derivation from passphrase failed
SPLIT_FAILED Split XorIDA split or Xformat envelope serialization failure
HMAC_FAILED Split HMAC-SHA256 generation failure
RECONSTRUCT_FAILED Reconstruct General reconstruction failure (envelope parsing, product mismatch, UUID mismatch, duplicate shares)
RECONSTRUCT_FAILED:HMAC_MISMATCH Reconstruct HMAC integrity check failed — share data corrupted or tampered
RECONSTRUCT_FAILED:INSUFFICIENT_SHARES Reconstruct Fewer than k shares provided to restoreCredentials
RECONSTRUCT_FAILED:DESERIALIZE Reconstruct Credential JSON deserialization or PKCS#7 unpad failure
RECONSTRUCT_FAILED:DECRYPT Decrypt AES-256-GCM decryption failure (passphrase mode)
RECONSTRUCT_FAILED:BAD_PASSPHRASE Decrypt Incorrect passphrase for encrypted backup
Appendix A2

Full API Surface

Complete TypeScript signatures for all exported functions and types.

backupCredentials(credentials: ReadonlyArray<Credential>, config: RecoveryConfig): Promise<Result<RecoveryResult, RecoveryError>>

Splits an array of credentials into K-of-N QR-printable shares using XorIDA. Returns n shares wrapped in Xformat envelopes and Base45-encoded for QR code printing. Pipeline: credentials → JSON serialize → PKCS#7 pad → HMAC sign → XorIDA split → Xformat envelope → Base45 encode.

restoreCredentials(qrShares: ReadonlyArray<string>): Promise<Result<RecoveryReconstructResult, RecoveryError>>

Reconstructs credentials from scanned QR share strings. Pipeline: Base45 decode → Xformat deserialize → validate consistency → XorIDA reconstruct → HMAC verify → PKCS#7 unpad → JSON parse. Returns the original credentials on success.

Types

TypeScript
interface Credential {
  readonly type: 'TOTP_SEED' | 'OAUTH_REFRESH' | 'PASSKEY' | 'RECOVERY_CODE' | 'API_KEY' | 'CERTIFICATE';
  readonly issuer: string;
  readonly account: string;
  readonly secret: Uint8Array;
  readonly label?: string;
  readonly expiresAt?: string; // ISO 8601
}

interface RecoveryConfig {
  readonly n: number;            // Total shares (2-255)
  readonly k: number;            // Threshold (2-n)
  readonly ownerDid: string;     // DID of credential owner
  readonly passphrase?: string;  // Optional AES-256-GCM layer
}

interface RecoveryShare {
  readonly shareId: number;              // 1-based share index
  readonly qrData: string;               // Base45-encoded envelope
  readonly ownerDid: string;
  readonly credentialCount: number;
  readonly n: number;
  readonly k: number;
}

interface RecoveryResult {
  readonly backupId: string;                     // UUID
  readonly shares: ReadonlyArray<RecoveryShare>; // n shares
  readonly credentialCount: number;
  readonly backedUpAt: string;                   // ISO 8601
  readonly ownerDid: string;
}

interface RecoveryReconstructResult {
  readonly backupId: string;                        // UUID from backup
  readonly credentials: ReadonlyArray<Credential>;  // Restored credentials
  readonly restoredAt: string;                      // ISO 8601
}

This document describes @private.me/authrecovery version 0.1.0 as of April 2026. For the latest API documentation and integration examples, see the package README.

Deployment Options

📦

SDK Integration

Embed directly in your application. Runs in your codebase with full programmatic control.

  • npm install @private.me/authrecovery
  • TypeScript/JavaScript SDK
  • Full source access
  • Enterprise support available
Get Started →
🏢

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
Request Quote →

Enterprise On-Premise Deployment

While authRecovery 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.

Contact sales for assessment and pricing →