Home

Schnorr Signatures

Bitcoin currently supports two signature schemes side by side: ECDSA and Schnorr. ECDSA is the original, in use since the Genesis block in 2009, while Schnorr (BIP-340) was introduced with the Taproot upgrade activated in November 2021. Both are built on the secp256k1 curve. ECDSA was invented to sidestep the Schnorr patent and is notoriously awkward to reason about. Now that the Schnorr patent has expired, we can skip ECDSA and go straight to the real thing.

secp256k1

secp256k1 is an elliptic curve defined over a finite field, given by:

y2=x3+7(modp)y^2 = x^3 + 7 \pmod p

where p=2256232977p = 2^{256} - 2^{32} - 977. The modulus forces both xx and yy to be integers, so secp256k1 is not a continuous curve but rather a collection of discrete points.

A scatter plot, however, is hard to build intuition from. The image below shows the curve before the modulo — drawn over the real numbers R\mathbb{R} (i.e. plain y2=x3+7y^2 = x^3 + 7 without the modp\bmod\, p). The real secp256k1 is what you get by “plucking points mod pp” from this curve, but when reasoning about point addition, tangents, and symmetry, the continuous picture is good enough.

y² = x³ + 7secp256k1
a0
b7

At this point you might wonder: why is it called an elliptic curve? The general form is the Weierstrass equation y2=x3+ax+by^2 = x^3 + ax + b. Drag aa to the left in the figure above and you’ll see exactly where the name comes from.

Point Addition

Point addition is the central operation of elliptic curve cryptography. Everything that follows — keys, signatures, verification — is built on top of it. The geometric definition goes like this:

Given two points PP and QQ on the curve, P+QP + Q is computed in three steps:

  1. Draw a straight line through PP and QQ.
  2. This line intersects the curve at a third point RR.
  3. Reflect RR across the xx-axis. The reflected point is P+QP + Q.
RP + QPQ

Three special cases

  • P=QP = Q: when the two points coincide, “the line through both points” degenerates into “the tangent line at PP”. Reflect the tangent’s third intersection with the curve and you get 2P2P.
  • PP and P-P: define P-P as the reflection of PP across the xx-axis. The line through them is vertical and meets the curve only at those two points. Mathematicians take “the third intersection lies at infinity” as a convention here, written O\mathcal{O} (the point at infinity); reflecting O\mathcal{O} still gives O\mathcal{O}. So P+(P)=OP + (-P) = \mathcal{O}.
  • Adding O\mathcal{O}: O\mathcal{O} is the identity element — for any point PP, P+O=PP + \mathcal{O} = P.

It forms an abelian group

Including O\mathcal{O}, every point on the curve satisfies the following under this addition:

  • Closure: the sum of two points is still on the curve
  • Associativity: (P+Q)+R=P+(Q+R)(P + Q) + R = P + (Q + R)
  • Identity: O\mathcal{O}
  • Inverses: the inverse of PP is P-P
  • Commutativity: P+Q=Q+PP + Q = Q + P

Five boxes ticked → an abelian group. This means all the familiar properties of everyday addition carry over to points on the curve.

Key Pairs

secp256k1 has a special point GG called the base point (generator point), with fixed, publicly agreed coordinates. Adding GG to itself nn times returns O\mathcal{O} (the point at infinity). nn is a large prime close to 22562^{256}, called the order of the base point.

Pick a random integer dd between 11 and n1n-1, and the point P=dGP = dG obtained by adding GG to itself dd times is your public key; dd is the private key.

For the relationship between public key PP and private key dd to be useful, it has to be cheap to compute PP given dd, but hard to recover dd given PP. This asymmetry is what elliptic curve cryptography rests on.

When I first saw this equation, my immediate question was: if PP is GG added to itself dd times, doesn’t computing PP from dd also take dd additions? Wouldn’t that be just as slow as brute-forcing? Not at all. When you know dd exactly, you can use the binary-expansion trick (double-and-add) to compute PP efficiently.

Suppose d=13d = 13. The double-and-add procedure looks like this:

  1. The binary representation of 1313 is 11011101.
  2. Starting from GG, compute 2G=G+G2G = G + G, 4G=2G+2G4G = 2G + 2G, 8G=4G+4G8G = 4G + 4G.
  3. Reading off the binary digits, 13G=G+4G+8G13G = G + 4G + 8G.

Just four additions — GG, 2G2G, 4G4G, 8G8G — and you have 13G13G, rather than thirteen separate additions. At most you need around 256256 additions (since dd can be as large as n1n-1, close to 22562^{256}). The intermediate doublings 2G2G, 4G4G, 8G8G, … can also be cached for further speedups. An attacker who doesn’t know dd, on the other hand, has no shortcut: they’re stuck computing GG, 2G2G, 3G3G, … from scratch until they hit PP.

Schnorr Signatures

Setup: generate a key pair (d,P)(d, P) with P=dGP = dG. We want to sign a message mm.

Signing

The signing procedure is:

  1. Pick a random number kk and compute R=kGR = kG.
  2. Compute the hash e=H(RPm)e = H(R \| P \| m), where mm is the message and \| denotes concatenation.
  3. Compute the signature value s=k+ed(modn)s = k + ed \pmod n.
  4. The signature is (R,s)(R, s).

Verification

Let’s first take stock of what’s public:

  • The public key PP
  • The message mm
  • The signature (R,s)(R, s)
  • The hash ee (anyone can recompute it from RR, PP, mm)

Going back to the signing equation s=k+ed(modn)s = k + ed \pmod n, multiply both sides by GG:

sG=kG+edG(modn)sG = kG + edG \pmod n

Substituting the public values R=kGR = kG and P=dGP = dG, this becomes:

sG=R+eP(modn)sG = R + eP \pmod n

Every term in this equation is public. The verifier just needs to check whether sGsG and R+ePR + eP are equal to decide if the signature is valid. Only someone who knows both kk and dd can produce a matching ss, which proves the signer holds the private key dd.

The random number kk is what protects the private key dd. The equation s=k+ed(modn)s = k + ed \pmod n has only two unknowns, kk and dd, so if kk leaks, dd falls out directly. And if the same kk is ever reused across two signatures, an attacker doesn’t even need to know its value: subtracting the two signature equations cancels kk out and yields dd. Making sure every signature uses a fresh, distinct random kk is therefore critical.

Comments

Loading...