Coinbase Open Source MPC Library — Demo Guide, Protocol Walkthrough & Mobile UX Prototype
1. Library Overview
What is CB-MPC?
CB-MPC is Coinbase's open-source secure multi-party computation library for protecting cryptographic keys. Instead of one person holding a private key, the key is split into shares distributed across multiple parties. No single party ever sees the full key — yet together, a threshold of parties can sign transactions as if they held a single key.
Demonstrates the foundational cryptographic building blocks: random oracle hashing and commitments.
What it does:
hash_string() — Hashes curve generator + random scalar into a 256-bit byte string via the random oracle
hash_number() — Hashes into a field element (big number mod q)
hash_curve() — Hashes into a new curve point (hash-to-curve)
com() — Creates a cryptographic commitment (hiding + binding), then opens it to verify correctness
Why this matters
Commitments are the building block of every MPC protocol. A party "commits" to a value (like locking it in a sealed envelope), then later "opens" it. This prevents cheating — you can't change your value after seeing others' values.
2.2 Zero-Knowledge Proof C++
demos-cpp/zk
Proves knowledge of a discrete logarithm without revealing the secret.
Prover picks secret w
→
Computes Q = w * G
→
Proves: "I know w such that Q = w*G"
→
Verifier checks proof (no w revealed)
Uses Fischlin's transform with 16 parallel repetitions for a non-interactive proof. Output is 2315 bytes — compact enough to include on-chain or in a backup attestation.
2.3 Agree Random Go
demos-go/examples/agreerandom
Two parties jointly generate a random value that neither can bias.
Party 0
Picks private randomness r0
Commits to r0
Party 1
Picks private randomness r1
Commits to r1
Exchange commits
→
Open commits
→
result = combine(r0, r1)
Both parties get the same random value. Supports arbitrary bit lengths (128-bit, 10-bit shown in demo). Used internally by signing protocols to agree on nonces.
Each party gets a key share (x_i) — a scalar on secp256k1
Both parties compute the same public key Q
The full private key x = x_0 + x_1 is never materialized
Collaborative Signing
Party 0 receives the final DER-encoded ECDSA signature
Party 1 contributes to the protocol but gets no signature
Output is a standard ECDSA signature — verifiable by anyone
Key Refresh
After refresh, both parties hold new shares (different x_i values), but the public key Q stays the same. This means old shares are useless — even if an attacker stole a share before refresh, it's now invalid.
2.5 ECDSA MPC with Backup GoPVE
demos-go/examples/ecdsa-mpc-with-backup
The most comprehensive demo: N-party ECDSA key generation + PVE backup + restore + signing.
This means: to restore a backup, you need party 0 AND any 2 of {p1, p2, p3}.
Key Share Management
Backup: Each party encrypts their key share using PVE (Publicly Verifiable Encryption) with RSA-OAEP KEM. The encrypted bundles can be publicly verified by all parties without decrypting.
Restore: Each backup holder partially decrypts using their RSA private key. The partial decryptions are sent to the share owner, who aggregates them. The access structure enforces the threshold policy.
Critical: In production, partial decryptions must be routed to the correct party only. Sending to the wrong party leaks information.
2.6 Zero-Knowledge Proof Go
demos-go/examples/zk
Go wrapper for the same ZK discrete-log proof shown in the C++ demo. Generates a key pair on secp256k1, proves knowledge of the private key, and verifies the proof — all without revealing the secret witness.
2.7 Access Structure Go
demos-go/examples/access-structure
Demonstrates how to build complex authorization policies using boolean trees:
AND
OR role
LEAF role:Admin
LEAF dept:HR
THRESHOLD sig (2/3)
LEAF sig:A
LEAF sig:B
LEAF sig:C
This encodes: (Admin OR HR) AND (2 of 3 signers). Access structures define who can participate in key generation, signing, and backup/restore operations.
3. Key Share Lifecycle
Lifecycle Diagram
GENERATE DKG protocol creates shares
→
STORE Secure enclave / keychain
→
BACKUP PVE to USB-C / cloud
↓
USE Sign transactions
←
REFRESH Rotate shares periodically
←
RESTORE Quorum decryption from backup
Operation
What Happens
Security Property
Generate
DKG protocol runs; each party gets x_i, all see Q
Full key x never exists in one place
Store
x_i stored in device Secure Enclave / TEE
Hardware-bound, non-exportable
Backup
x_i encrypted via PVE; ciphertext publicly verifiable
Verifiable without decrypting
Refresh
x_i re-randomized; Q unchanged; old shares invalidated
Forward security — old leaks useless
Sign
Threshold parties run MPC signing; one gets signature
Standard ECDSA — indistinguishable from single-signer
Restore
Quorum holders partially decrypt; owner aggregates
Threshold enforcement by access structure
4. Protocol Flow: ECDSA-2PC
Phase 1: Key Generation
Party 0 (Phone)
secret x_0 — key share
public Q = (x_0 + x_1) * G
Party 1 (Server)
secret x_1 — key share
public Q = (x_0 + x_1) * G
Both parties run the interactive DKG protocol over a network channel. The output: each holds a share, both agree on the public key. The private key x = x_0 + x_1 is never computed anywhere.
Phase 2: Collaborative Signing
Party 0: pick nonce k_0
↔
Party 1: pick nonce k_1
Exchange commitments & partial sigs
→
Party 0 gets final (r, s) signature
The signature is a standard DER-encoded ECDSA signature that any blockchain node can verify. The 2PC protocol is invisible — it looks like one person signed.
Phase 3: Key Refresh
Party 0
x_0 (old) — discarded
new x_0' = x_0 + delta
Party 1
x_1 (old) — discarded
new x_1' = x_1 - delta
x_0' + x_1' = x_0 + x_1 = x (unchanged). The public key Q stays the same, but an attacker who captured the old x_0 can no longer reconstruct x.
Mobile UX Prototype
5. iOS App — Key Management UX
Neo-brutalist mobile prototype for on-device MPC key share management. The app runs one party of the MPC protocol locally; the counterparty is a server or another device.
5.1 Key Share Generation (On-Device)
⚿
CB-MPC Vault
Threshold key management. Your key never exists in one place.
How it works
Your private key is split into shares. This device holds one share. A server (or second device) holds another. Both must cooperate to sign. Neither can act alone.
IMPORTANT: Store this drive in a physically secure location. The encrypted share alone is not enough to restore — you also need quorum cooperation.
Backup Verified
5.4 Restore from USB-C Drive
Restore Vault
🔌
Connect your backup USB-C drive
[...] WAITING FOR DRIVE
What you need to restore
1. USB-C drive with backup file
2. Quorum of recovery contacts:
- This device (you)
- 2 of 3 recovery contacts
Restore process
Each contact uses their RSA private key to partially decrypt your backup. You collect these partial decryptions and aggregate them to recover your key share.
Restore Init
Quorum Collection
Backup File
[OK] encrypted_share.pve loaded
Access Structure
Required: THIS DEVICE + 2/3 contacts
Recovery Contacts
ALICE [OK]
BOB [OK]
CAROL [---]
[OK] QUORUM MET (2/3)
Partial Decryptions
Alice: partial_dec received [OK]
Bob: partial_dec received [OK]
Carol: not needed
Quorum Status
Vault Restored
[OK] KEY SHARE RECOVERED
Verification
x_i matches original: [OK]
Q_i = x_i * G matches: [OK]
Public key Q unchanged: [OK]
Key Share
[STORED IN SECURE ENCLAVE]
Party 0 — Restored
SUCCESS: Your vault is fully operational. You can sign transactions immediately. Consider running a key refresh to invalidate the backup shares.
Restore Complete
5.5 Key Refresh
Key Refresh
Re-randomize key shares without changing the public key
Current State
Public Key Q: 04f6a3...a17e (unchanged)
Share x_0: 91c495...d5a8 (current)
Last Refresh: 2026-02-15
Refresh Count: 3
After Refresh
Public Key Q: 04f6a3...a17e (SAME)
Share x_0: d22214...2fe6 (NEW)
Old Share: [DESTROYED]
After refresh, any previously leaked or backed-up shares become useless. Refresh regularly for forward security.
Key Refresh
Vault Dashboard
Active Vault
Name: Primary Wallet
Curve: secp256k1
Mode: ECDSA-2PC
Status: ACTIVE
Public Key
04f6a30309f61ded59...3bdda17e
Key Share Health
Secure Enclave: [OK]
Last Refresh: 2h ago
Backup Status: [OK] USB-C verified
Counterparty: [OK] Server online
Dashboard
6. Key Share Security Guidelines
Production Checklist
Rule
Why
Never export raw key shares
Key shares should live in hardware security modules (HSM, Secure Enclave, TEE). If you must export for backup, use PVE.
Refresh keys after any suspected compromise
Key refresh invalidates all previous shares. Even if an attacker captured a share, it becomes useless after refresh.
Verify PVE backups before trusting them
PVE is "publicly verifiable" — any party can check that the encrypted backup actually contains the correct share, without decrypting it.
Route partial decryptions carefully
During PVE restore, each holder's partial decryption must go only to the rightful share owner. Misrouting leaks information.
Use access structures for backup policies
Define who can restore via AND/OR/THRESHOLD trees. Example: "device owner AND 2-of-3 recovery contacts."
Bind party identity to key shares
Use hashes of public keys or similar identifiers — not just indices. This prevents party impersonation.
This library is not thread-safe
Protect all shared objects with mutexes if using multiple threads.
Refresh backups after key refresh
Old backups contain old shares. After refresh, create a new backup and securely delete the old one.