xTrust: Trust Registry & Key Verification
Trust-on-first-use, mutual key verification ceremonies, append-only transparency logs, and continuity-proven key rotation. xTrust makes identity binding automatic, auditable, and tamper-evident.
The Problem
Every secure channel starts with one question: whose key is this? Get the answer wrong and nothing that follows matters — encryption protects the wrong conversation.
Conventional PKI solves identity binding with certificate authorities. But CAs are centralized trust anchors. One compromised CA invalidates every certificate it ever issued. The 2011 DigiNotar breach, the 2015 CNNIC incident, and the ongoing Let's Encrypt phishing certificate problem all demonstrate the same structural failure: delegated trust collapses at scale.
PGP's Web of Trust tried to decentralize the problem but created its own: key signing parties, manual fingerprint comparison, incomprehensible trust paths, and a UX so hostile that even security researchers get it wrong. After three decades, PGP adoption among non-specialists remains negligible.
Modern messengers like Signal improved the UX with safety numbers, but the verification model is still manual, optional, and per-conversation. Most users never verify. When a contact changes devices, Signal silently accepts the new key with a small notification that most users dismiss.
Key rotation makes everything worse. When a user gets a new phone, their old key pair is gone. Every contact must re-verify. Most systems handle this by silently accepting the new key — the exact behavior an attacker would exploit. Without cryptographic continuity proofs, there is no way to distinguish a legitimate device change from a man-in-the-middle attack.
The Old Way
The PRIVATE.ME Solution
xTrust replaces centralized certificate authorities with a four-layer trust stack: automatic TOFU registration, mutual SAS verification ceremonies, append-only transparency logs, and continuity-proven key rotation.
When a contact's public key is first encountered, xTrust accepts it automatically with TOFU (Trust on First Use) trust level and records the event in a SHA-256 hash-chained transparency log. If the key is seen again, it matches. If a different key appears for the same identity, xTrust raises a FINGERPRINT_CONFLICT warning — the cryptographic equivalent of "this person's identity has changed."
Trust can be upgraded from tofu to verified via a mutual key verification ceremony. Both parties derive a 6-word Short Authentication String (SAS) from their fingerprints using HMAC-SHA256. They compare the SAS over a separate channel (in person, phone, video). If the words match, the key binding is cryptographically confirmed.
When keys rotate (new device, scheduled rotation, key compromise), the old private key signs the new public key to create a continuity proof. Contacts can verify the rotation was authorized by the key holder, not a MITM attacker. A configurable grace period (default 7 days) accepts both old and new keys during transition.
Every trust-relevant event — key registration, SAS verification, rotation, revocation — is recorded in an append-only transparency log where each entry is SHA-256 hash-chained to the previous. Tampering with any entry breaks the chain. Auditors can verify the complete key history for any contact without accessing message content or key material.
The New Way
Architecture
Four modules, each handling one dimension of trust. They compose together but each works independently.
Module 1: TofuManager
Manages trust-on-first-use for contacts. When processKey(email, fingerprint) is called, TofuManager checks its in-memory contact map. New keys are accepted with tofu trust level. Matching keys return the existing trust state. Changed keys return FINGERPRINT_CONFLICT — the application decides whether to warn the user or auto-reject. Trust can be upgraded to verified via upgradeTrust(email, fingerprint) after a successful verification ceremony.
Module 2: Key Verification Ceremony
Implements QR code + Short Authentication String (SAS) verification for mutual key confirmation. Both parties' public key fingerprints are computed via SHA-256, then fed into HMAC-SHA256 to derive a 6-word human-readable SAS from a 256-word PGP-style wordlist. A challenge is created with a 15-minute TTL, a unique ID from crypto.getRandomValues(), and QR data encoding both fingerprints. Both parties compare the SAS phrase over a separate channel. If they match, the key binding is confirmed.
The SAS wordlist uses a PGP-style approach where each byte maps to one of 256 words (e.g., "aardvark", "arctic", "beacon", "cipher", "glacier"). Six words provide 48 bits of entropy — enough for a human to compare in under 10 seconds. The probability of a MITM attacker guessing the correct SAS is 1 in 281 trillion.
Module 3: KeyTransparencyLog
Append-only cryptographic log where every key event (registration, rotation, verification, revocation) is recorded with a SHA-256 hash chain linking each entry to the previous one. Each entry contains the contact email, public key fingerprint, action type, timestamp, and optional metadata. verifyChain(contactEmail) walks the chain and confirms every previousEntryHash is correct. If any entry has been tampered with, the chain breaks.
Module 4: KeyRotationManager
Handles key rotation with continuity proofs. When a contact rotates their key pair, the old private key signs the new public key using ML-DSA-65 (FIPS 204 post-quantum signature). The initiateRotation() method verifies the continuity proof, computes fingerprints for both keys, logs the event to the transparency log, and starts a configurable grace period (default 7 days). During the grace period, both the old and new fingerprints are accepted by isAccepted().
crypto.getRandomValues() for all random data. Result<T, E> pattern for typed error handling. No exceptions thrown in library code.
Competitive Failure Analysis
Every trust model makes tradeoffs. Here is where each one fails — and how xTrust avoids the same failure modes.
| System | Trust Model | Key Rotation | Transparency | UX Burden | Failure Mode |
|---|---|---|---|---|---|
| PGP Web of Trust | Transitive signatures | Manual revocation | × None | Key signing parties | Unusable for non-experts |
| Signal Protocol | TOFU + safety numbers | Silent accept | × None | Manual QR scan (optional) | Key changes silently accepted |
| Matrix / Vodozemac | Cross-signing + TOFU | Device-level | × None | Emoji verification | Complex device trust graph |
| X.509 / PKI | Centralized CA hierarchy | Certificate renewal | ✓ CT logs | None (delegated) | CA compromise = total breach |
| Certificate Transparency | Append-only CA logs | N/A (audit only) | ✓ Merkle tree | Monitor-only | Detects but does not prevent |
| xTrust | TOFU + SAS + transparency | Continuity proof + grace | ✓ SHA-256 chain | 6-word phrase (optional) | See Limitations section |
Benchmarks
Trust operations are fast enough to be invisible. Key lookups are sub-microsecond. Verification ceremonies complete in milliseconds. Transparency log audits scale linearly with chain length.
| Operation | Latency | Notes |
|---|---|---|
| TOFU key lookup | < 0.1 ms | In-memory Map<string, ContactTrust> |
| TOFU key registration | < 1 ms | Map insert + transparency log append |
| SHA-256 fingerprint | ~50 µs | Web Crypto exportKey + digest |
| SAS derivation (HMAC-SHA256) | ~80 µs | HMAC of concatenated fingerprints |
| Challenge creation | ~200 µs | 2 fingerprints + SAS + QR data |
| Transparency log append | ~100 µs | SHA-256 hash chain link |
| Chain verification (100 entries) | ~10 ms | Linear scan with hash recomputation |
| Chain verification (1,000 entries) | ~95 ms | One SHA-256 per entry |
| ML-DSA-65 continuity sign | ~2 ms | Old key signs new key SPKI |
| ML-DSA-65 continuity verify | ~0.5 ms | Verify signature on new key SPKI |
| Key rotation initiation | ~3 ms | Verify + fingerprint + log + record |
| Grace period check | < 0.1 ms | In-memory array scan + Date.now() |
Measured on commodity hardware (4-core, 3.2 GHz). Web Crypto API for SHA-256 and HMAC. ML-DSA-65 via mldsa-wasm. All operations single-threaded.
ACI Surface
Eight core functions organized into four modules. Every function returns Result<T, TrustError> or a simple value — no exceptions thrown.
TofuManager
tofu to verified trust level after a successful SAS verification ceremony. Logs the event to the transparency log.Key Verification
crypto.getRandomValues().Transparency Log
Key Rotation
Use Cases
Automatically register contact keys on first encounter. Upgrade to verified trust via in-person SAS comparison. Detect key changes that could indicate MITM attacks.
TOFU + SASEvery key event is recorded in a tamper-evident transparency log. Auditors can verify the complete key history for any contact without accessing message content.
Transparency LogRotate keys with cryptographic continuity proofs. The old key signs the new key, proving the rotation is authorized. Grace periods prevent message loss during transition.
Continuity ProofBind DID-based service identities to their signing keys. TOFU accepts the first key per DID, transparency logs record every rotation, and automated SAS can be verified programmatically.
M2M TrustProve that encryption keys used for legal holds were the correct keys for the stated identities. Transparency logs provide an immutable record of key provenance.
Legal HoldVerify that the public key used to encrypt patient data belongs to the stated healthcare provider. SAS ceremonies can be conducted during onboarding. Key rotation is logged for HIPAA audits.
HIPAA AuditRegulatory Alignment
xTrust addresses key management requirements across major compliance frameworks. The transparency log provides the audit trail that regulators demand.
| Framework | Requirement | xTrust Control |
|---|---|---|
| eIDAS 2.0 | Qualified trust service provider key management | TOFU + SAS verification ceremony. Hash-chained transparency log for key lifecycle audit. |
| NIST SP 800-57 | Key management lifecycle (generation, distribution, rotation, destruction) | Full lifecycle coverage: registration (processKey), verification (SAS), rotation (continuity proof), revocation (transparency log action). |
| NIST SP 800-63 | Digital identity assurance levels (IAL/AAL/FAL) | TOFU provides IAL1. SAS verification provides IAL2-equivalent out-of-band confirmation. Continuity proofs maintain assurance across key rotation. |
| DORA (EU) | ICT risk management: cryptographic key controls and audit trails | Append-only transparency log with SHA-256 chain. verifyChain() for integrity audit. All key events timestamped and immutable. |
| SOC 2 Type II | CC6.1 Logical access controls, CC6.6 External threats | Key verification ceremony for access binding. FINGERPRINT_CONFLICT detection for threat alerting. Grace period rotation for continuity. |
| ISO 27001 | A.10 Cryptographic controls, A.14 System acquisition | Web Crypto API for SHA-256 and HMAC-SHA256. ML-DSA-65 (FIPS 204) via mldsa-wasm for continuity proofs. No custom primitives. |
| HIPAA | 164.312(a) Access control, 164.312(e) Transmission security | Key identity verification before encrypted data exchange. Transparency log provides audit trail for key provenance. |
Cross-ACI Integration
xTrust is the identity binding layer that other ACIs depend on. When an ACI needs to know whose key it is talking to, xTrust provides the answer.
xBind (Agent SDK)
Every xBind channel begins with a DID handshake. xTrust's TofuManager registers the remote DID's signing key on first connection. Subsequent connections verify the key matches. If the remote agent rotates their key, the continuity proof is verified before the channel is established. The transparency log records every key event for every xBind peer.
xFuse (Threshold Identity Fusion)
xFuse's verify step in the 5-stage pipeline calls xTrust to confirm that each signal provider's key is trusted before accepting their identity signals. A FINGERPRINT_CONFLICT from xTrust halts the pipeline — the system will not fuse identity signals from an unverified source.
xID (Digital Identity)
xID's ephemeral DIDs are derived from a master seed, but verifiers need to confirm the DID belongs to the claimed identity. xTrust's transparency log records the binding between each DID and the master public key. When a DID rotates (epoch-based), the continuity proof is logged and the grace period prevents verification failures during transition.
xGate (Rate Limiting)
xGate's PerDidLimiter uses DID identifiers as rate limit keys. xTrust resolves whether a DID is trusted, verified, or unknown — enabling different rate limits per trust level. Verified contacts might get higher limits while TOFU contacts get stricter throttling.
xLock (Push Authentication)
xLock's push-based 1-tap authentication relies on device key binding. xTrust's TOFU registration accepts the device key on first setup. When a user gets a new device, the old device signs the new device's key via xTrust's continuity proof, allowing a seamless device transition without requiring the user to re-verify on every service.
import { TofuManager, KeyTransparencyLog } from '@private.me/xtrust'; import { Agent } from '@private.me/xbind'; // Initialize trust registry const log = new KeyTransparencyLog(); const tofu = new TofuManager(log); // On xBind channel open, verify remote agent's key const result = await tofu.processKey( remoteDid, remoteFingerprint ); if (!result.ok) { // FINGERPRINT_CONFLICT: key changed unexpectedly throw new Error(`Trust violation: ${result.error.message}`); }
Security Properties
| Property | Mechanism | Guarantee |
|---|---|---|
| Key identity | SHA-256 fingerprint (SPKI export) | ✓ Collision-resistant binding |
| Mutual verification | HMAC-SHA256 SAS (6-word phrase) | ✓ Out-of-band confirmation |
| Tamper detection | SHA-256 hash chain | ✓ Any modification breaks chain |
| Rotation continuity | ML-DSA-65 signature (FIPS 204, post-quantum) | ✓ Old key authorizes new key |
| Random generation | crypto.getRandomValues() | ✓ CSPRNG for IDs and challenges |
| Key change detection | FINGERPRINT_CONFLICT error | ✓ MITM warning on key swap |
| Challenge expiration | 15-minute TTL | ✓ Time-bounded verification |
| Error handling | Result<T, TrustError> | ✓ No thrown exceptions in library |
Ship Proofs, Not Source
xTrust generates cryptographic proofs of correct execution without exposing proprietary algorithms. Verify integrity using zero-knowledge proofs — no source code required.
- Tier 1 HMAC (~0.7KB)
- Tier 2 Commit-Reveal (~0.5KB)
- Tier 3 IT-MAC (~0.3KB)
- Tier 4 KKW ZK (~0.4KB)
Use Cases
Honest Limitations
xTrust is a trust registry, not a replacement for all PKI. Understanding its boundaries helps you deploy it correctly.
| Limitation | Detail | Mitigation |
|---|---|---|
| In-memory storage | TofuManager, KeyTransparencyLog, and KeyRotationManager all use in-memory data structures (Map, arrays). Data is lost on process restart. | Enterprise CLI (trust-cli) provides persistent JSONL storage with replay-on-init. Client applications should serialize to encrypted storage. |
| No federation | The transparency log is local. There is no protocol for federating logs across organizations or comparing independent logs for the same contact. | Future: gossip protocol for cross-organization log comparison. Today: export via getAllEntries() and manual comparison. |
| Discrete trust levels | Trust is binary: tofu or verified. There is no continuous trust score, no decay over time, and no partial trust. |
Pair with xFuse for continuous trust scoring (IAL1/IAL2/IAL3) based on multiple identity signals. |
| SAS requires OOB channel | Upgrading from TOFU to verified requires both parties to compare a 6-word phrase over a separate channel (phone, in-person, video). This requires coordination. | TOFU is sufficient for most use cases. SAS verification is needed only when MITM protection is critical. Automated SAS is possible for M2M via secondary authenticated channels. |
| Log growth | The transparency log grows linearly with key events. For contacts with frequent key rotations, the log can become large. verifyChain() scans every entry. | Prune completed chains to summary checkpoints. Archive old entries. trust-cli provides JSONL compaction on rotation. |
| Signature scheme agility | Continuity proofs use ML-DSA-65 (FIPS 204). The signing module is isolated behind a typed interface, so the scheme can be swapped (for example to ML-DSA-87) without changing the registry format. | Future migration runs as a module swap: log entries change, transparency log format does not. |
| No revocation broadcast | When a key is revoked (logged as key_revoked), remote parties are not automatically notified. They will only discover the revocation on next contact. | Pair with xBind for real-time revocation notification via signed DID messages to all known peers. |
Enterprise HTTP Server
A turn-key HTTP server that wraps the xTrust core for organizations needing a managed, multi-team trust registry. One binary launches the listener, replays state from append-only JSONL stores, enforces three RBAC roles, and exposes the full xTrust capability surface as REST — with a hash-chained transparency log behind every endpoint.
The SDK described above is exactly right inside one application. It is exactly the wrong shape when an entire enterprise needs to share one canonical key registry. Multi-team deployments break the in-memory model: contact A's TOFU registration in the trading-desk app is invisible to the compliance app two floors down, library calls cannot be audited from the outside, and key history disappears on process restart. The Enterprise HTTP Server solves all three by lifting @private.me/xtrust into a single long-running process with persistent storage, RBAC, and an HTTP query surface auditors can point at.
@private.me/xtrust) when trust state lives inside one application's process. Pick the Server when multiple teams, services, or tenants need to share one canonical key registry — or when auditors require a query surface that survives restarts. Both ship from the same core; the server adds HTTP, RBAC, persistence, and rate limiting.
Architecture
A thin HTTP layer over the xTrust core, backed by five JSONL stores and gated by three RBAC roles. No database. No external dependency. One process. Inbound requests pass through three middleware layers: API-key authentication, role-based authorization, and per-key rate limiting (1000 requests per minute by default). Every endpoint delegates to the underlying library — TofuManager for key registration, KeyTransparencyLog for the append-only audit chain, KeyRotationManager for continuity-proven rotation, and the SAS verification helpers for mutual key confirmation. The server adds nothing to the cryptographic story; it only wraps it.
State persists across restarts via append-only JSONL files. On boot, each file is replayed into an in-memory Map for sub-millisecond reads. On every write, the new record is appended to disk before the in-memory map is updated, so a crash never leaves the maps ahead of the log. The data directory is the database.
Technical Highlights
| Property | How It Works | Why It Matters |
|---|---|---|
| Merkle-tree transparency log | Every key event (register, rotate, revoke) is appended to transparency.jsonl with a SHA-256 hash linking to the previous entry. Merkle commitments are computed across batches for compact proofs. |
An auditor can prove a specific key event was recorded at a specific point in time without scanning the full log. |
| RBAC with three roles | admin (full control), operator (register / rotate / verify), auditor (read-only). API keys are SHA-256 hashed before storage; only the hash hits disk. | Compliance teams can hand auditors read-only credentials without exposing operational ability. Bootstrap key is single-use. |
| Append-only JSONL persistence | Five log files: keys, api_keys, transparency, rotations, audit. Every write is an append. Every boot replays the log into memory. No update-in-place anywhere. | Logs are forensically clean. Backup is cp -r. Recovery is “start the binary.” Tampering with history requires editing a file with hash chains in it. |
| Identity-system integration | Endpoints accept DIDs (did:key, did:web) as identifiers and base64-encoded public keys as payloads. Existing identity providers register their issued keys via API. |
The trust registry slots into your existing IAM stack instead of replacing it. SSO, SCIM, and IdM systems remain authoritative for who; the server becomes authoritative for which key. |
| Post-quantum upgrade path | Continuity proofs use ML-DSA-65 (FIPS 204), so xTrust is post-quantum out of the box. The signing module is isolated behind a typed interface, so future schemes (ML-DSA-87, hybrid constructions) can be substituted without changing the registry format. The transparency log itself is hash-based and already PQ-friendly. | You do not need to migrate the registry to upgrade the signature scheme — the log entries change, the format does not. |
REST Endpoints
Eleven endpoints organized into five capability groups. Every request is authenticated by API key, authorized by role, and rate-limited per key.
Health
{ status: "ok" }. Unauthenticated. Useful for load balancers and Kubernetes liveness checks.Key Registration & Verification
tofu or verified) and registration timestamp.tofu to verified after a successful out-of-band SAS comparison. Logs the verification to the transparency log.Key Rotation
Transparency Log
?after=.RBAC Management
401 UNAUTHORIZED. The revocation is recorded in the audit log.RBAC Model
Three roles, one bootstrap key, and SHA-256 hashing for every credential at rest. The principle is least privilege by default.
| Role | Can do | Cannot do |
|---|---|---|
| admin | Issue and revoke API keys, register and rotate keys, read everything | Nothing — admin is the root role |
| operator | Register new keys (TOFU), verify keys (SAS), initiate rotations, read transparency log | Issue or revoke API keys, modify the audit trail |
| auditor | Read keys, transparency log, rotation history, audit trail | Modify any state. All endpoints are GET-only for this role. |
TRUST_ADMIN_KEY from the environment, hashes it with SHA-256, and stores only the hash. The plaintext is then discarded by the process. From that point forward, the bootstrap key authenticates as admin until it is rotated through POST /api-keys and DELETE /api-keys/:id. Operator and auditor keys are issued by an admin and never appear in the environment.
Enterprise Use Cases
One trust server shared across engineering, security, and compliance teams. Every team queries the same canonical key state. No per-application drift.
Shared Trust AnchorAuditors query the transparency log directly through read-only credentials. Every key registration, verification, rotation, and revocation has a timestamp, an actor, and a Merkle inclusion proof.
SOC 2 / DORA / HIPAAZero outbound network requirements. Single binary, single port, single data directory. Runs in environments where SaaS trust services are prohibited by policy.
No EgressBind every DID issued by your identity platform to its current signing key. Track rotations across the lifetime of the identity. Provide verifiers with one place to look.
DID AuthoritativeService identities (workload DIDs) register their signing keys on first deployment via TOFU. Rotations on redeploy carry continuity proofs. The mesh has one place to ask “is this the right key for service X?”
Workload IdentityHand external auditors an auditor-role API key. They can read the transparency log, rotation history, and audit trail without any ability to alter state. Revoke the key when the engagement ends.
External AuditDeployment
One binary, one data directory, one port. Container-friendly. Air-gap-friendly.
# Required export TRUST_ADMIN_KEY=$(openssl rand -hex 32) # Optional (defaults shown) export TRUST_PORT=3700 export TRUST_DATA_DIR=./data export TRUST_LOG_FORMAT=json export TRUST_MERKLE_ALGORITHM=sha256
# Install pnpm add @private.me/xtrust # Start the server xtrust serve --port 3700 --data ./data # Output Trust server listening on port 3700 Data directory: ./data Admin API key configured
docker run -d \ --name xtrust \ -p 3700:3700 \ -v /var/data/trust:/app/data \ -e TRUST_ADMIN_KEY=<bootstrap-key> \ -e TRUST_LOG_FORMAT=json \ privateme/xtrust:latest
curl -X POST http://localhost:3700/keys \ -H "Authorization: Bearer $TRUST_ADMIN_KEY" \ -H "Content-Type: application/json" \ -d '{"did":"did:key:z6MkUser","publicKey":"<base64>"}'
cp -r /var/data/trust /backup/. Recovery is cp -r /backup/trust /var/data/ followed by xtrust serve. The data directory is the database; there is nothing else to back up.
Server Security Properties
| Property | Mechanism | Guarantee |
|---|---|---|
| API key storage | SHA-256 hashed before persistence | ✓ Plaintext never written to disk |
| Bootstrap admin key | Read from env, hashed on first run, plaintext discarded | ✓ Single-point credential |
| Transparency integrity | SHA-256 hash chain + Merkle commitments | ✓ Tampering detectable end-to-end |
| Rate limiting | 1000 requests / minute per API key | ✓ Per-credential isolation |
| Authorization | Three RBAC roles enforced per endpoint | ✓ Least privilege by default |
| Random generation | Node.js crypto.randomBytes | ✓ CSPRNG for IDs and challenges |
| Persistence | Append-only JSONL with replay-on-init | ✓ No update-in-place; forensically clean |
| Network footprint | One inbound port; zero outbound calls | ✓ Air-gap deployable |
Server Limitations
| Limitation | Detail | Mitigation |
|---|---|---|
| Single-process design | One node serves the registry. Horizontal scale requires either active-passive failover or partitioning by tenant. | For typical enterprise volume, one node handles peak load comfortably. Run a hot standby reading the same data directory for HA. |
| No federation | The transparency log is local to the deployment. Cross-organization log comparison is not built in. | Export transparency.jsonl for offline comparison. Federation protocol planned for a future release. |
| JSONL log growth | Append-only stores grow without bound. A high-rotation environment can produce a large transparency log over multi-year horizons. | Periodic compaction to checkpoint summaries. Off-line archive of older entries with Merkle root snapshots. |
| Signature scheme lock-in | Default continuity proofs use ML-DSA-65 (FIPS 204). The signing module is isolated, so the scheme can be swapped without changing the registry format, but a coordinated migration is still required across all SDK consumers. | Plan the signature-scheme upgrade as a module-swap event across SDK versions. The log entries change shape; the transparency log format does not. |
| No revocation broadcast | Revoked keys are recorded, but remote consumers learn of the revocation only on their next read. | Pair with xBind for real-time signed revocation messages to known peers. |
Verifiable Trust Operations
Every trust operation in this ACI produces a verifiable audit trail via xProve. HMAC-chained integrity proofs let auditors confirm that keys were registered, verified, and rotated correctly — without accessing the keys themselves.
Read the xProve white paper →
Ready to deploy xTrust?
Talk to Sol, our AI platform engineer, or book a live demo with our team.
import { TofuManager, KeyTransparencyLog, KeyRotationManager, createChallenge, computeFingerprint, deriveSas, } from '@private.me/xtrust'; // Initialize the trust stack const log = new KeyTransparencyLog(); const tofu = new TofuManager(log); const rotation = new KeyRotationManager(log); // Register a contact's key (TOFU) const fp = await computeFingerprint(contactPublicKey); const trust = await tofu.processKey( 'alice@example.com', fp ); // trust.value.trustLevel === 'tofu' // Upgrade to verified via SAS ceremony const challenge = await createChallenge( 'bob@example.com', 'alice@example.com', myPublicKey, contactPublicKey ); // challenge.value.shortAuthString === "arctic comet glacier..." // Compare over phone/video, then: await tofu.upgradeTrust('alice@example.com', fp); // trust.value.trustLevel === 'verified'
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
SDK Integration
Embed directly in your application. Runs in your codebase with full programmatic control.
npm install @private.me/xtrust- TypeScript/JavaScript SDK
- Full source access
- Enterprise support available
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
Pricing
Three tiers priced by managed contacts — the active trust relationships your deployment maintains. Free for real production deployments under 1,000 contacts. Pro for growing deployments. Enterprise for regulated and federated scale. See private.me/pricing for current rates.
- ✓ All xTrust capabilities
- ✓ TOFU registration & SAS ceremony
- ✓ Transparency log (90-day retention)
- ✓ Key rotation with continuity proofs
- ✓ In-memory storage (SDK)
- ✓ Community support
- Everything in Free, plus:
- ✓ Persistent JSONL storage
- ✓ Basic RBAC
- ✓ Hosted transparency log
- ✓ Email support (24h business-day SLA)
- ✓ Soft cap at 50,000 contacts
- Everything in Pro, plus:
- ✓ 50,000+ managed contacts
- ✓ Federation across deployments
- ✓ Air-gapped / on-premises deployment
- ✓ BAA / DPA pass-through
- ✓ 7-year transparency log retention
- ✓ Full RBAC & auto-archival policies
- ✓ Dedicated CSM & custom SLA
What counts as a managed contact
A managed contact is any DID with at least one entry in the xTrust transparency log, in Active, Dormant, or Revoked state. DIDs you explicitly archive after dormancy review stop counting toward the limit; transparency log history is preserved.
xTrust prices by maintained trust relationships, not per-operation throughput. A typical relationship involves 1 registration, 0–1 verification ceremonies, a handful of rotations, and 0–1 revocations — the value is in the relationship itself, not the call volume.
Purchase Endpoint
Programmatic subscription creation via REST API. Supports both email-based and xBind identity-based purchases.
Endpoint
POST https://private.me/api/aci/checkout
Request Body
interface PurchaseRequest { // Product identification (required) productId: 'xtrust'; tier: 'pro' | 'enterprise'; // Customer identification (one required) email?: string; // Email-based purchase did?: string; // xBind identity-based purchase // Optional metadata metadata?: Record<string, string>; }
Response
interface PurchaseResponse { checkoutUrl: string; // Stripe Checkout session URL sessionId: string; // Stripe session ID expiresAt: string; // ISO 8601 timestamp }
Error Response (RFC 7807)
All errors follow RFC 7807 Problem Details for HTTP APIs format.
interface ProblemDetails { type: string; // URI identifying the problem type title: string; // Human-readable summary status: number; // HTTP status code detail?: string; // Detailed explanation instance?: string; // URI reference to specific occurrence }
Common Error Codes:
400 Bad Request— Invalid productId, tier, or missing identification401 Unauthorized— Invalid or expired xBind signature429 Too Many Requests— Rate limit exceeded (60/min for xBind, 10/min for email)500 Internal Server Error— Stripe API failure or server error
Example: Email-Based Purchase
const response = await fetch('https://private.me/api/aci/checkout', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ productId: 'xtrust', tier: 'pro', email: 'user@example.com' }) }); const { checkoutUrl } = await response.json(); // Redirect user to checkoutUrl for payment window.location.href = checkoutUrl;
Example: xBind Identity Purchase
import { Agent } from '@private.me/xbind'; // Create agent identity const agent = await Agent.quickstart({ name: 'purchase-agent' }); // Purchase using agent DID (email optional) const envelope = await agent.send( 'did:web:private.me', { productId: 'xtrust', tier: 'pro', did: agent.did // email optional - fallback generated if missing } ); const response = await fetch('https://private.me/api/aci/checkout', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(envelope) }); const { checkoutUrl } = await response.json(); // Higher rate limit: 60/min (vs 10/min for email-based)
Email-based: 10 requests/min per IP address
xBind identity: 60 requests/min per DID (6× faster, prevents impersonation)