Introduction

Imagine you want to whisper a secret to a stranger across a crowded room where everyone can hear every word you say. It sounds impossible — yet this is exactly what your browser does every time it opens a secure connection.

For thousands of years, two people could only share a secret code if they had already met to agree on it. The mailman, the wiretapper, anyone on the line could copy the key in transit. In 1976, Whitfield Diffie and Martin Hellman published New Directions in Cryptography and broke that rule forever: two parties who have never met can agree on a shared secret while an eavesdropper records the entire conversation — and the eavesdropper still ends up with nothing.

The magic is not a trick of misdirection. It is a piece of arithmetic that is easy to do forwards and brutally hard to undo.

Run the Exchange

Below, Alice and Bob agree on a shared secret using only public messages. They both start from agreed public numbers: a base g and a prime modulus p. Each secretly picks a private number, then they swap mixtures — never the secrets themselves. Pick the private numbers and step through it.

<p class="hint">Alice and Bob share a public base <b>g</b> and prime modulus <b>p</b>. Each secretly picks a private number, they swap public mixtures, and both arrive at the <b>same</b> shared secret — while Eve, who sees everything on the wire, cannot.</p>
<div class="params">
  <label>g = <input id="g" type="number" min="2" max="20" value="5"></label>
  <label>p = <input id="p" type="number" min="3" max="9973" value="23"></label>
</div>
<div class="lanes">
  <div class="lane alice">
    <h3>Alice</h3>
    <label class="priv">private a = <input id="a" type="number" min="1" max="9972" value="6"></label>
    <div class="calc" id="calcA">A = g<sup>a</sup> mod p = ?</div>
    <div class="secret" id="secA">secret = B<sup>a</sup> mod p = ?</div>
  </div>
  <div class="lane eve">
    <h3>Eve (eavesdropper)</h3>
    <div class="wire" id="wireA">A = ?</div>
    <div class="wire" id="wireB">B = ?</div>
    <div class="evenote" id="eveNote">sees g, p, A, B — must solve the discrete log to learn the secret.</div>
  </div>
  <div class="lane bob">
    <h3>Bob</h3>
    <label class="priv">private b = <input id="b" type="number" min="1" max="9972" value="15"></label>
    <div class="calc" id="calcB">B = g<sup>b</sup> mod p = ?</div>
    <div class="secret" id="secB">secret = A<sup>b</sup> mod p = ?</div>
  </div>
</div>
<div class="status" id="status">Pick numbers, then run the exchange.</div>
<div class="btns">
  <button id="run" type="button">Run the exchange</button>
  <button id="crack" type="button" class="ghost">Eve: brute-force the secret</button>
