freecoding.school100% FREE · NO SIGNUP
Proof PeaksISSUE #6 of 38

threshold signatures · t-of-n signing

ZeekaVSThe Collision
Zeeka saysThreshold signatures split one key across n parties so any t of them can sign, but fewer than t learn nothing — built on Shamir secret sharing.

A threshold signature (t-of-n) means a key is shared so that any t parties can jointly sign while t−1 learn nothing. The foundation is Shamir secret sharing: encode the secret as the constant term of a degree t−1 polynomial, hand each party one point on it, and any t points uniquely reconstruct the polynomial — and thus the secret — by Lagrange interpolation. Fewer than t points leave the secret information-theoretically hidden.

Real TSS never reassembles the key in one place; parties compute on their shares so the full key exists only implicitly. That removes the single point of failure custodial keys have, which is why MPC wallets and validator clusters use it. The demo splits the secret 42 over GF(101) and recovers it from two different sets of three shares.

Power-ups you unlock

The Collision attacks — common mistakes

Boss battleSplit the secret 42 with t=3 over GF(101), then recover it from two different sets of three shares.

Example code

<!doctype html><html><head><meta charset="utf-8"></head>
<body style="background:#06040d;color:#e6e0ff;font-family:monospace;padding:20px"><pre id="o"></pre>
<script>
// REAL Shamir secret sharing over GF(101): split a key into n, recover from t.
const p = 101, mod=(n)=>((n%p)+p)%p;
const pw=(a,e)=>{ let r=1; a=mod(a); while(e>0){ if(e&1) r=mod(r*a); a=mod(a*a); e>>=1; } return r; };
const inv=(a)=>pw(a, p-2);
const secret = 42;
const coeffs = [secret, 17, 8];                    // f(x) = 42 + 17x + 8x²  (t=3)
const f = (x)=> mod(coeffs.reduce((s,c,i)=> s + c*pw(x,i), 0));
const shares = [1,2,3,4,5].map(x => ({ x, y: f(x) }));   // n = 5 shares
function recover(pts){                             // Lagrange interpolation at x=0
  let acc = 0;
  for(let i=0;i<pts.length;i++){
    let num=1, den=1;
    for(let j=0;j<pts.length;j++) if(j!==i){ num=mod(num*(0 - pts[j].x)); den=mod(den*(pts[i].x - pts[j].x)); }
    acc = mod(acc + pts[i].y * mod(num*inv(den)));
  }
  return acc;
}
document.getElementById('o').textContent = [
  'secret = ' + secret + ', split into 5 shares, threshold t = 3',
  'shares: ' + shares.map(s=>'('+s.x+','+s.y+')').join(' '),
  'recover from shares 1,3,5 → ' + recover([shares[0],shares[2],shares[4]]),
  'recover from shares 2,4,5 → ' + recover([shares[1],shares[3],shares[4]]),
  '2 shares < t → information-theoretically hidden'
].join('\n');
</script></body></html>
▶ Open the interactive comic issue
‹ Schnorr Signatures · Linearity · Musig2Verifiable Random Functions · Vrf Sortition ›