Threshold cryptography 101

Threshold cryptography is the math that lets a group of N parties share the ability to sign or decrypt, such that any subset of T parties can act jointly but no smaller subset can. The two non-negotiable properties:

  • T parties can produce a valid signature.
  • Any T−1 parties learn nothing useful about the secret.

This is the foundation of every Confium deployment.

Why threshold?

Consider a conventional CA: a single private key signs certificates. If that key is compromised, every certificate it ever issued is called into question. DigiNotar, Symantec, and Let’s Encrypt each had incidents where exactly this happened.

Now consider T-of-N = 3-of-5. The signing key is split into 5 shares; any 3 of them can produce a signature indistinguishable from one signed by a single key. To forge a signature, an attacker must compromise 3 of the 5 parties simultaneously — far harder than compromising one.

Shamir secret sharing

The simplest threshold scheme is Shamir’s, from 1979. The secret lives at the constant term of a polynomial of degree T−1 over a finite field. To split the secret:

  1. Pick a polynomial f(x) = a₀ + a₁x + a₂x² + ... + aₜ₋₁xᵗ⁻¹ where a₀ is the secret and a₁, ..., aₜ₋₁ are random.
  2. Each party gets a share (i, f(i)) for i = 1, 2, ..., N.
  3. To recover: any T shares uniquely determine the polynomial (Lagrange interpolation), so you can compute f(0) = a₀.

Fewer than T shares reveal nothing — any value of a₀ is consistent with T−1 points.

Why this is the right primitive

  • No key ceremony for the joint secret: the secret exists only at the moment of generation, then it’s gone. The shares are distributed; the secret never appears in any single machine’s memory again.
  • Tunable security threshold: 2-of-3 for moderate assurance, 3-of-5 for high assurance, 5-of-9 for the most paranoid deployments.
  • Composable with attribute policies: not just “any T of N parties” but “T of N parties from K distinct groups” — see attribute-based threshold.

Protocols above Shamir

Shamir gets you key generation and secret recovery. But you rarely want to actually recover the secret — every recovery puts it in one machine’s memory, defeating the purpose.

Real threshold signing protocols (FROST, CMP20, GG18) let T parties co-sign a message without ever reconstructing the secret. Each party contributes a partial signature; the partial signatures combine into the final signature. The secret stays split.

  • FROST (FROST-ed25519, FROST-P256) — two-round signing, efficient, well-studied.
  • CMP20 — three-round ECDSA threshold, stronger security model against malicious coordinators.
  • GG18 — older but widely deployed, multiplicative sharing.

Confium ships real implementations of all three.

Lagrange interpolation

The math that combines T shares. Given T points (x₁, y₁), ..., (x_T, y_T), the unique polynomial of degree T−1 passing through them is:

f(x) = Σᵢ yᵢ · ℓᵢ(x)

where ℓᵢ(x) = Πⱼ≠ᵢ (x − xⱼ) / (xᵢ − xⱼ) is the Lagrange basis polynomial. Setting x = 0 recovers the secret.

For practical signing, the same idea runs in the exponent: each party’s partial signature is σᵢ = f(i) · H(m) and the final signature is σ = Σᵢ ℓᵢ(0) · σᵢ.

Visual: how a signing session works

The diagram below shows a 3-of-5 signing session. Three parties participate (P1, P3, P5); two are offline (P2, P4). The coordinator collects partial signatures from the three participating parties and produces the final signature. The secret is never reconstructed on any single machine.

Threshold signing: T-of-N parties co-sign without reconstructing the secret. MESSAGE COORDINATOR aggregates shares P1 share 1 P2 offline P3 share 3 P4 offline P5 share 5 3-OF-5 QUORUM signature produced N = 5 T = 3 participating: 3 secret never rebuilt

Try it

The Confium homepage has an interactive quorum playground where you can drag T and N sliders and watch the threshold property in action.

For a worked code example, see the threshold signing walkthrough in the Rust workspace docs.

What this has to do with transparency logs

Once you have a valid threshold signature, you typically want a public, verifiable record that the signing happened. That’s where the transparency log comes in. The signature event becomes a leaf in a Merkle tree like the one below:

RFC 6962 Merkle tree: leaves hashed with 0x01 prefix, internal nodes with 0x02 prefix; root commits to the entire set. ROOT H(01|L|R) H(01|L|R) H(01|..) H(01|..) H(01|..) H(01|..) 0x01 entry[0] 0x01 entry[1] ★ 0x01 entry[2] 0x01 entry[3] inclusion proof for entry[1] root = commitment to all leaves

The root hash commits to every leaf. Inclusion proofs let any verifier independently confirm a specific signature event is in the log without revealing anything else about the log’s contents.

See also