Introduction

Imagine a game show where a contestant whispers a number into a sealed envelope, hands it to the host, and an hour later proves to the audience that the envelope contains exactly that number — and not a different one they chose after seeing the results. For the game to be fair, two things must hold: the host cannot peek at the number before the reveal, and the contestant cannot swap the number after sealing the envelope. That is the commitment problem in cryptography.

Pedersen commitments, introduced by Torben Pedersen in 1991, solve this problem with elegant mathematics. A committer computes a single group element C that hides the secret value completely — even an adversary with unlimited computation cannot distinguish a commitment to 7 from one to 42. Yet once the committer reveals the secret, a verifier can check instantly that C was computed from exactly that value. Changing the committed value later would require breaking the discrete logarithm assumption, which no known algorithm can do efficiently.

What makes Pedersen commitments remarkable is that both properties come for free from a single algebraic structure — no hash functions, no encryption keys, just arithmetic in a cyclic group. They are perfectly hiding (information-theoretically secure) and computationally binding (secure under a well-studied hardness assumption). This careful asymmetry is not a bug; it is the mechanism that enables the commitment to be composed inside zero-knowledge proofs and modern cryptographic protocols.

Commit and Reveal

Pick a secret value and click Commit — the demo seals it into a single number using a blinding factor chosen at random. The commitment reveals nothing about your secret. Then click Reveal to open it and verify that the commitment matches.

<p class="hint">
  {{hint}}
</p>
<div class="params">
  <div class="row">
    <span class="label">{{label_p}}</span>
    <span class="val" id="pVal"></span>
  </div>
  <div class="row">
    <span class="label">{{label_g}}</span>
    <span class="val" id="gVal"></span>
  </div>
  <div class="row">
    <span class="label">{{label_h}}</span>
    <span class="val" id="hVal"></span>
  </div>
</div>
<div class="input-row">
  <label for="secret">{{secret_label}}</label>
  <input id="secret" type="number" min="0" max="9999" value="42" />
</div>
<div class="btns">
  <button id="commitBtn" type="button">{{btn_commit}}</button>
  <button id="revealBtn" type="button" disabled>{{btn_reveal}}</button>
  <button id="resetBtn" type="button" class="ghost">{{btn_reset}}</button>
