Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Part I · Bricks: the cryptographic floor This chapter closes the loop. You will assemble the previous two chapters into real ECDSA, then count how many times priv appears inside verify.


3.0 First, why signatures need to exist at all

You have two things now: a hash (chapter 1) and a key pair (chapter 2).

Before going further, ask the obvious question — almost everyone asks it at this point:

A hash is also easy-forwards and hard-backwards. Why can’t we just use that as a key pair?

It is an excellent question, because thinking it all the way through derives the entire reason signatures exist.

Try it: a hash as an identity

Pick a secret number x. Call it the private key. Compute hash(x), publish it, call it the public key.

Nobody can recover x from the hash. When you need to prove “I am the person behind this public key,” you reveal x, everyone hashes it, it matches — that’s you.

This works. In fact you already wrote it: this is chapter 1’s commitment, used as an ID card.

And here it dies

The trouble:

To prove anything, you must produce x itself. Produce it once, and x is burned.

Next time, the whole world already knows x. Anyone can impersonate you.

Stop here, because this is one of the most important contrasts in the book:

Hash-as-identityAn actual private key
To proveYou must hand over the secret (reveal)The secret never appears
Usable how many timesOnce, then deadUnlimited

And be precise about where the difference is. At the public-key layer, both are public — a published hash and a published curve point are equally exposed. That is not the difference. The difference is entirely at the proving layer: the hash approach must expose the secret, while the key pair only exposes a value computed from the secret.

That is the watershed. Which turns the question into:

Is there a way to prove I know a secret without saying what it is?

That question is the entire reason digital signatures exist. This chapter is the answer.


3.1 While we’re here: what is a signature actually for?

We sign contracts constantly. But a handwritten signature is not very good, and it has exactly two holes. Seeing them tells you precisely what a digital signature is buying you.

Hole one: it can be forged. Practise someone’s handwriting and you can get close enough that the person checking cannot tell.

Hole two: it can be peeled off and moved. Your signature on a contract and your signature on an IOU look identical — because the signature has nothing to do with the content. So someone can detach the page you signed and staple it to a different document. “I signed version A, how did you end up with version B?” Good luck proving it.

Remember those two words: forgeable and transplantable. A digital signature kills one each.

Killing hole one: the seal stays home

A medieval king had one unique signet ring. Pressed into wax it left a mark the whole country recognized. Everyone knew what the mark looked like — but the ring itself never left the king’s hand, and nobody could manufacture a second one.

The elegant part: the person checking the seal does not need to own the ring.

In this book’s vocabulary: you hold a unique seal (private key); everyone else holds a lamp that reveals whether a seal is genuine (public key). Stamping requires the seal, which only you have. Checking requires the lamp, and the lamp is safe to hand out to the entire world because a lamp can only inspect, never stamp.

Handwriting can be imitated; a seal cannot be duplicated. Hole one closed.

Killing hole two: the signature moves with the content

A digital signature is not stamped onto a document from outside. It is computed from your private key together with every character of that document.

Change one character and the whole signature changes. So a digital signature is welded to this document, this version. Peel it off, staple it to version B, and it fails on inspection.

Hole two closed.

That is the complete reason a digital signature beats a handwritten one. Not more, not less.


3.2 Bring in the bricks

A signature is not new magic. It is a composition of old parts. Set them up first.

This chapter uses a smaller curve: y2=x3+x+4(mod23)y^2 = x^3 + x + 4 \pmod{23}, with G=(1,12)G=(1,12).

Why change? Because signature mathematics needs one extra property: the order of G must be prime. On this curve G has order 29, which is prime; on chapter 2’s curve G had order 50, which is not. (A composite order breaks the modular inverses the signature equation relies on. Real Bitcoin’s curve satisfies the same requirement.)

bricks ready. G = (1, 12)  n = 29

There is not one new line in that cell. inv, point_add, scalar_mul are all yours from chapter 2, unchanged except for the curve constants.

