Skip to content
Sonr Crypto
Esc
navigateopen⌘Jpreview
On this page

Threshold & MPC

Splitting keys across parties so no single machine ever holds a signing key — secret sharing, distributed key generation, and threshold signing.

Everything in this section exists to answer one question: how do you sign without any single machine ever holding the private key? The answer is built in four layers, and each layer is a separate package in this repository. Reading them bottom-up is the fastest way to make sense of the code.

The stack

Oblivious transfer — ot/base/simplest, ot/extension/kos

The raw two-party primitive. A sender holds two messages, a receiver picks one, and neither learns anything about the other’s choice. Threshold ECDSA needs it because ECDSA multiplies two secrets together, and OT is how two parties multiply shares without revealing them. You will almost never call this directly. See Oblivious Transfer.

Secret sharing — sharing, sharing/v1

Shamir, Feldman, and Pedersen. Given a secret that already exists, split it into n shares so that any t reconstruct it. Purely local: one process does the splitting. See Secret Sharing.

Distributed key generation — dkg/frost, dkg/gennaro, dkg/gennaro2p

Each party samples its own contribution and the parties run an interactive protocol. The resulting signing key is never assembled anywhere. See Distributed Key Generation.

Threshold signing — tecdsa/dklsv1, ted25519

Consume a DKG output and produce a signature that verifies under an ordinary ECDSA or Ed25519 verifier. See Threshold ECDSA and Threshold Ed25519.

Sharing a secret is not the same as DKG

This is the distinction people get wrong, and getting it wrong voids the entire security argument.

Secret sharing with a dealer (sharing.Shamir, sharing.Feldman, sharing.Pedersen, tecdsa/dklsv1/dealer) starts from a secret that exists in one process’s memory. That process runs a polynomial, emits n shares, and hands them out. For the duration of Split, one machine knows the whole key. If that machine is compromised — or if it neglects to zero the secret, or if it is swapped to disk — the key is gone. Threshold reconstruction after the fact does not undo that.

Distributed key generation (dkg/frost, dkg/gennaro, dkg/gennaro2p, and the DKG phase of tecdsa/dklsv1) never forms the key. Each participant i samples its own secret s_i, shares s_i with everyone, and the joint key is the sum of every contribution. Each party ends up with a share of Σ s_i and the public key Σ s_i · G, and no participant — not even a coalition below threshold — ever sees the key.

Protocol comparison

Package Threshold model Curves Rounds Notes
sharing (Shamir/Feldman/Pedersen) t-of-n, 2 ≤ t ≤ n ≤ 255 any curves.Curve none (local) Trusted dealer
sharing/v1 t-of-n elliptic.Curve / curves.Field none (local) Legacy; []byte secrets
dkg/frost t-of-n any curves.Curve 2 Feldman VSS + Schnorr PoK
dkg/gennaro t-of-n, ids must be exactly 1..n k256 and other elliptic.Curve 4 Pedersen then Feldman
dkg/gennaro2p 2-of-2 elliptic.Curve 2 + Finalize Façade over dkg/gennaro
tecdsa/dklsv1 (DKG) 2-of-2 only K256, P256 10 interleaved half-rounds DKLs18
tecdsa/dklsv1 (sign) 2-of-2 only K256, P256 4 interleaved half-rounds Bob receives the signature
tecdsa/dklsv1 (refresh) 2-of-2 only K256, P256 7 interleaved half-rounds Public key unchanged
ted25519/ted25519 t-of-n Ed25519 only 1 round + aggregation Output is a plain Ed25519 signature
ted25519/frost t-of-n any curves.Curve 3 Schnorr, needs a dkg/frost result
ot/base/simplest 2-party any curves.Curve 8 interleaved half-rounds Internal
ot/extension/kos 2-party K256, P256 (tested) 3 Internal

Do not drive rounds by hand

For 2-of-2 ECDSA — which is what a Sonr wallet uses — the round-level API is not the intended entry point. Two layers sit above it:

  1. tecdsa/dklsv1’s protocol.Iterator wrappers (NewAliceDkg, NewBobSign, …) reduce every protocol to a Next(msg) loop over opaque *protocol.Message values you can put on a wire.
  2. The mpc package wraps that into an enclave with key import/export, signing, and serialization. Application code should start there. See MPC Enclave.

Reach for the numbered Round1..Round10 methods only when you are writing your own transport, or auditing.

Where to next

Last updated on September 2, 2026

Was this page helpful?