Loading...
private.me Docs
Get xChange
ACI #15 — KEY TRANSPORT

xChange: XorIDA Key Transport

Replaces KEM key agreement with a random AES-256-GCM key bundled with ciphertext, then split via XorIDA. No lattice assumptions. Unconditionally quantum-safe. ~180x faster than KEM.

~15µs keygen 180x faster than KEM Unconditionally quantum-safe
Section 01

The KEM Bottleneck

ML-KEM-768 key agreement adds ~2,740µs overhead per message. For high-throughput API payloads, this latency dominates total processing time.

Key Encapsulation Mechanisms (KEMs) like ML-KEM-768 (Kyber) rely on the computational hardness of the Module Learning With Errors (MLWE) problem. While considered post-quantum secure, this is a computational assumption — not an unconditional guarantee. A mathematical breakthrough or sufficiently powerful quantum algorithm could invalidate the assumption retroactively.

Every post-quantum messaging platform in production today — Signal (PQXDH), Apple PQ3, Tuta — depends on Kyber lattice assumptions for key agreement. The payload encryption itself (AES or ChaCha) is symmetric, but the key transport layer is the single point of cryptographic assumption. If the lattice breaks, the key breaks, and every message encrypted under that key is exposed.

The Old Way

SENDER Generate keypair ~2,740µs KEM (ML-KEM-768) Lattice assumption MLWE hardness Computational security shared secret RECIPIENT Decapsulate
Industry Status
Every PQ messaging platform — Signal, Apple PQ3, Tuta — depends on Kyber lattice assumptions for key transport. The symmetric encryption (AES/ChaCha) is not the weak point. The key agreement layer is.
Section 02

The xChange Solution

Generate a random AES-256-GCM key, encrypt the payload, bundle key+IV+ciphertext, and split the bundle via XorIDA. Each channel carries a share. No lattice assumptions. Information-theoretic security.

xChange eliminates the key agreement step entirely. Instead of negotiating a shared secret through a computationally hard problem, it generates a fresh random AES-256-GCM key per message using crypto.getRandomValues(). The payload is encrypted with this key, then the key, IV, and ciphertext are bundled together into a single binary blob.

This bundle is then split via XorIDA into N shares distributed across independent channels. No single channel carries enough information to reconstruct the bundle. The security comes from the information-theoretic properties of the split — not from the hardness of any mathematical problem. There is no lattice, no elliptic curve, no factoring assumption. The guarantee holds against unbounded adversaries, including quantum computers of any size.

The New Way

Random Key ~15µs AES-GCM Encrypt Bundle [key||IV||ct] 44+ bytes XorIDA Split K-of-N Share 1 Share 2 Share N
Section 03

Architecture

The xChange bundle format packs the random AES-256-GCM key, initialization vector, and authenticated ciphertext into a single binary envelope that XorIDA splits atomically.

Bundle Format

AES Key bytes 0-31 (32 bytes) IV bytes 32-43 (12 bytes) Ciphertext + Auth Tag bytes 44+ (payload + 16-byte GCM tag)

Data Flow

generateKey() ~15µs xchangeEncrypt AES-GCM XorIDA Split K-of-N Channels Transport Reconstruct XorIDA Decrypt OK
Core API
import { generateXchangeKey, xchangeEncrypt, xchangeDecrypt } from '@private.me/xchange';

// Generate random AES-256-GCM key
const key = await generateXchangeKey();

// Encrypt and bundle
const bundle = await xchangeEncrypt(plaintext, key.value);

// After XorIDA split + reconstruct on other side:
const decrypted = await xchangeDecrypt(reconstructedBundle);
Atomic Bundle
The key, IV, and ciphertext travel together as a single binary blob. XorIDA splits the entire bundle atomically — there is no way to extract the key without reconstructing the full bundle from K shares. The GCM auth tag ensures that any tampering with any byte of the bundle is detected before decryption output is produced.
Section 04

Benchmarks

xChange eliminates KEM overhead entirely. For API-sized payloads, total processing time drops by up to 2x compared to KEM-based competitors.

End-to-End Latency Comparison

PayloadxLink (xChange)TutaSignalApple PQ3
64B (auth token)2.0ms4.2ms5.0ms5.0ms
256B (JSON)1.9ms4.2ms5.0ms5.0ms
1KB (REST)1.9ms4.2ms5.0ms5.0ms
4KB (document)2.5ms4.2ms5.0ms5.0ms

