# MPC Wallet Security

A technical overview of Aurea's MPC wallets: who holds what, how a wallet is made and signs, what travels through Aurea, and what Aurea can and cannot do.

## Overview

- An MPC wallet is an ordinary address on its chain — `secp256k1` for EVM chains, `ed25519` for Solana — whose private key is never assembled. It exists only as three **shares**, and any two of them sign together (2-of-3).
- A `secp256k1` wallet uses **CGGMP** (the CGGMP21 threshold ECDSA protocol, an audited implementation) — or, for older wallets, GG18; an `ed25519` wallet uses threshold EdDSA. A signature is a standard signature of the address: nothing on chain tells it from any other.
- The integration: [MPC Wallet Setup](https://docs.aureahub.com/docs/guide-wallet-setup.md) and the MPC Wallets reference ([Start DKG Ceremony](https://docs.aureahub.com/docs/mpc-dkg-start.md), [Start Signing Ceremony](https://docs.aureahub.com/docs/mpc-sign-start.md)).

## The Shares

| Share | Kept by | Used for |
| --- | --- | --- |
| DEVICE | The user's device, in your app's secure storage | Every everyday signature, with Aurea's cosigner |
| BACKUP | The user: a recovery file, or a backup sealed with the user's passkey | A backup proof; a signature after the device is lost |
| AUREA | Aurea's cosigner, encrypted, in the EU | Taking part in a signature the user starts |

- Two shares are always the user's: together, device and backup are enough to sign without Aurea's share, while Aurea's single share never is.
- A wallet made with your tenant's own co-signer has its third share there instead of at Aurea ([Institution Callback & Co-Signer](https://docs.aureahub.com/docs/guide-institution-callback.md)).

## Making a Wallet

- **Key generation (DKG).** The three parties generate the key together: each produces its own share and the parties exchange only what the protocol needs. The address comes out of the ceremony; the private key is never formed. The user's app derives the address on its side, and registering the wallet checks it against the cosigner's ([Register MPC Wallet](https://docs.aureahub.com/docs/mpc-wallet-register.md)).
- **The second ceremony.** A CGGMP wallet runs one more ceremony before its first signature, which prepares each share to sign ([Start Aux Ceremony](https://docs.aureahub.com/docs/mpc-aux-start.md)).
- **The backup.** The user keeps the backup share, and can prove it is still held (Backup). A wallet's setup state says which step comes next ([MPC Wallet Setup](https://docs.aureahub.com/docs/guide-wallet-setup.md)).

## Signing

- Your app asks for a signature of a digest for one of the user's wallets ([Start Signing Ceremony](https://docs.aureahub.com/docs/mpc-sign-start.md)). Only the wallet's own user can, with an access token whose role runs MPC ceremonies.
- Aurea's API checks the request — the wallet, the user, freezes and your tenant's policy at that signing point — and only then asks the cosigner to take part. The cosigner accepts a request to join only when Aurea's API has signed it, and it is single-use and short-lived.
- The device and the cosigner then run the signing protocol; neither learns the other's share, and the signature comes out of the ceremony.
- A ceremony that fails repeatedly for the same wallet is recorded with the party that caused it, so that a misbehaving party can be identified.

## The Relay

- The parties do not connect to each other: they exchange the protocol's messages through Aurea's relay, over HTTPS, in a session that only the ceremony's parties can join.
- **Relay version 2** (`wireVersion: 2`): each message to another party is sealed for that party and signed by its sender, so the relay carries it without being able to read or change it; a message sent to everyone is checked to be the same for every party before the protocol uses it; a copy delivered twice is used once. Use version 2: version 1 is kept only for clients that have not moved yet, where your tenant may still use it.
- What the relay sees: the session, the parties' names, the size and order of the messages. Never a share.

## The Approval Key

- A wallet can be made with an **approval key** — a passkey, or a P-256 key pair your app keeps on the user's device. Its public part reaches the cosigner inside the key generation, end to end over relay version 2, and is bound to the wallet ([Start DKG Ceremony](https://docs.aureahub.com/docs/mpc-dkg-start.md) › An Approval Key).
- Each signature then carries the approval key's signature over the wallet's id and the digest; the cosigner verifies it against the bound key. Because the key never leaves the user's device and is bound inside the ceremony, neither Aurea's API nor the relay can produce or swap it.
- The cosigner signs nothing of such a wallet without a valid approval and an `intent` that stands for the digest.

## What Is Signed

- With each signature your app can send its **intent**: what the digest is the hash of — an EIP-1559 transaction, EIP-712 typed data, an EIP-191 message or a backup proof. The cosigner recomputes the digest from it and compares, so the user's approval and the cosigner's record are about the transaction itself, not an opaque hash ([Start Signing Ceremony](https://docs.aureahub.com/docs/mpc-sign-start.md) › What Is Signed).
- A signature whose intent does not stand for its digest is refused: by Aurea's API before the ceremony starts (`422` `MPC_INTENT_MISMATCH`), and by the cosigner.

## Backup

- The backup share stays with the user — a recovery file, or a backup sealed with the user's passkey. Aurea's API never receives it.
- **Backup proof.** The backup share and Aurea's cosigner sign a one-time challenge together, which proves the user still holds the backup without moving funds or revealing it ([Start a Backup Proof](https://docs.aureahub.com/docs/mpc-backup-proof-start.md)). [Get the Backup State](https://docs.aureahub.com/docs/mpc-backup-get.md) says when to ask for it again.
- [Coming soon, upon request](https://docs.aureahub.com/docs/feature-availability.md) Your tenant can have an MPC address bound for receiving only once its backup is confirmed, so that a user never receives funds into a wallet they could not recover ([MPC Wallet Setup](https://docs.aureahub.com/docs/guide-wallet-setup.md) › Can Receive, Can Spend).

## A Lost Device

- The user restores the backup share and signs with it and Aurea's cosigner (committee `BACKUP` + `AUREA`). A signature from the backup always needs the owner's step-up: the current password, or a passkey step-up.
- A wallet whose device was lost before its backup was kept, and that holds nothing, can be given up and made again ([Restart a Pending Wallet](https://docs.aureahub.com/docs/mpc-wallet-restart.md)); a wallet that holds funds is never given up.
- A user who keeps both the device and the backup share holds two shares — the threshold: cryptographically, their funds do not depend on Aurea's share.

## Policy and Controls

- Your tenant's controls apply before Aurea's cosigner is asked: [policy sets](https://docs.aureahub.com/docs/guide-policy-sets.md), [signing rules](https://docs.aureahub.com/docs/guide-signing-rules.md), the [address book](https://docs.aureahub.com/docs/guide-address-book.md), [screening](https://docs.aureahub.com/docs/guide-screening.md), [freezes and quarantines](https://docs.aureahub.com/docs/guide-freezes.md), and your own [institution callback](https://docs.aureahub.com/docs/guide-institution-callback.md).
- A frozen tenant, user, account or wallet signs nothing (`423`), a backup proof included.
- Every MPC wallet's setup step is sent to your server as an event ([MPC Wallet Setup](https://docs.aureahub.com/docs/guide-wallet-setup.md) › Events).

## What Aurea Cannot Do

- Sign for a user alone: one share is below the threshold of two.
- Read the protocol's messages between the user's parties and the cosigner on relay version 2, or change them unnoticed.
- Reconstruct a wallet's key: it is never assembled, and the user's two shares never reach Aurea.
- Take away a user's ability to sign with both of their own shares: device and backup reach the threshold without Aurea's.

## Status of Each Control

What runs for every MPC wallet today, and what your tenant can have on request:

| Control | Today |
| --- | --- |
| 2-of-3 shares; Aurea's cosigner keeps one; key never assembled | Every wallet |
| Cosigner joins only requests signed by Aurea's API | Every wallet |
| Relay version 2: sealed, signed, echo-checked messages | Every client on version 2 |
| Backup proof | Every wallet |
| Approval key bound in the key generation, verified at each signature | Wallets made with one |
| Refusing a signature without a valid approval and intent | Wallets made with an approval key |
| Intent recomputed and compared at each signature | Signatures sent with one |
| Refusing a signature whose intent does not match its digest | Signatures sent with one |
| The owner's step-up for a signature from the backup | Every wallet |
| One wallet in setup per user and purpose | Every tenant |
| Receiving only once the backup is confirmed | On request |
| Your tenant's policy, signing rules, address book, screening, freezes | As your tenant sets them (Feature Availability) |

Report a suspected vulnerability to [help@aureahub.com](mailto:help@aureahub.com) ([Security Overview › Reporting a Vulnerability](https://docs.aureahub.com/docs/guide-security.md)).

---

Web version: https://docs.aureahub.com/#guide-mpc-security
