Skip to main content

Cryptography

The cryptographic core of Custody is a single primitive: threshold ECDSA implemented by the DKLS23 library. This page explains why, what it does, and the trade-offs that come with it.

Why DKLS23

We surveyed the active TSS-MPC libraries before settling on DKLS23. The short version of the comparison:

  • Coverage of features we need. DKG, share refresh, true t-of-n thresholds (with t = 1 and up to n = 255), and BIP-32 unhardened HD derivation. Several other libraries cover only n-of-n, miss key refresh, or restrict HD wallets to 2-party setups.
  • Memory safety. DKLS23 is written in Rust with unsafe blocks disallowed at the project level, and uses zero-on-drop wrappers for all share material. Even if our wrapper code mishandles a buffer, the underlying library will not leak material via uninitialised memory.
  • Audit posture. The secp256k1 implementation it depends on has been audited by NCC; the project ships meaningful test coverage and benchmarks.
  • License. MIT/Apache, no commercial-use restrictions.

The candidates we ruled out and why are recorded internally; the relevant contrast for an outside reader is that two of the otherwise-strongest options (Silence Laboratories DKLS, Coinbase's cb-mpc) had license or HD-wallet limitations that did not match our requirements.

What DKLS23 gives us

The library exposes three operations:

  • DKG — distributed key generation. The n participants run a multi-round protocol after which each holds a Shamir share of a secret none of them ever materialised, and all of them know the corresponding public key.
  • Sign — a t-of-n subset produces an ECDSA signature collaboratively. The signing protocol is four rounds.
  • Refresh — the n participants re-randomise their shares. The public key is unchanged; the old shares cannot be combined with the new ones.

It also supports BIP-32 unhardened derivation, which is what we use to issue child addresses under a wallet's master key without ever reconstructing the parent private key.

What DKLS23 does not give us

A few properties matter for our threat model and are explicitly absent:

  • No EdDSA. DKLS23 is ECDSA-only, which covers Bitcoin (up to SegWit) and EVM chains but does not extend to Solana, Cosmos SDK chains using ed25519, etc. Any future need for those would require a second primitive.
  • No identifiable abort. If a participant misbehaves, the protocol aborts, but the surviving parties cannot point at the bad actor. We compensate by attesting the participants out-of-band: every signing node runs in a Nitro Enclave and can only call KMS with a valid measurement.
  • I/O cost. DKLS23 is heavier on inbound/outbound data per cosigner than some competing protocols (CGGMP-family). For our latency targets this is not a constraint; for very high-frequency signing it would be worth measuring.

Integration into the signer

The signer service is a Go process. DKLS23 is consumed as a Rust library; the integration approach (FFI vs gRPC server) is still in flux and documented separately. From the perspective of this page, what matters is that the protocol logic does not run in pure Go — only the orchestration, networking, and lifecycle around it.

Out of scope here

  • The exact threshold value, refresh cadence, and wallet-to-key mapping — see Key lifecycle.
  • The protocol-level diagrams (DKG and signing rounds) — see Signing layer.