xChange vs KEM Overhead

MetricxChangeKEM (ML-KEM-768)
Key generation~15µs~2,740µs
API latency overhead (10ms)16.2%39.7%
Throughput517 req/s151 req/s
Security modelInformation-theoreticLattice computational
PQ protectionUnconditionalML-KEM assumption

Key Generation: xChange vs KEM

500µs 1,000µs 1,500µs 2,000µs 2,740µs xChange ~15µs KEM ~2,740µs 180x faster
~15µs
Key generation
180x
Faster than KEM
517
Requests/sec
0
Lattice assumptions
Section 05

Security Analysis

xChange achieves information-theoretic confidentiality through XorIDA splitting and authenticated encryption through AES-256-GCM. No computational assumptions are required for the key transport layer.

PropertyMechanismGuarantee
ConfidentialityAES-256-GCM + XorIDA splitInformation-theoretic
IntegrityGCM 16-byte auth tagTamper detection
Key freshnessRandom key per messageNo key reuse
IV uniquenesscrypto.getRandomValues()No nonce reuse
Quantum safetyNo lattice assumptionsUnconditional
Fail-closedAuth tag check before outputNo partial leakage
Information-Theoretic vs Computational
Unlike KEM-based approaches (ML-KEM/Kyber), xChange has zero computational assumptions. The security comes from the XorIDA split — not from the hardness of any mathematical problem. An adversary with unlimited compute, unlimited time, and a quantum computer of any size cannot reconstruct the bundle from fewer than K shares. This is a mathematical impossibility, not a computational difficulty.
Section 06

Integration

xChange is used by @private.me/agent-sdk v4 envelopes for split-channel messaging. When both parties support xChange, it replaces KEM automatically. Fallback to KEM is seamless when the recipient does not advertise xChange support.

The agent SDK auto-selects xChange when the recipient's DID document includes xchange: true in its capabilities. No manual configuration is needed. The sender's agent queries the trust registry, checks capabilities, and routes through xChange or KEM accordingly. This makes the upgrade path zero-friction: deploy xChange support, and all future messages from xChange-capable senders use the faster, unconditionally secure path.

v4 Envelope via Agent SDK
// Agent auto-selects xChange when recipient supports it
const result = await alice.send({
  to: bob.did,
  payload: { msg: 'secured via xChange' },
  scope: 'email:send',
  splitChannel: true,
  splitChannelConfig: { totalShares: 3, threshold: 2 },
});
// Produces 3 v4 envelopes with kem: 'xChange'
Backward Compatibility
When the recipient does not support xChange (no xchange: true capability), the agent SDK falls back to v2/v3 envelopes using ML-KEM-768 + X25519 hybrid KEM. Existing deployments continue to work without any changes. xChange is an additive upgrade, not a breaking change.
Section 07

Enhanced Identity with Xid

xChange can optionally integrate with Xid to enable unlinkable key transport — verifiable within each exchange context, but uncorrelatable across sessions, parties, or time.

Three Identity Modes

Basic (Default)
Static Party DIDs
One DID per party, persistent across all key exchanges and sessions. Simple, but linkable — same identities can be tracked across exchanges, peers, and time.
Current xChange behavior
xChange+ (With Xid)
Ephemeral Per-Exchange DIDs
Each key exchange gets unique party DIDs derived from XorIDA-split master seeds. DIDs are unlinkable across sessions and rotate per epoch. Verifiable within exchange context, but cross-session correlation is impossible. ~50µs overhead per exchange.
Unlinkable key agreement
xChange Enterprise
K-of-N High-Assurance Key Agreement
Require 3-of-5 signals (biometric + device TPM + location + time + YubiKey) to authorize key exchange. IAL2/3 assurance levels for classified communications, financial transactions, or defense systems. Continuous refresh ensures only authorized parties can establish shared secrets.
IAL2/3 compliance

How Ephemeral Key Exchange Works

Key Transport Workflow (xChange+ with Xid)
// Initialize xChange with Xid integration
import { XchangeClient } from '@private.me/xchange-cli';
import { XidClient } from '@private.me/xid';

const xid = new XidClient({ mode: 'ephemeral' });
const xchange = new XchangeClient({ identityProvider: xid });

// Each exchange derives unlinkable DIDs automatically
const { key, envelope } = await xchange.send(payload);
  → [xChange] Deriving ephemeral sender DID from master seed...
  → [xChange] Sender DID: did:key:z6MkH... (unique to this exchange + epoch)
  → [xChange] XorIDA-split AES key with ephemeral identity (~50µs)
  → [xChange] Key purged (<1ms exposure)

