Key Custody & Self-Sovereignty
Multi-party computation wallets, threshold signatures, and the principle of "not your keys, not your crypto."
The Custody Problem
"Your keys, your Bitcoin. Not your keys, not your Bitcoin."
— Andreas Antonopoulos, Bitcoin educator and author of "Mastering Bitcoin"
This fundamental principle of cryptocurrency - popularized by Andreas Antonopoulos in 2016 - states that whoever controls the private keys controls the assets. Custodial solutions (exchanges, hosted wallets) require trust in third parties, contradicting the core premise of decentralized systems.
For autonomous agents, custody becomes even more critical. Agents must:
- Sign transactions automatically (no manual approval for every payment)
- Operate within user-defined spending limits
- Protect keys from compromise if agent code is exploited
- Enable user override at any time (ultimate sovereignty)
Traditional solutions fail this test:
- Single-key wallets - Agent has full access, no spending limits
- Custodial services - Third party controls keys, user loses sovereignty
- Multisig (m-of-n) - On-chain signatures reveal transaction structure, high fees
Multi-Party Computation (MPC) Wallets
MPC wallets solve the custody trilemma through threshold signature schemes (TSS). The private key never exists as a single entity - instead, it is mathematically distributed across multiple parties as encrypted shares.
┌───────────────────────────────────────────────────────────┐ │ TRADITIONAL WALLET (Single Private Key) │ ├───────────────────────────────────────────────────────────┤ │ │ │ Private Key: d7a8fbb3...c9e2 (full key) │ │ ↓ │ │ [SINGLE POINT OF FAILURE] │ │ ↓ │ │ If compromised → All funds stolen │ │ │ └───────────────────────────────────────────────────────────┘ ┌───────────────────────────────────────────────────────────┐ │ MPC WALLET (Distributed Key Shares) │ ├───────────────────────────────────────────────────────────┤ │ │ │ Share 1: e4b2...8f3a → User Device (hardware secure) │ │ Share 2: 3c9d...1a7e → Browser Agent (sandboxed) │ │ Share 3: 7f1e...5b4c → Backup Server (encrypted) │ │ │ │ ❌ No single share can steal funds │ │ ✅ Require 2-of-3 for transaction signing │ │ ✅ User + Agent = normal operations │ │ ✅ User + Backup = recovery if agent compromised │ │ │ └───────────────────────────────────────────────────────────┘
MPC vs Traditional Key Management
How TSS Works
Threshold Signature Schemes enable n parties to jointly sign a transaction, requiring only t of them (where t ≤ n). The process involves:
- Distributed Key Generation (DKG) - Parties collaboratively generate a public key without any single party learning the private key
- Threshold Signing - To sign a transaction, t parties produce partial signatures using their key shares
- Signature Combination - Partial signatures combine mathematically into a valid ECDSA signature matching the public key
Critically, the private key is never reconstructed during signing - it remains distributed across participants.
import { TSS, ECDSASignature } from '@agentic/crypto-tss'
// Distributed Key Generation (setup phase)
const participants = [
{ id: 'user-device', publicKey: userDevicePublicKey },
{ id: 'browser-agent', publicKey: agentPublicKey },
{ id: 'backup-server', publicKey: backupPublicKey }
]
const threshold = 2 // Require 2-of-3 signatures
const keyShares = await TSS.distributedKeyGeneration(participants, threshold)
// keyShares[0] → User device (never transmitted)
// keyShares[1] → Browser agent (ephemeral, isolated)
// keyShares[2] → Backup server (encrypted at rest)
// Each party stores their share locally - no centralized storage
// Transaction Signing (2-of-3 threshold)
async function signAgentTransaction(tx: Transaction) {
// Step 1: Check spending threshold
if (tx.amount > userSettings.autoApproveThreshold) {
throw new Error('Exceeds auto-approval limit - manual confirmation required')
}
// Step 2: Select signing parties (user + agent)
const signers = ['user-device', 'browser-agent']
// Step 3: Each party generates partial signature
const partialSigs = await Promise.all([
TSS.partialSign(tx, keyShares['user-device']),
TSS.partialSign(tx, keyShares['browser-agent'])
])
// Step 4: Combine partial signatures (MPC protocol)
const fullSignature = TSS.combineSignatures(partialSigs)
// Step 5: Verify signature is valid ECDSA
const isValid = TSS.verifySignature(
tx.hash(),
fullSignature,
publicKey
)
if (!isValid) throw new Error('Invalid threshold signature')
return fullSignature
}
// Key Rotation (without changing public key)
async function rotateKeyShares() {
// Generate new key shares while maintaining same public key
const newShares = await TSS.refreshKeyShares(keyShares, participants)
// Old shares become invalid - attacker's stolen share is useless
return newShares
}Security Benefits
1. No Single Point of Failure
Compromising one key share yields zero value. An attacker would need to simultaneously compromise both the user's device AND the browser agent to steal funds - a significantly higher bar than traditional single-key wallets.
2. Agent Spending Limits (Cryptographic)
Unlike software-level guardrails (which can be bypassed), TSS provides cryptographic enforcement of spending limits:
- Agent alone cannot sign (requires user's key share)
- User can revoke agent's key share instantly
- Spending policies enforced at protocol level, not application level
3. Key Rotation Without Address Change
TSS supports refreshing key shares while maintaining the same public key/address. This means:
- No need to migrate funds to a new address
- Stolen key shares can be invalidated without disrupting operations
- Regular rotation reduces window of opportunity for attackers
4. Standard ECDSA Signatures
TSS produces standard ECDSA signatures indistinguishable from single-key signatures. Benefits:
- Privacy - On-chain observers cannot tell if a transaction used MPC
- Compatibility - Works with 95%+ of blockchains (Bitcoin, Ethereum, Solana, etc.)
- Lower fees - Single signature vs. multisig's multiple signatures
Comparison to Multisig
| Feature | MPC (TSS) | Multisig |
|---|---|---|
| Signatures | 1 signature (combined off-chain) | m signatures (all on-chain) |
| Transaction Size | Standard (65 bytes) | Larger (m × 65 bytes) |
| Gas Fees | Standard | Higher (multiple signature verification) |
| Privacy | Appears as single-key wallet | Reveals multisig structure on-chain |
| Blockchain Support | Universal (any ECDSA chain) | Limited (requires smart contract support) |
| Key Rotation | Yes, same address | No, requires new multisig address |
Agentic Browser Implementation
The Agentic Browser uses a 2-of-3 TSS configuration:
- Share 1: User Device - Stored in secure enclave (iOS Keychain, Android Keystore, TPM on desktop)
- Share 2: Browser Agent - Ephemeral key share, regenerated on each session
- Share 3: Backup Server - Encrypted at rest, used for recovery scenarios
Normal operations require User + Agent (2-of-3). If the agent is compromised, user can combine with backup server to move funds to a new wallet.
Recovery Scenarios
Lost Device
User loses their device → Use backup server + agent to recover funds to new wallet.
Compromised Agent
Agent exploited by attacker → User can immediately revoke agent's key share, preventing unauthorized signatures.
Backup Server Compromised
Backup server hacked → Attacker gains one key share (useless alone). User rotates key shares to invalidate stolen share.
Research & Standards
The Agentic Browser's MPC implementation is based on peer-reviewed research:
- GG20 - Gennaro & Goldfeder (2020) threshold ECDSA protocol
- CGGMP21 - Canetti et al. (2021) - UC-secure TSS with identifiable aborts
- Fireblocks MPC - Production-grade MPC wallet infrastructure (reference implementation)
Our implementation undergoes regular security audits by Trail of Bits and Kudelski Security.
Next Steps
- Browser Architecture - How MPC integrates with the browser's security model
- Integration Guide - Implementing TSS in your application
- FAQ - Common questions about key management