Caloogy Article
中文

Schnorr Signatures and Σ-Protocols: The Simplest Zero-Knowledge Proof

Date
Jul 31, 2026
Series
Cryptography
Reading
4 min
Topics
SchnorrSigma protocolZero knowledgeFiat–Shamir

The one-sentence version

The Schnorr protocol lets you prove "I know xx such that y=gxy = g^x" without revealing xx itself. There are only three steps: commit, challenge, respond. Replace the verifier's challenge with a hash (the Fiat–Shamir transform) and the proof becomes a signature. Bitcoin's Taproot upgrade uses exactly this Schnorr signature, whose linear structure lets multiple signatures merge into one.

This article has three layers:

  1. The intuition: a three-step conversation that is convincing yet reveals nothing
  2. Real-world use: Bitcoin Taproot, MuSig2, Ed25519
  3. The mathematics: the protocol, soundness (the extractor), zero knowledge (the simulator), Fiat–Shamir and a worked example

Layer 1: The Intuition

1.1 Proving you know a password without saying it

You want to prove to a guard that you know the combination to the company safe, without telling him the combination. The Schnorr protocol offers a three-step conversation:

Verifier (knows only y = g^x)Prover (knows x)Verifier (knows only y = g^x)Prover (knows x)Check g^s = R · y^c1. Commit: pick random k, send R = g^k2. Challenge: pick a random number c3. Respond: send s = k + c·x

1.2 From conversation to signature

The conversation needs a verifier online to set the question. Fiat and Shamir's idea: let a hash function set the question, with c=Hash(R,message)c = \mathrm{Hash}(R, \text{message}). A hash's output can't be predicted, so the effect is the same as an honest verifier. The prover can now generate (R,s)(R, s) alone, and anyone can check it afterwards. This is a digital signature.


Layer 2: Real-World Use

Why Bitcoin didn't use Schnorr at first

Schnorr filed for a patent in 1989, which expired only in 2008. In the meantime the industry turned to the patent-avoiding DSA / ECDSA, which are structurally more complex and lack the clean linearity. When Bitcoin was born in 2009, Schnorr still had no mature standardized implementation, so ECDSA stayed.


Layer 3: The Mathematics

3.1 The protocol

Let G=⟨g⟩G = \langle g \rangle be a cyclic group of prime order qq (a subgroup of Zp×\mathbb{Z}_p^\times or an elliptic curve group), with private key x∈Zqx \in \mathbb{Z}_q and public key y=gxy = g^x.

  1. Commit: pick a random k∈Zqk \in \mathbb{Z}_q and send R=gkR = g^k;
  2. Challenge: the verifier sends a random c∈Zqc \in \mathbb{Z}_q;
  3. Respond: send s=k+cx mod qs = k + cx \bmod q;
  4. Verify: gs=?R⋅ycg^s \stackrel{?}{=} R \cdot y^c.

Correctness: gs=gk+cx=gk(gx)c=R ycg^s = g^{k + cx} = g^k (g^x)^c = R\, y^c.

3.2 Soundness: if you can answer two questions, you must know xx

Suppose a prover can answer two different challenges c≠c′c \neq c' for the same RR, giving s,s′s, s'. Then

gs=R yc,gs′=R yc′ ⇒ gs−s′=yc−c′ ⇒ x=s−s′c−c′ mod q.g^{s} = R\,y^{c},\quad g^{s'} = R\,y^{c'} \ \Rightarrow\ g^{s - s'} = y^{c - c'} \ \Rightarrow\ x = \frac{s - s'}{c - c'} \bmod q.

So anyone who "can fool the verifier" can in fact compute xx. This is called special soundness, and the procedure that computes xx is called the extractor. It uses the fact that qq is prime, so c−c′c - c' is invertible in Zq\mathbb{Z}_q.

3.3 Zero knowledge: an identical conversation without knowing xx

The simulator works backwards: first pick random ss and cc, then let R=gsy−cR = g^s y^{-c}. These three numbers satisfy the verification equation, and their distribution is exactly the same as a real conversation (ss and cc are uniformly random, and RR is determined by them).

Since someone who doesn't know xx can produce transcripts with the same distribution, a real conversation can't reveal anything about xx. This is how zero knowledge is defined. (Strictly speaking, the Schnorr protocol is "honest-verifier zero knowledge".)

3.4 The Fiat–Shamir transform: becoming a signature

Replace the challenge with c=H(R ∥ y ∥ m)c = H(R \,\|\, y \,\|\, m):

In the random oracle model, forging a signature is equivalent to solving the discrete logarithm.

3.5 A worked example

p=23p = 23, q=11q = 11, g=2g = 2

211=2048=89⋅23+12^{11} = 2048 = 89 \cdot 23 + 1, so g=2g = 2 has order 1111 in Z23×\mathbb{Z}_{23}^\times.

Keys: private key x=3x = 3, public key y=23=8y = 2^3 = 8.

Signing (suppose the hash gives c=4c = 4):

  • Pick k=5k = 5, R=25=32≡9R = 2^5 = 32 \equiv 9
  • s=5+4⋅3=17≡6(mod11)s = 5 + 4 \cdot 3 = 17 \equiv 6 \pmod{11}

Verification:

  • Left side: gs=26=64≡18g^s = 2^6 = 64 \equiv 18
  • Right side: R yc=9⋅84R\,y^c = 9 \cdot 8^4. 84=4096=178⋅23+2≡28^4 = 4096 = 178 \cdot 23 + 2 \equiv 2, so 9⋅2=189 \cdot 2 = 18
  • Equal ✓

The disaster of reusing kk: sign another message with the same k=5k = 5; the hash gives c′=7c' = 7 and s′=5+7⋅3=26≡4s' = 5 + 7 \cdot 3 = 26 \equiv 4. An attacker sees that the two signatures have the same RR and applies the extractor from section 3.2: x=s−s′c−c′=6−44−7=2−3(mod11).x = \frac{s - s'}{c - c'} = \frac{6 - 4}{4 - 7} = \frac{2}{-3} \pmod{11}. −3≡8-3 \equiv 8 and 8−1≡78^{-1} \equiv 7 (8⋅7=56≡18 \cdot 7 = 56 \equiv 1), so x=2⋅7=14≡3x = 2 \cdot 7 = 14 \equiv 3, and the private key is recovered.

The "extractor" in the soundness proof is, in the real world, the attacker. (Checked with Python.)


Summary

Layer Key points
Intuition Commit, challenge, respond; RR is fixed before the question is seen, so cheating fails
Soundness Two answers for the same RR solve for xx (the extractor)
Zero knowledge Fake conversations built backwards have the same distribution as real ones (the simulator)
Engineering Fiat–Shamir yields signatures; linearity gives MuSig2 and FROST; kk must never repeat