// Exchange is unconditionally secure with unlinkable DIDs
// Verification works within session, but cross-session correlation fails
Integration Pattern
xChange+ is not a new ACI — it's an integration of two existing ACIs (xChange + Xid). This demonstrates ACI composability — building blocks combine to create enhanced capabilities without requiring new primitives.

See the Xid white paper for details on ephemeral identity primitives and K-of-N convergence.

Market Positioning

Industry Use Case Compliance Driver
IoT Sensor network key exchange with unlinkable device identities GDPR, ePrivacy, IoT Security Act
Software Licensing (Anti-Piracy) Unlinkable license key distribution to customer devices. Each activation derives ephemeral DIDs — prevents key tracking, blacklisting, and resale. Vendor ships to customers without exposing licensing infrastructure to piracy attacks. IP protection, revenue assurance
Defense Tactical communications with IAL3 party authentication FISMA, DoD IL5/6, CMMC Level 3
Finance Payment network key agreement with PCI-compliant unlinkability PCI-DSS, EMV, SWIFT CSP

Key Benefits

  • Cross-session unlinkability — Can't track parties across exchanges
  • Per-exchange derivation — Same party has different DIDs per key agreement
  • Epoch rotation — DIDs automatically rotate daily/weekly/monthly
  • Split-protected derivation — Master seed is XorIDA-split, never reconstructed
  • Single IT layer — ~180x faster than split-channel with hybrid PQ KEM
  • IoT-optimized — ~1ms roundtrip for resource-constrained devices
Section 08

API Reference

Three functions compose the entire xChange surface. Generate a key, encrypt a payload into a bundle, decrypt a bundle back to plaintext.

generateXchangeKey(): Promise<Result<XchangeKey, XchangeError>>
Generates a random AES-256-GCM key (32 bytes) using crypto.getRandomValues(). Returns a Result wrapping the key material. The key is single-use — generate a fresh key for every message.
xchangeEncrypt(plaintext: Uint8Array, key: XchangeKey): Promise<Result<Uint8Array, XchangeError>>
Encrypts the plaintext with AES-256-GCM using the provided key, then bundles the key (32 bytes), IV (12 bytes), and ciphertext+auth tag into a single Uint8Array. The bundle is ready for XorIDA splitting.
xchangeDecrypt(bundle: Uint8Array): Promise<Result<Uint8Array, XchangeError>>
Extracts the AES key and IV from the bundle header, then decrypts the ciphertext with GCM auth tag verification. Fails closed if the auth tag does not match — no partial plaintext is ever returned. Rejects bundles shorter than 44 bytes.

Error Codes

CodeTriggerRecovery
XCHANGE_KEYGEN_FAILEDcrypto.getRandomValues() unavailableCheck runtime environment supports Web Crypto
XCHANGE_ENCRYPT_FAILEDAES-GCM encryption errorVerify key and plaintext are valid Uint8Array
XCHANGE_DECRYPT_FAILEDGCM auth tag mismatchBundle was tampered — reject and request retransmission
INVALID_BUNDLE:TOO_SHORTBundle < 44 bytes (missing header)Verify bundle was not truncated during transport

Constants

NameValueDescription
AES_KEY_BYTES32AES-256-GCM key length
AES_IV_BYTES12GCM initialization vector length
BUNDLE_HEADER_BYTES44Key (32) + IV (12) = minimum bundle size
DEVELOPER EXPERIENCE

UX Enhancements

Session 64 UX standardization added progress tracking and detailed error handling to all xChange operations. Real-time progress callbacks and actionable error hints improve developer experience.

Progress Callbacks

All three core functions now accept optional ProgressCallback parameters that provide real-time status updates during operations. Useful for long-running operations or UI progress indicators.

Progress Tracking Example
import { generateXchangeKey, xchangeEncrypt } from '@private.me/xchange';

// Key generation with progress
const key = await generateXchangeKey({
  onProgress: (status, percent) => {
    console.log(`[${percent}%] ${status}`);
  }
});
// [0%] Generating AES-256-GCM key...
// [50%] Importing key material...
// [100%] Complete