Worth noticing: the “magic” that follows is built entirely from parts you already understand.

Make a key pair

private key = 7   (hidden)
public key  = (0, 21)   (published)

private key = 7, public key = (0, 21). Same two shapes as chapter 2 — one integer, one tuple.

Squeeze the message into a number

A signature does not sign raw text. First the message is hashed into a number z:

z(pay 0.5 to Alice) = 4
z(pay 5 to Bob)     = 7

hash_to_int is chapter 1’s sha256 plus one line: turn the 32-byte fingerprint into a single integer between 0 and 28.

(Real Bitcoin’s n is a 256-bit number, so almost nothing is lost. Here n=29 compresses brutally, purely so you can follow the arithmetic by hand.)

And section 3.1’s “the signature moves with the content” originates in exactly this line: change one character and z changes, and every subsequent computation changes with it.


3.3 sign — requires the private key

signature (r, s) = (18, 25)

Output: signature (r, s) = (18, 25).

Be clear what a signature is: a tuple of two integers.

Not a hash, not a blob of ciphertext. Two numbers. That is the first layer of “a signature is not a hash”: a hash returns one value, a signature returns two.

Now look at the function’s inputs. Three parameters, and one of them is priv — signing requires the private key, and there is no way around that.

About k: it is a one-time nonce, and it must be fresh every single time. Passing it in by hand here exists only so your output matches the book’s. In a real system k must be a secret random value — and section 3.6 explains what happens when it isn’t, using events that actually occurred.


3.4 verify — the pivot of the whole book

Here is the verification function. Before you read it, know that you are about to count something.

verify: True

It prints True.

Now count

How many times does priv appear in the body of verify?

Zero.

Its three parameters — pub, msg, sig — are all public. Everything it touches inside — inv, z, point_add, scalar_mul, G, pub — is public.

Anyone can run this function. Every full node on the Bitcoin network verifies thousands of transactions a day using a function of exactly this shape. None of them knows your private key, and all of them can confirm you authorized the payment.

That is the answer to the question in 3.0:

Prove you know the secret, without saying what it is.

sign contains priv. verify does not. The rest of this book stands on that asymmetry.

The second difference from hashing

Chapter 1’s hash is a machine with one input: content goes in, a fingerprint comes out, and anybody can turn the crank.

Signing is a machine with two inputs: content and the private key go in, a signature comes out, and only the key holder can operate it.

Verification takes three: content, signature, and public key. Note that the lamp contains no private key and does not regenerate the signature — it is a gate that outputs True or False and nothing else.


3.5 Three attacks, three failures

tampered content : False
wrong identity   : False
guessed signature: False

Three Falses. And they fail for three different reasons, which is worth reading carefully:

AttackWhy it failsWhich hole it closes
TamperingThe message changed, so z went from 4 to 7, so the computed X no longer matches r3.1’s hole two (transplanting)
Impersonationverify uses pub to compute X; a different key gives a different XIdentity binding
ForgeryWithout priv you cannot produce an (r, s) satisfying the equation3.1’s hole one (forgery)

Unforgeable, unimpersonatable, untamperable. And all three fall out of one equation.

YOUR TURN

new signature: (4, 18)  still valid?: True
valid (r,s) pairs found by brute force: 26 / 784

Question 1 prints (4, 18) — completely different from (18, 25) — and still verifies. So one message has many valid signatures. A signature is not a fingerprint of the message; it is evidence that you hold the key, and evidence can be produced in unlimited forms.

Question 2: both k=7 and k=22 return None. Not a bug — a genuine ECDSA detail. A few unlucky nonces drive r or s to zero, and real implementations simply pick another.

Question 3 prints 26 / 784.

That number is more interesting than it looks. 26/784 ≈ 3.3%, and 1/n = 1/29 ≈ 3.4%. They are nearly equal, and that is not a coincidence:

