Introduction

Almost every cipher you have ever used — from the lock on your messages to the padlock in your browser — is only hard to break. Its security rests on a bet: that no one has enough computing power, or a clever enough shortcut, to undo it. Break the bet and the secret falls.

The one-time pad is different. It is the only cipher whose unbreakability is a mathematical theorem, not a hope. No amount of computing power — not today's machines, not a future quantum computer, not a billion years of brute force — can ever recover the message. And the recipe is almost insultingly simple: take a key of truly random bits, exactly as long as your message, and combine the two bit by bit.

There is exactly one catch, and the same proof that makes the pad perfect tells you precisely what it is. Break that one rule and the magic evaporates instantly.

Try It

Type a message below. The demo picks a truly random key the same length as your message and XORs them together — that is the entire cipher. XOR the ciphertext with the same key and your message comes back exactly.

<p class="hint">The one-time pad XORs each bit of your message with a bit of a truly random key. Pick a key as long as the message and it is <b>provably</b> unbreakable. Shorten it or reuse it and the secrecy shatters.</p>
<label class="fld">Message <input id="msg" type="text" value="ATTACK" maxlength="8"></label>
<div class="row">
  <button id="rand" type="button">Fresh random key</button>
  <label class="chk"><input id="reuse" type="checkbox"> Reuse the same key on a 2nd message</label>
</div>
<div id="reuse2" class="hidden">
  <label class="fld">2nd message <input id="msg2" type="text" value="RETREAT" maxlength="8"></label>