</div>
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; }
.hint { font-size: .9rem; color: #444; margin: 0 0 .8rem; line-height: 1.45; }
.params { display: flex; gap: 1rem; margin: .3rem 0 .8rem; flex-wrap: wrap; }
label { font-size: .9rem; font-weight: 600; }
input { width: 64px; font: 600 14px ui-monospace, monospace; padding: .25rem .4rem;
        border: 1px solid #adb1b8; border-radius: 6px; }
.lanes { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: .6rem; }
.lane { border: 1px solid #cdd9e3; border-radius: 10px; padding: .6rem; background: #f4f8fb; }
.lane h3 { margin: 0 0 .5rem; font-size: 1rem; }
.alice h3 { color: #1d6fb8; }
.bob h3 { color: #0a7d33; }
.eve { background: #fbf0f0; border-color: #e3cdcd; }
.eve h3 { color: #c92f3c; }
.priv { display: block; margin-bottom: .5rem; }
.calc, .secret, .wire { font: 600 13px ui-monospace, monospace; margin: .35rem 0;
        background: #fff; border: 1px solid #dde6ee; border-radius: 6px; padding: .35rem .45rem; }
.secret { background: #e9f7ee; border-color: #b8e3c8; }
.secret.match { background: #d4f0de; }
.wire { background: #fff; border-color: #ecd6d6; }
.evenote { font-size: .78rem; color: #944; margin-top: .4rem; line-height: 1.35; }
.status { font-size: 1rem; font-weight: 700; margin: .7rem 0 .4rem; min-height: 1.4em; }
.status.ok { color: #0a7d33; }
.status.bad { color: #c92f3c; }
.btns { display: flex; gap: .5rem; flex-wrap: wrap; }
button { font: 600 14px system-ui, sans-serif; padding: .45rem .9rem; border: 1px solid #1d3557;
         background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #c92f3c; border-color: #c92f3c; }
@media (max-width: 560px) { .lanes { grid-template-columns: 1fr; } }
const fmt = (s, v) => s.replace(/%(\w+)%/g, (_, k) => String(v[k] ?? ''));
// Diffie-Hellman key exchange. Public: base g and prime modulus p.
// Alice's private a -> A = g^a mod p ; Bob's private b -> B = g^b mod p.
// Shared secret: Alice computes B^a mod p, Bob computes A^b mod p.
// Both equal g^(ab) mod p. Eve sees g, p, A, B but must solve the
// DISCRETE LOGARITHM (find a from A = g^a mod p) to recover the secret —
// easy to exponentiate, hard to invert.
function modpow(base, exp, mod) {
  base %= mod; let r = 1n;
  let b = BigInt(base), e = BigInt(exp), m = BigInt(mod);
  while (e > 0n) { if (e & 1n) r = (r * b) % m; b = (b * b) % m; e >>= 1n; }
  return Number(r);
}
const $ = id => document.getElementById(id);
function setStatus(t, cls){ const s = $('status'); s.textContent = t; s.className = 'status ' + cls; }

function run() {
  const g = +$('g').value, p = +$('p').value, a = +$('a').value, b = +$('b').value;
  const A = modpow(g, a, p);          // Alice's public value
  const B = modpow(g, b, p);          // Bob's public value
  const sAlice = modpow(B, a, p);     // Alice's computed secret = B^a mod p
  const sBob   = modpow(A, b, p);     // Bob's computed secret   = A^b mod p
  $('calcA').innerHTML = 'A = g<sup>a</sup> mod p = ' + A;
  $('calcB').innerHTML = 'B = g<sup>b</sup> mod p = ' + B;
  $('wireA').textContent = 'A = ' + A;
  $('wireB').textContent = 'B = ' + B;
  $('secA').innerHTML = 'secret = B<sup>a</sup> mod p = ' + sAlice;
  $('secB').innerHTML = 'secret = A<sup>b</sup> mod p = ' + sBob;
  const ok = sAlice === sBob;
  $('secA').classList.toggle('match', ok);
  $('secB').classList.toggle('match', ok);
  if (ok) setStatus(fmt('Both sides agree on the shared secret %sAlice% — Eve never saw it.', { sAlice: sAlice }), 'ok');
  else    setStatus('Secrets differ — check that p is prime and inputs are valid.', 'bad');
  console.log(fmt('A=%A% B=%B% Alice secret=%sAlice% Bob secret=%sBob%', { A: A, B: B, sAlice: sAlice, sBob: sBob }));
}

// Eve's only route: try every private exponent until g^x mod p matches A,
// then use it. This brute force is trivial for tiny p but explodes with size.
function crack() {
  const g = +$('g').value, p = +$('p').value;
  const A = modpow(g, +$('a').value, p);
  const b = +$('b').value, B = modpow(g, b, p);
  let steps = 0, found = -1;
  for (let x = 1; x < p; x++) { steps++; if (modpow(g, x, p) === A) { found = x; break; } }
  if (found >= 0) {
    const secret = modpow(B, found, p);
    setStatus(fmt('Eve cracked it in %steps% tries: a = %found%, secret = %secret%. With a 2048-bit p this loop would outlast the universe.', { steps: steps, found: found, secret: secret }), 'bad');
  } else setStatus('Eve found no exponent (bad parameters).', 'bad');
}
$('run').addEventListener('click', run);
$('crack').addEventListener('click', crack);
run();
Result
Console

Watch the asymmetry. Alice sends A = gᵃ mod p and Bob sends B = gᵇ mod p in the clear. Alice computes Bᵃ mod p, Bob computes Aᵇ mod p, and both land on the same value gᵃᵇ mod p — their shared secret. Eve sees g, p, A and B, but to find the secret she would have to recover a private exponent from gᵃ mod p. That is the discrete logarithm: easy to raise a number to a power, fiendishly hard to climb back down.

The Real Complexity

How safe is Diffie-Hellman, really? The whole scheme balances on a single asymmetry:

  • Exponentiation is easy. Computing gᵃ mod p for a 2048-bit prime takes a few thousand multiplications — milliseconds on a phone.
  • Inverting it is hard. Given g, p and gᵃ mod p, finding a is the discrete-logarithm problem. The best known classical algorithms run in sub-exponential time, which for a well-chosen prime means billions of years.
  • It is conjectured, not proven. Nobody has shown the discrete log is genuinely hard — a fast algorithm could exist tomorrow. Its presumed difficulty sits inside the same open landscape as P vs NP and the discrete logarithm itself.
  • Quantum changes everything. Peter Shor's 1994 algorithm solves the discrete logarithm in polynomial time on a large quantum computer. Such a machine does not yet exist at scale, but its mere possibility is why the world is migrating to post-quantum schemes.

That is the honest punchline: Diffie-Hellman is not secured by a proof, but by a problem we believe is hard. The exchange runs in plain sight precisely because undoing one-way arithmetic appears to be beyond any efficient algorithm we know — for now.

Where It Matters

"Agree on a key with someone you've never met" is the founding problem of secure communication, and Diffie-Hellman is the answer running quietly underneath almost everything online:

  • HTTPS / TLS: the padlock in your browser begins with a Diffie-Hellman exchange (today its elliptic-curve variant) to set up the session key.
  • Messaging apps: Signal, WhatsApp and others chain Diffie-Hellman exchanges to give forward secrecy — stealing today's key doesn't unlock yesterday's messages.
  • VPNs and SSH: every tunnel you open to a remote server negotiates its keys this way.
  • Hardness as a foundation: the same one-way-function idea underpins factoring-based RSA and the search for discrete logarithm hardness across cryptography.

Understand Diffie-Hellman and you've met the deal that makes the open internet trustworthy: build security not on secrecy of the channel, but on the difficulty of a single computation.

Conclusion

Diffie-Hellman turned a paradox into a protocol: two people, no prior meeting, a fully public conversation — and a secret only they share. The whole edifice rests on a beautiful imbalance, an operation easy to perform and, as far as anyone knows, hopeless to reverse.

So the next time a padlock appears in your address bar, remember the quiet handshake behind it. Its security is not certainty but conjecture — a bet that the discrete logarithm stays hard. That bet has held since 1976, and the entire trustworthy internet rides on it. The same hardness shows up in factoring and across computational complexity, where what we can't compute is exactly what keeps us safe.

Share this article

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

Comments

Loading comments...

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