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
A secret is the constant term of a degree t−1 polynomial
Each party holds one point (share) on that polynomial
Any t shares reconstruct the secret via Lagrange interpolation
Fewer than t shares reveal nothing (information-theoretic)
TSS signs without ever reassembling the key in one place
The Collision attacks — common mistakes
Reconstructing the key on one machine — defeats the purpose
Choosing t too low (easy collusion) or too high (no liveness)
Doing interpolation over the reals instead of a finite field
Losing shares with no refresh / rotation plan
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>