</div>
<div id="output"></div>
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; }
.hint { font-size: .88rem; color: #444; margin: 0 0 .8rem; line-height: 1.5; }
.params { background: #f0f4f8; border: 1px solid #d0dae4; border-radius: 8px; padding: .6rem .9rem; margin-bottom: .9rem; font-size: .85rem; }
.params .row { display: flex; gap: .5rem; align-items: baseline; margin-bottom: .2rem; }
.params .row:last-child { margin-bottom: 0; }
.label { color: #5a7088; min-width: 90px; font-weight: 600; }
.val { font-family: ui-monospace, monospace; color: #1d3557; word-break: break-all; }
.input-row { display: flex; align-items: center; gap: .6rem; margin-bottom: .7rem; flex-wrap: wrap; }
label { font-size: .9rem; font-weight: 600; color: #333; }
input { font: 400 .95rem system-ui; padding: .3rem .5rem; border: 1px solid #a0b0bf; border-radius: 6px; width: 120px; }
.btns { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: .8rem; }
button { font: 600 14px system-ui; padding: .45rem .9rem; border: 1px solid #1d3557; background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
button:disabled { opacity: .45; cursor: default; }
#output { font-size: .9rem; line-height: 1.65; }
.block { background: #f0f4f8; border: 1px solid #d0dae4; border-radius: 8px; padding: .65rem .9rem; margin-bottom: .6rem; }
.block h3 { margin: 0 0 .4rem; font-size: .9rem; color: #1d3557; letter-spacing: .03em; }
.mono { font-family: ui-monospace, monospace; font-size: .85rem; word-break: break-all; }
.ok { color: #0a7d33; font-weight: 700; }
.bad { color: #c92f3c; font-weight: 700; }
.step { margin: .2rem 0; }
.kv { display: flex; gap: .5rem; }
.kv .k { color: #5a7088; min-width: 120px; font-weight: 600; }
// Code not found

Notice the asymmetry. The commitment is a single number, yet it completely hides the secret. The reveal provides both the secret and the blinding factor, and verification is instant: recompute the commitment and compare. Changing the secret after committing would require computing a discrete logarithm — a problem believed to be computationally infeasible.

The Security Guarantee

Pedersen commitments rest on two independent security properties — and understanding their asymmetry reveals why the scheme is so powerful.

Setup: choose a large prime p, a generator g of Z*_p, and a second random generator h whose discrete logarithm log_g(h) is unknown to everyone (this is the trapdoor). To commit to a value m using a random blinding factor r, compute:

C = gmg^{m} · hrh^{r} (mod p)

Perfectly hiding — information-theoretically secure. For any fixed commitment C and any target value m*, there exists exactly one blinding factor r* such that C = gmg^{m}* · hrh^{r}* (mod p). This means no matter how much computation an adversary applies, they cannot distinguish a commitment to m from a commitment to m*. The distribution over commitments is identical regardless of the secret. Even a computationally unbounded eavesdropper learns zero bits about m from C.

Computationally binding — secure under discrete log. A cheating committer can only change the opening from (m, r) to (m', r') by finding a pair where gmg^{m} · hrh^{r}gmg^{m}' · hrh^{r}' (mod p), which requires computing log_g(h). No polynomial-time algorithm is known for this under the discrete logarithm (DLOG) assumption. This was proven in Pedersen's 1991 paper at CRYPTO.

The intentional asymmetry: the binding property is computational (not information-theoretic). This is not a weakness — it is a feature. It means the commitment can be used inside zero-knowledge proof systems where the prover can convince a verifier of facts about the committed value without revealing it. See also discrete log for the hardness assumption underneath.

If the discrete log were ever solved — for instance by a large quantum computer running Shor's algorithm — commitments could be broken. Lattice-based alternatives are being researched for the post-quantum world.

Where It Matters

Pedersen commitments are a foundational primitive that appears wherever a protocol needs to promise a value without revealing it:

  • Confidential transactions (Monero, MimbleWimble, Liquid): each transaction output is replaced by a Pedersen commitment to its value. The amounts remain private, but miners can verify that the sum of inputs equals the sum of outputs — using the homomorphic property: C(a) · C(b) = C(a + b). Nobody sees the amounts; everyone can check the books.
  • Zero-knowledge proofs (zk-SNARKs, Bulletproofs): prover commits to a witness (e.g. "I know a secret key") and then proves statements about it without revealing the witness. Pedersen commitments are the building block for range proofs, shuffle proofs, and many others.
  • Verifiable secret sharing: Pedersen's 1991 paper introduced the scheme specifically for VSS — distributing a secret among n parties so that any t of them can reconstruct it, with each party able to verify their share is consistent without seeing anyone else's share.
  • Electronic voting: a voter commits to their ballot before any result is known, then reveals it in the tallying phase. The commitment prevents vote-changing while keeping ballots private until the deadline.
  • Multi-party computation: parties commit to their private inputs at the start of a protocol, run a joint computation, and reveal outputs — the commitment ensures nobody can retroactively adjust their input based on others' data.

The homomorphic property — that commitments can be added without opening them — is what makes Pedersen commitments uniquely powerful compared to hash-based schemes.

Conclusion

Pedersen commitments distill a deep idea into a single multiplication: C = gmg^{m} · hrh^{r}. The committer seals a secret into a single group element that is information-theoretically indistinguishable from any other commitment — an adversary with infinite compute learns nothing. Yet the committer is locked in: changing the opening requires solving the discrete logarithm, which no known algorithm can do efficiently.

This elegant asymmetry is what powers the privacy layer of modern blockchains, the validity of zero-knowledge proofs, and the integrity of distributed cryptographic protocols. A scheme introduced in 1991 to solve verifiable secret sharing has become one of the most-used primitives in applied cryptography — proof that elegant mathematics ages well.

The next challenge is the post-quantum world: once large quantum computers arrive, Shor's algorithm breaks the discrete logarithm assumption and with it the binding property. Lattice-based commitments are actively being developed as the successor — the same promise, on harder mathematics.

Share this article

Pick a channel — or use your device's native share sheet.

Comments

Loading comments...

https://www.kipuhub.com/en/article/pedersen-commitments/Content licensed under CC BY-NC 4.0.