Zeeka saysSchnorr signatures are linear and simple: a commitment, a challenge, a response — verified by one group equation. That linearity is what enables MuSig key aggregation.
Schnorr is the clean cousin of ECDSA. To sign: pick a random nonce k, publish the commitment R = g^k, compute the challenge e = H(R, m), and answer with s = k + e·x where x is the secret key. Verification is one line: g^s == R · y^e. No malleability, smaller than ECDSA, and — crucially — linear, so multiple signers can combine their pieces into a single signature (MuSig2).
The one rule you cannot break: never reuse or leak a nonce. Two signatures with the same k expose the private key via simple algebra. Bitcoin enabled Schnorr through the Taproot upgrade, unlocking compact multisig that looks identical to a single-key spend on-chain. The demo signs and verifies over a real order-11 subgroup of GF(23).
Power-ups you unlock
Sign: pick nonce k, R = g^k, e = H(R, m), s = k + e·x
Verify: g^s == R · y^e
Linearity lets several signers combine into one (MuSig2)
Smaller and cleaner than ECDSA; no signature malleability
Bitcoin enabled Schnorr via the Taproot upgrade
The Collision attacks — common mistakes
Reusing a nonce k across two signatures — leaks the private key
A predictable or low-entropy nonce — same disaster as reuse
Forgetting to bind both R and m into the challenge hash
Naive n-of-n multisig that is vulnerable to rogue-key attacks
Boss battleSign a message with Schnorr over GF(23) (the order-11 subgroup) and verify g^s == R · y^e.
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 Schnorr over a small prime-order group (toy scale, exact math).
const p = 23, q = 11, g = 2; // g has order q=11 in GF(23)*
const pw=(a,e,m)=>{ let r=1; a%=m; while(e>0){ if(e&1) r=(r*a)%m; a=(a*a)%m; e>>=1; } return r; };
const H = (R,m)=> (R*7 + m*13) % q; // toy hash → exponent mod q
const x = 6, y = pw(g, x, p); // secret key x, public key y = g^x
const m = 4, k = 9; // message, nonce
const R = pw(g, k, p);
const e = H(R, m);
const s = (k + e * x) % q; // s = k + e·x (mod q)
const lhs = pw(g, s, p), rhs = (R * pw(y, e, p)) % p;
document.getElementById('o').textContent = [
'Schnorr over GF(23), subgroup order 11',
'pubkey y = g^x = ' + y,
'sig (R, s) = (' + R + ', ' + s + ') e = H(R,m) = ' + e,
'verify g^s = ' + lhs + ' R·y^e = ' + rhs,
'valid? ' + (lhs === rhs)
].join('\n');
</script></body></html>