Skip to main content

Key lifecycle

This page covers what a "key" means inside Custody, how the threshold is chosen, and how shares move through their lifecycle from creation to retirement.

What a key is, in this system

There is no single artefact called the private key anywhere in Custody. For each wallet, the signing capability is split into shares — produced during a distributed key generation (DKG) ceremony — and stored independently across n MPC nodes. The corresponding public key is the only object that exists in one piece, and it is what addresses are derived from.

When this page says "key," it always means the wallet's signing capability, materialised as n shares.

Threshold: 3-of-5

Every wallet uses a 3-of-5 threshold scheme: any three of five shares are sufficient to sign, and no fewer.

This is the institutional-custody default for a reason:

  • Tolerates simultaneous loss of two shares without losing access to funds. If a node, an availability zone, or even a small partial outage takes shares offline, signing continues from the remaining ones.
  • Compromise of one or two shares is insufficient to forge a signature. An attacker would need to coordinate compromise of at least three independently administered locations.
  • Coordination overhead remains practical. Higher thresholds (e.g. 5-of-9) push latency up and increase the social-engineering surface; lower thresholds (e.g. 2-of-3) shrink the safety margin.

Two of the five shares are intended to live in physically distinct vaults maintained by independent custodians; the remaining three sit in operational nodes. The exact distribution is a deployment-time decision.

Wallet-to-key mapping

We use one master key per wallet. Addresses inside a wallet are derived from that master key via BIP-32 unhardened derivation (so that the operational nodes can derive without ever reconstructing the parent key). Two wallets in the same tenant do not share a master key; each has its own DKG ceremony and its own set of five shares.

The alternatives we considered and ruled out:

  • One master key per tenant. Easier finance ops, but a single crypto failure or share compromise affects every wallet under that tenant.
  • One master key per platform. Even worse blast radius; backups become a single point of failure.
  • No HD derivation, fresh key per address. Backup becomes painful and finance ops nearly impossible.

The wallet-scoped model gives us segregation between wallets while keeping the per-wallet experience standard for any BIP-32 consumer.

Share states

A share is always in one of three states:

  • Active. The current generation of the share. Used for signing. Genesis is the first active share, produced by DKG; subsequent active generations are produced by refresh.
  • On-refresh. The share is participating in a refresh ceremony. It is not used for signing while a refresh is in flight; the previous active generation is the safety net until the refresh completes.
  • Old. The share has been replaced by a newer generation. Old shares are deleted from the operational store. They remain in the dead-drop backup for the historical record (see Backup & recovery), but cannot be combined with current-generation shares to produce a signature.

The forward-secrecy property follows directly: a share captured today cannot be combined with shares captured after the next refresh.

Rotation

Shares are rotated through a refresh protocol that keeps the public key constant while re-randomising every share. Refresh is triggered by:

  • Schedule. Every wallet refreshes on a recurring cadence (currently monthly for hot wallets; the cadence is a deployment knob).
  • Quorum or holder change. Adding, removing, or replacing a share custodian triggers a reshare even outside the schedule.
  • Operator request. A human operator can request an out-of-band refresh — for example, after a suspected exposure of a single share.

A refresh takes well under a second to complete; from the caller's perspective, the wallet is briefly read-only and then resumes signing with the new generation transparently.

Out of scope here