> For the complete documentation index, see [llms.txt](https://docs.tresori.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tresori.xyz/introduction/tresori-mpc/3-party-mpc-wallet.md).

# 3-Party MPC Wallet

Tresori is a professional-grade Multi-Party Computation (MPC) wallet service designed to protect your digital assets with institutional-level security. Unlike conventional crypto wallets — where a single private key control all your funds — Tresori splits control across three independent parties, ensuring that no single point of failure can ever compromise your wallet.

Secure threshold ECDSA for Ethereum. The private key is split into 3 shares across Client, Server (relay), and Nitro Enclave. Any 2 shares can sign, but the full key is **never reconstructed**.

<a class="button primary">Client: Share 1</a><a class="button primary">Server: Relay Only</a><a class="button primary">Enclave: Share 2 + 3</a><a class="button primary">2-of-3 Threshold</a>

***

<table data-header-hidden data-full-width="false"><thead><tr><th valign="top"></th></tr></thead><tbody><tr><td valign="top"><p>The Core Promise</p><p>Your private key is NEVER fully assembled in any one place — not on your device, not on our server, not anywhere. Tresori signs transactions using partial contributions from separate parties, and the complete private key simply does not exist in reconstructed form at any point.</p></td></tr></tbody></table>

***

### 🛡️Zero Knowledge Key Derivation + Server Relay Architecture

The combined private key is **never computed**. Client communicates with Server only - Server relays to Enclave. Client ↔ Enclave data is **end-to-end encrypted**.

### 🔌Service Connections

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td>🌐<strong>Client</strong></td><td><ul><li>Active signing party</li><li>Generates partial sig s₁</li><li>Combines final signature</li><li>User interface</li></ul></td></tr><tr><td><strong>Server (Relay)</strong></td><td><ul><li>Relay/Proxy only</li><li>Forwards to Enclave</li><li>Contributes to DKG</li><li>Cannot compute shares</li></ul></td></tr><tr><td><strong>Nitro Enclave</strong></td><td><ul><li>Holds Share 2 (active)</li><li>Holds Share 3 (backup)</li><li>Attestation verified</li><li>All crypto processing</li></ul></td></tr></tbody></table>

### Distributed Key Generation&#x20;

Generate a new MPC wallet. Each party generates its own secret and shares polynomial evaluations. The combined public key is derived via EC point addition - **the private key is never assembled**.

When you create a new Tresori wallet, the system uses a cryptographic process called Distributed Key Generation (DKG). Each of the three parties independently generates its portion of the key. The combined Ethereum address is derived without any party ever seeing the complete private key.

<table data-header-hidden data-full-width="false"><thead><tr><th valign="top"></th></tr></thead><tbody><tr><td valign="top"><p>•        Your key share (Share 1) is generated in your browser and stored only on your device.</p><p>•        The Enclave independently generates and holds Share 2 (active) and Share 3 (backup).</p><p>•        No party ever transmits a complete key to another.</p><p>•        Your Ethereum address is computed from the combined public key — the same address you will use for all transactions.</p></td></tr></tbody></table>

```mermaid
sequenceDiagram
    participant Client as Client (Browser - Share d1)
    participant Enclave2 as Enclave (Share d2 - Active)
    participant Enclave3 as Enclave (Share d3 - Backup)

    Note over Client,Enclave3: Distributed Key Generation (3-Party MPC)

    Client->>Client: Generate Secret (Polynomial f1)
    Enclave2->>Enclave2: Generate Secret (Polynomial f2)
    Enclave3->>Enclave3: Generate Secret (Polynomial f3)

    Client->>Enclave2: Send Share Evaluations
    Client->>Enclave3: Send Share Evaluations

    Enclave2->>Client: Send Share Evaluations
    Enclave2->>Enclave3: Send Share Evaluations

    Enclave3->>Client: Send Share Evaluations
    Enclave3->>Enclave2: Send Share Evaluations

    Note over Client: Compute Share d1
    Note over Enclave2: Compute Share d2
    Note over Enclave3: Compute Share d3

    Note over Client,Enclave3: Public Key = EC Point Addition of all contributions

    Client->>Client: Derive Ethereum Address
    Enclave2->>Client: Return Session ID
```

### Recover Client Share (Secret Resharing)

Lost your client share? Recover it using the enclave's Share 2 & Share 3 stored in S3. The enclave uses **proactive secret sharing** to generate a fresh set of shares for the same private key; old shares are invalidated and replaced.

#### How Recovery Works

```mermaid
sequenceDiagram
    participant S3
    participant KMS
    participant Enclave

    S3->>KMS: Fetch Encrypted Shares
    KMS->>Enclave: Decrypt Data Key

    Note over Enclave: Decrypt Shares (2,3)
    Note over Enclave: Recover Share 1 (Lagrange Interpolation)
    Note over Enclave: Reconstruct Private Key
    Note over Enclave: Apply Resharing Polynomial

    Enclave-->>S3: Store New Encrypted Shares
    S3->>S3: Delete Old Shares
```

### ✍️ Sign Message (Client + Enclave Share 2)

Create a valid Ethereum signature using Share 1 (Client) and Share 2 (Enclave via Server relay). Partial signatures are combined using Lagrange interpolation; **the private key is never reconstructed**.

<figure><img src="/files/OpA0ZYZwAeL8OmXRrnpp" alt=""><figcaption></figcaption></figure>

```mermaid
sequenceDiagram
    participant Client
    participant Enclave

    Note over Client,Enclave: MPC Signing (Private Key Never Reconstructed)

    Client->>Client: Input Message
    Client->>Client: Hash Message (keccak256)
    Client->>Client: Generate Nonce (k)

    Client->>Client: Create Partial Signature s1
    Client->>Enclave: Send Signing Request (hash, nonce data)

    Enclave->>Enclave: Generate Partial Signature s2

    Enclave-->>Client: Return Partial Signature s2

    Client->>Client: Combine s1 + s2 (Lagrange Interpolation)

    Client->>Client: Generate Final Signature (r, s, v)

    Client->>Client: Verify Signature
```

### Security Properties

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td> <strong>No Key Reconstruction</strong></td><td>The combined private key d = s<sub>c</sub> + s<sub>s</sub> + s<sub>e</sub> is <strong>never computed</strong>. Only partial signatures are combined using Lagrange interpolation.</td><td><a href="https://images.unsplash.com/photo-1593062037896-764e9f52029e?crop=entropy&#x26;cs=srgb&#x26;fm=jpg&#x26;ixid=M3wxOTcwMjR8MHwxfHNlYXJjaHwzfHxnZWFyfGVufDB8fHx8MTc3NDc5MTc0NHww&#x26;ixlib=rb-4.1.0&#x26;q=85">https://images.unsplash.com/photo-1593062037896-764e9f52029e?crop=entropy&#x26;cs=srgb&#x26;fm=jpg&#x26;ixid=M3wxOTcwMjR8MHwxfHNlYXJjaHwzfHxnZWFyfGVufDB8fHx8MTc3NDc5MTc0NHww&#x26;ixlib=rb-4.1.0&#x26;q=85</a></td></tr><tr><td> <strong>Server is Relay Only</strong></td><td>Server holds NO shares - it only relays encrypted data between Client and Enclave. Server cannot read f_c(3) or compute any shares.</td><td><a href="https://images.unsplash.com/photo-1560732488-6b0df240254a?crop=entropy&#x26;cs=srgb&#x26;fm=jpg&#x26;ixid=M3wxOTcwMjR8MHwxfHNlYXJjaHw2fHxzZXJ2ZXJ8ZW58MHx8fHwxNzc0NzkxODAyfDA&#x26;ixlib=rb-4.1.0&#x26;q=85">https://images.unsplash.com/photo-1560732488-6b0df240254a?crop=entropy&#x26;cs=srgb&#x26;fm=jpg&#x26;ixid=M3wxOTcwMjR8MHwxfHNlYXJjaHw2fHxzZXJ2ZXJ8ZW58MHx8fHwxNzc0NzkxODAyfDA&#x26;ixlib=rb-4.1.0&#x26;q=85</a></td></tr><tr><td><strong>Enclave Holds Both Shares</strong></td><td>Share 2 (active signing) and Share 3 (backup) are both securely stored in the Nitro Enclave. Attestation verifies enclave integrity.</td><td><a href="https://images.unsplash.com/photo-1521159936751-ff7c25fd187b?crop=entropy&#x26;cs=srgb&#x26;fm=jpg&#x26;ixid=M3wxOTcwMjR8MHwxfHNlYXJjaHwxfHxzZWNlcmV0fGVufDB8fHx8MTc3NDc5MTg2M3ww&#x26;ixlib=rb-4.1.0&#x26;q=85">https://images.unsplash.com/photo-1521159936751-ff7c25fd187b?crop=entropy&#x26;cs=srgb&#x26;fm=jpg&#x26;ixid=M3wxOTcwMjR8MHwxfHNlYXJjaHwxfHxzZWNlcmV0fGVufDB8fHx8MTc3NDc5MTg2M3ww&#x26;ixlib=rb-4.1.0&#x26;q=85</a></td></tr><tr><td><strong>End-to-End Encryption</strong></td><td>Client ↔ Enclave communication uses ECDH key exchange + AES-256-GCM. Server relays encrypted data but CANNOT read it.</td><td><a href="https://images.unsplash.com/photo-1526374965328-7f61d4dc18c5?crop=entropy&#x26;cs=srgb&#x26;fm=jpg&#x26;ixid=M3wxOTcwMjR8MHwxfHNlYXJjaHwyfHxlbmNyeXB0aW9ufGVufDB8fHx8MTc3NDc5MTkyMXww&#x26;ixlib=rb-4.1.0&#x26;q=85">https://images.unsplash.com/photo-1526374965328-7f61d4dc18c5?crop=entropy&#x26;cs=srgb&#x26;fm=jpg&#x26;ixid=M3wxOTcwMjR8MHwxfHNlYXJjaHwyfHxlbmNyeXB0aW9ufGVufDB8fHx8MTc3NDc5MTkyMXww&#x26;ixlib=rb-4.1.0&#x26;q=85</a></td></tr><tr><td><strong>Demo Nonce</strong></td><td>This demo uses a shared nonce for simplicity. Production systems should use distributed nonce generation via MPC.</td><td><a href="https://images.unsplash.com/photo-1667984436031-ea1d9ff307ec?crop=entropy&#x26;cs=srgb&#x26;fm=jpg&#x26;ixid=M3wxOTcwMjR8MHwxfHNlYXJjaHw2fHxjcnlwdG9ncmFwaHl8ZW58MHx8fHwxNzc0NzkyMTE1fDA&#x26;ixlib=rb-4.1.0&#x26;q=85">https://images.unsplash.com/photo-1667984436031-ea1d9ff307ec?crop=entropy&#x26;cs=srgb&#x26;fm=jpg&#x26;ixid=M3wxOTcwMjR8MHwxfHNlYXJjaHw2fHxjcnlwdG9ncmFwaHl8ZW58MHx8fHwxNzc0NzkyMTE1fDA&#x26;ixlib=rb-4.1.0&#x26;q=85</a></td></tr><tr><td> <strong>Simulated Enclave</strong></td><td>The Nitro Enclave is simulated for demo purposes. Production should use real AWS Nitro Enclaves with attestation.</td><td><a href="https://images.unsplash.com/photo-1741958193874-6ef299f6b053?crop=entropy&#x26;cs=srgb&#x26;fm=jpg&#x26;ixid=M3wxOTcwMjR8MHwxfHNlYXJjaHw1fHxEYXRhYmFzZXxlbnwwfHx8fDE3NzQ3OTIyMTR8MA&#x26;ixlib=rb-4.1.0&#x26;q=85">https://images.unsplash.com/photo-1741958193874-6ef299f6b053?crop=entropy&#x26;cs=srgb&#x26;fm=jpg&#x26;ixid=M3wxOTcwMjR8MHwxfHNlYXJjaHw1fHxEYXRhYmFzZXxlbnwwfHx8fDE3NzQ3OTIyMTR8MA&#x26;ixlib=rb-4.1.0&#x26;q=85</a></td></tr></tbody></table>
