You and a friend want to flip a coin over the phone. If you just say "heads" and she replies "agreed", whoever speaks last wins. The fix is a digital sealed envelope: lock your choice inside a mathematical safe you can't re-open dishonestly, hand over the safe, and only later reveal the key.
Two phases, two promises
Phase 1 · Commit
You publish a commitment C that "locks in" your value m using randomness r.
Phase 2 · Reveal
Later you open the envelope by showing (m, r); anyone can check they really produce C.
A useful commitment makes two contradictory-sounding promises at once:
Property
Meaning
What breaks without it
Hiding
C leaks nothing about m.
The "sealed envelope" is a window — your opponent reads your coin flip and always wins.
Binding
You can't later find a different (m′, r′) with the same C.
The envelope is rewritable — you wait for the opponent's move, then "reveal" whatever suits you.
🔍 Deeper dive · perfect hiding and perfect binding can't coexist
Here's a fundamental tradeoff, provable: if a commitment is perfectly hiding, then C is consistent with every possible message — some other pair (m′, r′) mathematically reopens it — but then an unbounded committer could hunt for that pair and binding is gone. Conversely, if exactly one opener exists, C pins down m and hiding is gone. So one of the two properties must rest on computational hardness. Designers choose which side deserves the information-theoretic guarantee: Pedersen picks perfect hiding / computational binding (binding leans on discrete-log hardness — Chapter 2 again), while simple exponential commitments C = gᵐ pick perfect binding / computational hiding. Same envelope, opposite insurance policies — a recurring design dial you'll meet again with trusted setups (Chapter 7).
Recipe: hash commitments
The simplest construction uses the previous chapter's blender: C = SHA-256(m ‖ r) where r is a fresh long random string (a nonce).
Why the random r is non-negotiable
A coin is only one bit — an attacker hashes both H(0) and H(1) and instantly knows which one your commitment is. Mixing in 128+ random bits swamps the message: the attacker would need to grind ~2¹²⁸ candidate rs. Randomness converts "small secret" into "astronomically large secret". Hiding comes from your r; binding comes from collision resistance of the hash.
🔍 Deeper dive · blinding — the recurring trick
The nonce r has a name worth remembering: a blinding factor — randomness folded into an encoding so the result looks uniformly random whatever the payload. The same move powers blind signatures (Chaum, 1982): a bank signs a blinded serial number it cannot read; you later unblind and spend — digital cash that is anonymous yet unforgeable. It powers Pedersen's perfect hiding below (for every m there's an r landing on the same C). And it reappears in Chapter 8, where your wallet hands each verifier a differently-blinded presentation of the same credential — that's what makes sessions unlinkable.
🧪 Coin-Flip Duel
The computer flips a coin and commits to the result before you guess. If it tried to flip "again" after hearing your guess, it would need a second r′ producing the same commitment with the opposite face — and that's exactly what the hash forbids. First to 3 points wins the duel.
🃏Coin-Flip Duel — verifiable fairnessyou 0 · cpu 0
Round 1 — the house has sealed its coin flip. Guess!
> awaiting your guess…
Attack lab: try to break binding
Words are cheap — let's attack it. Below, you commit to HEADS with a random nonce. Then the duel goes sideways and you'd really rather have committed to TAILS. Find any r′ that makes SHA-256("TAILS" ‖ r′) equal your original commitment:
🧨Binding Attack Lab
Commit first, then try to weasel out of it.
The 500-thousand-grind reality check
Finding a binding break means finding a hash collision on demand — expected cost ~2²⁵⁶. Your 500k grinds hit a probability of about 5·10⁵⁄2²⁵⁶ ≈ 0.000…(66 zeros)…01. The envelope stays sealed.
Leveled-up commitments: Pedersen
Hash commitments have one limitation: you can't do arithmetic on them. Pedersen commitments live in the modular universe of Chapter 2: C = gᵐ · hʳ mod p. They're perfectly hiding (any m has a matching r — information-theoretically sealed, if log_g h is unknown) and computationally binding (breaking it = solving a discrete log).
Their superpower is homomorphism: multiplying two commitments commits to the sum of the values, without ever opening either:
One detail matters enormously: h must be generated so that nobody knows γ = log_g h — typically by hashing a public, agreed string (a "nothing-up-my-sleeve" number) or via a small ceremony whose randomness is destroyed. Whoever knows γ can reopen commitments at will: since C = g^(m)·h^(r) = g^(m+γr), they can rewrite any committed m as any m′ by adjusting the nonce (m′ = m + γ(r−r′)). Binding — and the whole envelope — rests on γ staying dead.
🧮Pedersen Playground — commitments that add
m₁ =m₂ =
> waiting…
Watch the product of the two commitments equal a fresh commitment to m₁+m₂ — no values ever revealed.
🔍 Deeper dive · where sealed envelopes earn their keepSealed-bid auctions: bidders publish commitments, open them only after the deadline — no last-second underbidding. Mental poker: players commit to shuffled deals over a network. Voting: ballots are committed at cast time, mixed, then opened and tallied under public audit. Randomness beacons: commit-then-reveal sequences produce public randomness nobody can steer. And inside every protocol from the next chapter on: commitments are how a prover "lays cards face down" before the verifier names which to flip. Once you see the pattern, you'll spot commitments hiding in nearly every cryptographic ceremony.
Why commitments are the bones of every ZK protocol
In the 3-coloring proof (next chapter) the prover commits to a coloring, and soundness is binding: open one way per round and the graph must genuinely be colored. In SNARKs, polynomial commitments let a verifier check a function's behavior at a secret random point. Selective disclosure (Chapter 8) commits to attributes so the holder can later prove properties of them. Envelopes all the way down.
📌 Week 4 — key takeaways
Commit = seal in an envelope (hide), reveal = open with (m, r); the two-phase structure replaces trust with math.
Hash commitments C = H(m ‖ r): the nonce r is load-bearing — without it, small message spaces are guessable in one hash.
Perfect hiding and perfect binding are provably incompatible; you pick which side is information-theoretic and which is computational (Pedersen: perfectly hiding, binding via discrete log).
Pedersen homomorphism: C₁·C₂ = C(m₁+m₂, r₁+r₂) — arithmetic on sealed values without opening them.
Blinding (randomized encoding) is the recurring trick: e-cash, Pedersen, and Chapter 8's unlinkable credential presentations are all the same move.
🎯
Checkpoint: Sealed Envelopes
In C = SHA-256(m ‖ r), what does the random r mainly provide?
Binding — it stops hash collisions.
Hiding — it swamps small message spaces so attackers can't guess-and-check m.
Compression — it shortens the commitment.
Integrity — it detects transmission errors.
Without r, committing to a coin flip means publishing H(0) or H(1) — one hash lookup reveals it. Binding instead comes from SHA-256's collision resistance.
A commitment scheme that is binding but NOT hiding is useless as an envelope because…
the value can be changed after the fact.
it can't be verified at reveal time.
the commitment itself leaks the value — like sealing a letter in glass.
it requires a trusted setup.
Hiding = opacity, binding = immutability. You need both to replace a physical sealed envelope.
You hold C₁ = C(m₁, r₁) and C₂ = C(m₂, r₂), Pedersen commitments. What is C₁ · C₂?
A valid commitment to m₁ + m₂ with nonce r₁ + r₂.
A commitment to m₁ · m₂.
Random noise — commitments can't be combined.
A commitment that can never be opened.
Exponents add under multiplication — that's the homomorphism. There's no similarly clean way to multiply committed values, which is one reason building circuits over addition is cheap.
Why are Pedersen commitments called "perfectly hiding"?
The hash used is quantum-resistant.
Because p is enormous.
Because the nonce is hashed first.
For every possible message m there's an r making the same C — so C contains literally zero information about m.
Given C and any m′ you like, some r′ satisfies C = g^m′ h^r′ (r′ = (log_g C − m′)/log_g h). Information-theoretic opacity — no amount of compute helps — while binding leans on discrete-log hardness.