</div>
<pre id="out" class="out"></pre>
<button id="break" type="button" class="ghost">What can an attacker learn?</button>
<div class="status" id="status"></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 .7rem; line-height: 1.45; }
.fld { display: block; font-size: .85rem; color: #1d3557; margin: .5rem 0; font-weight: 600; }
.fld input { display: block; margin-top: .25rem; font: 600 15px ui-monospace, monospace;
             padding: .4rem .6rem; border: 1px solid #cdd9e3; border-radius: 8px; width: 100%;
             max-width: 260px; text-transform: uppercase; }
.row { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; margin: .5rem 0; }
.chk { font-size: .85rem; color: #444; font-weight: 500; }
.hidden { display: none; }
.out { background: #0f1f2e; color: #d6e4f0; padding: .8rem; border-radius: 8px;
       font: 13px/1.6 ui-monospace, monospace; overflow-x: auto; white-space: pre; margin: .6rem 0; }
.out .k { color: #ffd166; }
.out .c { color: #ef8a8a; }
.out .p { color: #8ce0a8; }
.status { font-size: .92rem; font-weight: 600; margin: .5rem 0; min-height: 1.4em; line-height: 1.45; }
.status.ok { color: #0a7d33; }
.status.bad { color: #c92f3c; }
button { font: 600 14px system-ui, sans-serif; padding: .45rem .9rem; border: 1px solid #1d3557;
         background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; margin: .2rem .4rem .2rem 0; }
button.ghost { background: #fff; color: #1d3557; }
const fmt = (s, v) => s.replace(/%(\w+)%/g, (_, k) => String(v[k] ?? ''));
// One-time pad: ciphertext = message XOR key, byte by byte. With a TRULY RANDOM
// key as long as the message, used exactly once, Shannon (1949) proved this gives
// PERFECT SECRECY: the ciphertext reveals nothing about the message — every
// plaintext of that length is equally likely. Two failures break it:
//   (1) a key SHORTER than the message must repeat -> structure leaks;
//   (2) REUSING a key on two messages -> XOR of ciphertexts = XOR of plaintexts,
const norm = s => (s.toUpperCase().replace(/[^A-Z]/g,'') || 'A').slice(0,8);
let key = [];
function freshKey(n){ key = []; for(let i=0;i<n;i++) key.push(Math.floor(Math.random()*256)); }
const bytes = s => [...s].map(c => c.charCodeAt(0));
const xor = (a,b) => a.map((v,i) => v ^ b[i % b.length]);
const hex = arr => arr.map(v => v.toString(16).padStart(2,'0').toUpperCase()).join(' ');

function render(){
  const m = norm(document.getElementById('msg').value);
  const reuse = document.getElementById('reuse').checked;
  document.getElementById('reuse2').className = reuse ? '' : 'hidden';
  if(key.length < m.length) freshKey(m.length);
  const p = bytes(m);
  const k = key.slice(0, m.length);
  const c = xor(p, k);
  let html =
    fmt(`<span class="p">message  %m%</span>
plaintext   %hex%
<span class="k">key (XOR)   %hex2%</span>
<span class="c">ciphertext  %hex3%</span>
decrypt     %fromCharCode%`, { m: m.padEnd(8), hex: hex(p), hex2: hex(k), hex3: hex(c), fromCharCode: String.fromCharCode(...xor(c,k)) });
  if(reuse){
    const m2 = norm(document.getElementById('msg2').value);
    const p2 = bytes(m2);
    const n = Math.min(p2.length, key.length);
    const c2 = xor(p2.slice(0,n), key.slice(0,n));
    html += "\n\n" + fmt(`<span class="c">2nd ciphertext (same key) %hex%</span>`, { hex: hex(c2) });
  }
  document.getElementById('out').innerHTML = html;
  setStatus('','');
}
function setStatus(t,cls){ const s=document.getElementById('status'); s.innerHTML=t; s.className='status '+cls; }

function attack(){
  const reuse = document.getElementById('reuse').checked;
  if(!reuse){
    setStatus(`✓ Single use, random key as long as the message: the attacker sees only random bytes. Every possible plaintext of this length is equally consistent — nothing leaks. That is perfect secrecy.`,'ok');
    return;
  }
  // Reuse attack: c1 XOR c2 = p1 XOR p2 (the key cancels).
  const m1 = norm(document.getElementById('msg').value);
  const m2 = norm(document.getElementById('msg2').value);
  const n = Math.min(m1.length, m2.length, key.length);
  const p1 = bytes(m1).slice(0,n), p2 = bytes(m2).slice(0,n);
  const k = key.slice(0,n);
  const c1 = xor(p1,k), c2 = xor(p2,k);
  const cdiff = c1.map((v,i)=> v ^ c2[i]);
  const pdiff = p1.map((v,i)=> v ^ p2[i]);
  const leaked = cdiff.every((v,i)=> v === pdiff[i]);
  setStatus(fmt(`✗ Key reused! The attacker XORs the two ciphertexts and the key cancels out:
c1 ⊕ c2 = %hex%  =  p1 ⊕ p2 %v%
The random key is gone — only the messages remain, and they leak.`, { hex: hex(cdiff), v: leaked ? `(exactly!)` : '' }), 'bad');
}

['msg','msg2'].forEach(id => document.getElementById(id).addEventListener('input', render));
document.getElementById('reuse').addEventListener('change', render);
document.getElementById('rand').addEventListener('click', ()=>{ const m=norm(document.getElementById('msg').value); freshKey(Math.max(m.length, norm(document.getElementById('msg2').value).length)); render(); });
document.getElementById('break').addEventListener('click', attack);
freshKey(8);
render();
Result
Console

Now tick Reuse the same key on a 2nd message and press What can an attacker learn?. With a single use, the attacker sees nothing but random noise — every possible message is equally likely. But reuse the key once and the math turns on you: XOR the two ciphertexts and the random key cancels out, leaving the XOR of your two plaintexts in plain sight. That is why it is called a one-time pad.

The Real Guarantee

What does "unbreakable" really mean here? It is a precise, proven statement, not a marketing slogan.

  • The mechanism. Ciphertext = message XOR key, one random key bit per message bit. To decrypt, XOR with the same key again.
  • The theorem. In 1949 Claude Shannon proved the one-time pad achieves perfect secrecy: given only the ciphertext, every possible message of that length is exactly as likely as any other. Seeing the encrypted text teaches an attacker literally nothing about the original. This is a settled, proven result — not an open problem and not a mere computational guess.
  • Why it holds. For any ciphertext you intercept and any message you guess, there is exactly one key that would produce it. Since the key is uniformly random, all guesses stay equally plausible. There is nothing to attack.
  • The price. The key must be truly random, kept secret, as long as the message, and used only once. A key shorter than the message must repeat, and reuse — as the demo shows — lets the key cancel out and the messages leak. Unlike Diffie–Hellman, whose safety rests on a hard computational problem, the pad's safety needs no such assumption — but it demands as much secret key material as data.

That trade is the whole story: the only cipher we can prove unbreakable buys its perfection by needing a secret as big as the secret it protects.

Where It Matters

Because the key has to be as large as the message and delivered in advance, the one-time pad is impractical for everyday traffic — but where the stakes are absolute, it is exactly the right tool:

  • Diplomatic and military links. The Cold War Moscow–Washington hotline used one-time pads, as did countless embassy channels — secrets that had to stay sealed for decades.
  • Espionage. Agents have long received pads as tiny printed booklets; the shortwave "numbers stations" still heard today broadcast one-time-pad messages to the field.
  • The benchmark for "perfect". Perfect secrecy is the gold standard every other cipher is measured against. Real systems settle for computational secrecy precisely because the pad's key cost is too high.
  • Quantum key distribution. Protocols like BB84 exist largely to solve the pad's one weakness — securely sharing fresh random key — so a future internet might one day approach pad-grade secrecy.

The one-time pad is rarely the practical choice, but it defines the very ceiling of what secrecy can mean.

Conclusion

The one-time pad sits alone in cryptography: not merely hard to break but provably impossible to break, a guarantee Shannon nailed down in 1949. Every other cipher you trust is, deep down, a bet that some problem stays hard. The pad makes no bet at all.

The catch is honest and total. Perfection costs a truly random key as big as your message, shared in advance and never reused — break that single rule and the whole edifice falls in a single XOR. The next time you reach for "unbreakable," remember the one-time pad: certainty is real, but it is never free.

Share this article

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

Comments

Loading comments...

https://www.kipuhub.com/en/article/one-time-pad/Content licensed under CC BY-NC 4.0.