// Encryption with progress
const bundle = await xchangeEncrypt(plaintext, key.value, {
  onProgress: (status, percent) => {
    console.log(`[${percent}%] ${status}`);
  }
});
// [0%] Preparing bundle encryption...
// [30%] Encrypting plaintext with AES-256-GCM...
// [70%] Bundling key + IV + ciphertext...
// [100%] Complete

Detailed Error Information

The createXchangeErrorDetail function converts error codes into user-friendly messages with actionable hints, field attribution, and documentation links. All errors follow a standardized format across the PRIVATE.ME platform.

Error Handling Example
import { xchangeDecrypt, createXchangeErrorDetail } from '@private.me/xchange';

const result = await xchangeDecrypt(bundle);

if (!result.ok) {
  const error = createXchangeErrorDetail(result.error);

  console.log(error.message); // User-friendly error message
  console.log(error.hint);    // Actionable resolution hint
  console.log(error.field);   // Field that caused error (if applicable)
  console.log(error.docs);    // Documentation URL
}

Error Details Map

All error codes map to structured error details with user-friendly messages, resolution hints, and documentation links:

CodeMessageHint
XCHANGE_KEYGEN_FAILED AES-256-GCM key generation failed crypto.getRandomValues or Web Crypto API unavailable. Ensure running in secure context (HTTPS).
XCHANGE_ENCRYPT_FAILED Bundle encryption failed AES-256-GCM encryption failed. Check key is valid and Web Crypto API is available.
XCHANGE_DECRYPT_FAILED Bundle decryption failed AES-256-GCM decryption failed. Data may be corrupted, tampered, or encrypted with different key.
INVALID_BUNDLE Bundle format is invalid or unrecognized Bundle data is corrupted or not a valid Xchange bundle. Check bundle reconstruction.
INVALID_BUNDLE:TOO_SHORT Bundle is too short (minimum 60 bytes required) Bundle must contain at least 32B key + 12B IV + 16B auth tag. Check XorIDA reconstruction produced full bundle.

Integration Pattern: Progress + Error Handling

Complete Example
import {
  generateXchangeKey,
  xchangeEncrypt,
  xchangeDecrypt,
  createXchangeErrorDetail
} from '@private.me/xchange';
import { split, reconstruct } from '@private.me/shareformat';

async function sendSecureMessage(plaintext: Uint8Array) {
  // Generate key with progress
  const keyResult = await generateXchangeKey({
    onProgress: (status, percent) => updateUI(status, percent)
  });

  if (!keyResult.ok) {
    const error = createXchangeErrorDetail(keyResult.error);
    throw new Error(`${error.message}: ${error.hint}`);
  }

  // Encrypt with progress
  const bundleResult = await xchangeEncrypt(plaintext, keyResult.value, {
    onProgress: (status, percent) => updateUI(status, percent)
  });

  if (!bundleResult.ok) {
    const error = createXchangeErrorDetail(bundleResult.error);
    throw new Error(`${error.message}: ${error.hint}`);
  }

  // Split via XorIDA (2-of-3)
  const shares = split(bundleResult.value, { k: 2, n: 3 });

  // Transport shares...
  return shares;
}
VERIFIED BY XPROVE

Verifiable Data Protection

Every operation in this ACI produces a verifiable audit trail via xProve. HMAC-chained integrity proofs let auditors confirm that data was split, stored, and reconstructed correctly — without accessing the data itself.

XPROVE AUDIT TRAIL
Every XorIDA split generates HMAC-SHA256 integrity tags. xProve chains these into a tamper-evident audit trail that proves data was handled correctly at every step. Upgrade to zero-knowledge proofs when regulators or counterparties need public verification.

Read the xProve white paper →
Section 08

Use Cases

Four deployment patterns where xChange’s sub-millisecond latency unlocks capabilities that traditional encryption cannot support.

IoT
Fleet Telemetry
Finance
API Security
Edge AI
Model Inference
Chat
Real-time Messaging
Use CaseWhy xChangeKey Metric
IoT fleet telemetrySub-millisecond split means sensor data is protected without adding measurable latency to telemetry pipelines. Traditional TLS handshakes add 50–200ms per connection.~1ms send/recv vs ~150ms TLS
Financial API securityInformation-theoretic security for high-frequency trading data. No lattice assumptions, no key compromise risk. Regulatory compliance (DORA Article 9) via split-storage.<1ms per API payload
Edge AI model inferenceProtect inference requests and responses at the edge without GPU overhead. XorIDA splitting is CPU-only and parallelizable across cores.~35µs for 256B inference payload
Real-time messaging180x faster than split-channel V3. Users experience zero perceptible encryption delay. Group messages split once, delivered per-recipient.~1ms vs ~180ms (V3 with PQ sigs)
VERIFIABLE WITHOUT CODE EXPOSURE

