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:
where . The modulus forces both and 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 (i.e. plain without the ). The real secp256k1 is what you get by “plucking points mod ” from this curve, but when reasoning about point addition, tangents, and symmetry, the continuous picture is good enough.
At this point you might wonder: why is it called an elliptic curve? The general form is the Weierstrass equation . Drag 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 and on the curve, is computed in three steps:
- Draw a straight line through and .
- This line intersects the curve at a third point .
- Reflect across the -axis. The reflected point is .
Three special cases
- : when the two points coincide, “the line through both points” degenerates into “the tangent line at ”. Reflect the tangent’s third intersection with the curve and you get .
- and : define as the reflection of across the -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 (the point at infinity); reflecting still gives . So .
- Adding : is the identity element — for any point , .
It forms an abelian group
Including , every point on the curve satisfies the following under this addition:
- Closure: the sum of two points is still on the curve
- Associativity:
- Identity:
- Inverses: the inverse of is
- Commutativity:
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 called the base point (generator point), with fixed, publicly agreed coordinates. Adding to itself times returns (the point at infinity). is a large prime close to , called the order of the base point.
Pick a random integer between and , and the point obtained by adding to itself times is your public key; is the private key.
For the relationship between public key and private key to be useful, it has to be cheap to compute given , but hard to recover given . This asymmetry is what elliptic curve cryptography rests on.
When I first saw this equation, my immediate question was: if is added to itself times, doesn’t computing from also take additions? Wouldn’t that be just as slow as brute-forcing? Not at all. When you know exactly, you can use the binary-expansion trick (double-and-add) to compute efficiently.
Suppose . The double-and-add procedure looks like this:
- The binary representation of is .
- Starting from , compute , , .
- Reading off the binary digits, .
Just four additions — , , , — and you have , rather than thirteen separate additions. At most you need around additions (since can be as large as , close to ). The intermediate doublings , , , … can also be cached for further speedups. An attacker who doesn’t know , on the other hand, has no shortcut: they’re stuck computing , , , … from scratch until they hit .
Schnorr Signatures
Setup: generate a key pair with . We want to sign a message .
Signing
The signing procedure is:
- Pick a random number and compute .
- Compute the hash , where is the message and denotes concatenation.
- Compute the signature value .
- The signature is .
Verification
Let’s first take stock of what’s public:
- The public key
- The message
- The signature
- The hash (anyone can recompute it from , , )
Going back to the signing equation , multiply both sides by :
Substituting the public values and , this becomes:
Every term in this equation is public. The verifier just needs to check whether and are equal to decide if the signature is valid. Only someone who knows both and can produce a matching , which proves the signer holds the private key .
The random number is what protects the private key . The equation has only two unknowns, and , so if leaks, falls out directly. And if the same is ever reused across two signatures, an attacker doesn’t even need to know its value: subtracting the two signature equations cancels out and yields . Making sure every signature uses a fresh, distinct random is therefore critical.
Comments