The probability that a randomly guessed (r, s) verifies is about 1/n.

On this curve n = 29, so roughly one guess in thirty works — on a toy curve, forgery is entirely practical.

Real Bitcoin has n ≈ 2²⁵⁶. Same formula, so the probability is 1/2²⁵⁶. A billion guesses a second until the heat death of the universe and your odds still round to zero.

Chapter 2’s sentence again: security is not the algorithm, it is the scale.


3.6 A real lesson: never reuse k

We passed k in as a parameter for reproducibility. In a real system k must be a fresh random value every time.

What happens if the same k signs two different messages?

Look at that line in sign:

s = (inv(k, n) * (z + r * priv)) % n

Same k → same r (since r depends only on k). So an observer has two equations, two known z values, two known s values, and only two unknowns: k and priv.

Two equations, two unknowns. High-school algebra recovers the private key.

This is not a theoretical concern. In the early 2010s, Android’s Bitcoin wallets reused k because of a flaw in the system random number generator, and real funds were stolen. Sony’s PlayStation 3 code-signing key leaked the same way — they had hardcoded k as a constant.

A signature’s security depends on the mathematics and on how you use it. This is the first time that shows up in this book, and it will not be the last — chapters 11, 13 and 18 all contain a mathematically flawless design ruined by an engineering detail.

(Real Bitcoin now generally uses RFC 6979: derive k deterministically from the private key and the message, so it depends on no random number generator at all. Reproducible and never repeated.)


3.7 A thirty-year gap

Part I ends here. You have three bricks: hashing, key pairs, signatures.

Worth knowing: all three existed thirty years before Bitcoin.

Digital signatures were invented in 1976–77. The moment they existed, people began chasing one goal: digital cash.

YearWhoWhat they builtWhere it stalled
1982David ChaumBlind signatures → DigiCash / eCash, the first serious attemptNeeded a central bank to stop double-spends
1997Adam BackHashcash proof-of-workNot money — postage
1998Wei Daib-money: a group keeping a ledger togetherStayed a proposal
1998Nick SzaboBitgold: proof-of-work plus a chained structureStayed a paper

Every one of them assumed signatures as the foundation, and every one of them stalled on the same thing.

A signature proves “I authorized this payment.” It cannot tell you whether I already spent that same coin somewhere else.

Because a signature is local: it can establish the validity of the transaction in front of you, and it has no way of knowing whether another equally valid transaction exists somewhere spending the same coin. Detecting that requires a ledger everyone agrees on.

And “how do mutually distrustful strangers maintain a shared ledger” — that is not a cryptography question.

That is what chapter 4 begins. From here on, the cryptography in your code thins out and systems, consensus, game theory and economics take over.

The prologue’s claim starts being cashed on the next page.


3.8 The ledger

What you wroteField
hash_to_int() — message to numberCryptography (reusing chapter 1)
sign(priv, msg, k) — signing with the private keyCryptography
verify(pub, msg, sig) — verifying, with no privCryptography
“Never reuse k”Engineering safety — not mathematics

Three conclusions:

  1. A signature is not a hash. A hash: one input, one output, anyone can compute it. A signature: two inputs, two outputs, only the key holder can produce it.

  2. Verification never touches the private key. Public verification, private key permanently hidden — and this is also the root of why an entire chain can be independently checked by anyone.

  3. Composition. A signature = a hash + an elliptic curve + one equation. This chapter invented no new primitive. It only put chapters 1 and 2 next to each other.

You have now walked all of Part I:

bytes → hash → commitment → finite field → curve → public key → sign & verify


Next

The hash time-stamp chain.

You will take chapter 1’s hash and do something Haber and Stornetta did in 1991: link data head-to-tail, then edit one item in the middle and watch everything after it collapse.

That chapter contains no new cryptography at all. It is the first piece of systems design in this book.

It is also where the “chain” in blockchain actually comes from.