Ship Proofs, Not Source

xChange generates cryptographic proofs of correct execution without exposing proprietary algorithms. Verify integrity using zero-knowledge proofs — no source code required.

XPROVE CRYPTOGRAPHIC PROOF
Download proofs:

Verify proofs online →

Use Cases

🏛️
REGULATORY
FDA / SEC Submissions
Prove algorithm correctness for key transport without exposing trade secrets or IP.
Zero IP Exposure
🏦
FINANCIAL
Audit Without Access
External auditors verify unconditionally secure key exchange without accessing source code or production systems.
FINRA / SOX Compliant
🛡️
DEFENSE
Classified Verification
Security clearance holders verify key transport correctness without clearance for source code.
CMMC / NIST Ready
🏢
ENTERPRISE
Procurement Due Diligence
Prove security + correctness during RFP evaluation without NDA or code escrow.
No NDA Required
Section 09

Honest Limitations

Five known limitations documented transparently. xChange optimizes for speed by trading off features that split-channel V3 provides.

LimitationImpactMitigation
No per-message forward secrecyxChange uses a single AES-256-GCM session key for all messages. Compromising the key compromises all messages in the session, not just one.Session keys are XorIDA-split — compromise requires both shares simultaneously. For forward secrecy, use split-channel V3 (separate KEM per message).
Fixed 256-bit AES keyThe session key is always AES-256-GCM. No algorithm agility — cannot switch to ChaCha20 or other ciphers without protocol changes.AES-256-GCM is NIST-approved and hardware-accelerated on all modern CPUs. The XorIDA split layer provides information-theoretic security regardless of the symmetric cipher.
2-of-2 only — no fault tolerancexChange splits into exactly 2 shares. If either share is lost, the message is unrecoverable. No redundancy.For fault-tolerant delivery, use split-channel V3 with 2-of-3 or 3-of-5 configurations. xChange prioritizes speed over redundancy.
No key negotiation (transport only)xChange is a transport protocol, not a key agreement protocol. It requires an existing authenticated channel (xLink) for initial key exchange.xLink handles identity, authentication, and key agreement. xChange handles fast data transport. The separation of concerns is intentional.
Single-threaded throughputCurrent implementation processes messages sequentially. High-throughput scenarios (>10K msg/sec) may hit Node.js event loop limits.XorIDA splitting is CPU-bound and parallelizable. Worker thread pool implementation is planned for high-throughput deployments.
ENTERPRISE DEPLOYMENT

xChange Enterprise CLI

Self-hosted key transport server. Deploy xChange on your own infrastructure with Docker-ready, air-gapped capable deployment.

xchange-cli — Port 4900
@private.me/xchange-cli wraps the xChange library in a standalone HTTP server with 9 REST endpoints. 93 tests, all passing. Key generation, encrypt/decrypt lifecycle, bundle management. 3-role RBAC (admin/operator/auditor), JSONL audit, AES-256-GCM at rest, rate limiting. Zero external dependencies. Part of the Enterprise CLI Suite — 21 self-hosted servers, 1,924 tests.

Features

Standalone HTTP server on port 4900 with 9 REST endpoints covering the complete key transport lifecycle. Built-in RBAC with three roles (admin, operator, auditor), JSONL-based audit logging, and sliding-window rate limiting (1,000 req/min per API key). All state stored in AES-256-GCM encrypted JSONL files for air-gap compatibility.

API Endpoints

EndpointMethodRolePurpose
/healthGETPublicServer health check (uptime, version)
/keys/generatePOSTOperatorGenerate random AES-256-GCM key
/encryptPOSTOperatorEncrypt plaintext and create bundle
/decryptPOSTOperatorDecrypt bundle to plaintext
/keys/:idGETOperatorRetrieve stored key by ID
/keys/:idDELETEAdminDelete stored key
/auditGETAuditorQuery audit log (filter by action, user, date)
/apikeys/createPOSTAdminCreate new API key with role assignment
/apikeys/revokePOSTAdminRevoke existing API key

RBAC Roles

  • Admin: Create/revoke API keys, delete stored keys, full system control
  • Operator: Generate keys, encrypt/decrypt, read keys, normal operations
  • Auditor: Read-only access to audit logs, compliance review

Deployment

Docker Compose
version: '3.8'
services:
  xchange:
    image: privateme/xchange-cli:latest
    ports:
      - "4900:4900"
    volumes:
      - ./data:/data
    environment:
      - XCHANGE_PORT=4900
      - XCHANGE_DATA_DIR=/data
      - ADMIN_API_KEY=${ADMIN_KEY}

Air-gap deployment: JSONL stores persist to local filesystem. No external database dependencies. Keys encrypted at rest with AES-256-GCM derived from admin API key. Rate limiter tracks per-key request windows in memory (survives restarts via JSONL replay).

Security Features

  • API key authentication: All endpoints (except /health) require Bearer token
  • Rate limiting: 1,000 requests per minute per API key (sliding window)
  • Audit logging: Every operation logged to JSONL with timestamp, user, action, outcome
  • Encrypted storage: Keys stored AES-256-GCM encrypted in JSONL files
  • TTL expiry: Keys auto-expire after configurable duration (default 24h)
  • Zero external deps: Runs offline, no database, no Redis, no external services
DEVELOPER EXPERIENCE

Fast Onboarding: 3 Acceleration Levels

Start transporting keys in under 2 minutes. Three acceleration levels: Node.js starter, serverless edge function, or one-click multi-platform deploy.

Level 1: Node.js TypeScript Starter

Clone and run. Demonstrates full Xchange lifecycle: key generation, encrypt, bundle, split, reconstruct, decrypt.

packages/xchange/templates/node-typescript
# Install dependencies
npm install

# Run demo
npm run dev

# Output:
# 🔑 Generating key...
#    [0%] Generating AES-256-GCM key...
#    [100%] Complete
# 🔐 Encrypting and bundling...
#    [0%] Preparing bundle encryption...
#    [30%] Encrypting plaintext with AES-256-GCM...
#    [100%] Complete
# 🔀 Splitting bundle (2-of-3)...
# ✅ Created 3 shares
# 📡 Simulating multi-channel transport:
#    Share 0: 128 bytes → Email
#    Share 1: 128 bytes → SMS
#    Share 2: 128 bytes → Messenger
src/index.ts — Core Usage Pattern
import {
  generateXchangeKey,
  xchangeEncrypt,
  xchangeDecrypt,
} from '@private.me/xchange';
import { split, reconstruct } from '@private.me/shareformat';

// 1. Generate random AES-256-GCM key
const keyResult = await generateXchangeKey();

// 2. Encrypt plaintext and bundle key + ciphertext
const plaintext = new TextEncoder().encode('Secret message');
const bundleResult = await xchangeEncrypt(plaintext, keyResult.value);

// 3. Split bundle via XorIDA (2-of-3 threshold)
const shares = split(bundleResult.value, { k: 2, n: 3 });

// 4. Transport shares via different channels
await sendViaEmail(recipient, shares[0]);
await sendViaSMS(recipient.phone, shares[1]);
await sendViaMessenger(recipient.id, shares[2]);

// 5. Reconstruct (any 2 shares)
const reconstructed = reconstruct([shares[0], shares[2]]);

// 6. Decrypt bundle
const decryptResult = await xchangeDecrypt(reconstructed);
const decrypted = new TextDecoder().decode(decryptResult.value);
// → "Secret message"
Performance
Total overhead: ~3-4 ms (key gen ~1 ms + encrypt ~1 ms + split ~0.5 ms + reconstruct ~0.3 ms + decrypt ~1 ms). Compare to hybrid PQ KEM: ~220 ms. That's ~60x faster for the complete encrypt-split-reconstruct-decrypt cycle.

Level 2: Vercel Edge Function

Deploy to Vercel in ~15 seconds. REST API with encrypt/decrypt endpoints. Automatic scaling, global edge network.

packages/xchange/templates/vercel
# Deploy to Vercel
npm i -g vercel
vercel deploy --prod

# Your Xchange API is live at:
# https://your-app.vercel.app/api/xchange
api/xchange.ts — Edge Function
import { generateXchangeKey, xchangeEncrypt } from '@private.me/xchange';
import { split } from '@private.me/shareformat';

export default async function handler(req, res) {
  const { action, data, shares } = req.body;

  if (action === 'encrypt') {
    const plaintext = new TextEncoder().encode(data);
    const keyResult = await generateXchangeKey();
    const bundleResult = await xchangeEncrypt(plaintext, keyResult.value);

    // Split into shares (2-of-3 configurable)
    const threshold = parseInt(process.env.XCHANGE_THRESHOLD || '2');
    const totalShares = parseInt(process.env.XCHANGE_TOTAL_SHARES || '3');
    const splitShares = split(bundleResult.value, { k: threshold, n: totalShares });

    res.json({ ok: true, shares: splitShares, threshold, totalShares });
  }
}
Usage
# Encrypt data
curl -X POST https://your-app.vercel.app/api/xchange \
  -H "Content-Type: application/json" \
  -d '{"action":"encrypt","data":"Secret message"}'

# Returns:
{
  "ok": true,
  "shares": [[...], [...], [...]],
  "threshold": 2,
  "totalShares": 3
}
~15s
Setup time
50-100ms
Cold start
10-20ms
Warm response
FREE
100GB/month

Level 3: One-Click Multi-Platform Deploy

GitHub starter repo with pre-configured deployment buttons for Vercel, Netlify, Railway. Platform-agnostic handler, deploy to any serverless provider in ~15-30 seconds.

packages/xchange/templates/github-starter
# Clone starter repo
git clone https://github.com/private-me/xchange-starter.git
cd xchange-starter

# Option 1: Deploy to Vercel (click button in README)
# Option 2: Deploy to Netlify (click button in README)
# Option 3: Deploy to Railway (click button in README)

# Or run locally:
npm install
npm run dev:vercel  # or dev:netlify
src/handler.ts — Platform-Agnostic Logic
import { generateXchangeKey, xchangeEncrypt, xchangeDecrypt }
  from '@private.me/xchange';
import { split, reconstruct } from '@private.me/shareformat';

export async function handleXchangeRequest(request) {
  const { action, data, shares } = request;

  if (action === 'encrypt') {
    const plaintext = typeof data === 'string'
      ? new TextEncoder().encode(data)
      : new Uint8Array(data);

    const keyResult = await generateXchangeKey();
    const bundleResult = await xchangeEncrypt(plaintext, keyResult.value);

    const threshold = parseInt(process.env.XCHANGE_THRESHOLD || '2');
    const totalShares = parseInt(process.env.XCHANGE_TOTAL_SHARES || '3');
    const splitShares = split(bundleResult.value, { k: threshold, n: totalShares });

    return { ok: true, shares: splitShares, threshold, totalShares };
  }

  if (action === 'decrypt') {
    const shareBuffers = shares.map(s => new Uint8Array(s));
    const bundle = reconstruct(shareBuffers);
    const decryptResult = await xchangeDecrypt(bundle);
    const plaintext = new TextDecoder().decode(decryptResult.value);
    return { ok: true, data: plaintext };
  }
}
PlatformSetup TimeCold StartFree Tier
Vercel~15 seconds~50-100ms100GB bandwidth/month
Netlify~20 seconds~100-150ms100GB bandwidth/month
Railway~30 seconds~150-250ms$5 credit/month
AWS Lambda~60 seconds~200-400ms1M requests/month
Template Locations
All three templates live in packages/xchange/templates/:
  • node-typescript/ — Local development starter (Level 1)
  • vercel/ — Vercel Edge Function (Level 2)
  • github-starter/ — Multi-platform deploy (Level 3)
Each includes README with full setup instructions, environment variable configuration, and platform-specific deployment guides.

Why Fast Onboarding Matters

Xchange competes with established KEM solutions (ML-KEM-768, X25519). The performance advantage (~180x faster) is only valuable if developers can try it immediately. Three acceleration levels serve three developer profiles:

  • Level 1 (Node.js): Backend engineers who want to understand the full encrypt-split-reconstruct-decrypt cycle before committing.
  • Level 2 (Vercel): Full-stack developers who need a production-ready REST API in under a minute. Edge deployment, auto-scaling.
  • Level 3 (Multi-platform): DevOps teams evaluating multiple cloud providers. Same handler logic, different runtime wrappers.

Traditional KEM integration requires key generation, trust anchor setup, certificate management, and integration testing. Xchange eliminates all of that. Generate a random key, bundle with ciphertext, split, send. No PKI, no trust anchors, no key escrow. The simplicity is the feature.

GET STARTED

Ready to deploy xChange?

Talk to Ren, our AI sales engineer, or book a live demo with our team.

Book a Demo

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/xchange
  • 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 →