Introduction

Imagine you want to send an encrypted message to a colleague whose email address you already know. With classical public-key cryptography you have a problem: you first have to find their public key, verify it is really theirs through a certificate authority, and hope they have set one up. That bureaucratic chain stops many people from encrypting anything at all.

Identity-Based Encryption (IBE) cuts through that tangle. In IBE, any string — an email address, a phone number, even a date — acts directly as a public key. The sender encrypts to alice@example.com. When Alice later wants to read the message, she contacts a Private Key Generator (PKG), a trusted authority that uses a master secret to derive her personal decryption key.

The concept was sketched by Adi Shamir in 1984, but it took seventeen years until Dan Boneh and Matthew Franklin (2001) made it practical by exploiting the surprising algebraic structure of bilinear pairings on elliptic curves — the same building blocks that now power much of modern pairing-based cryptography.

Try It

The demo below simulates the four core IBE operations in a simplified, illustrative model (real pairings use 256-bit fields; here we use tiny numbers so you can follow along).

<!-- Identity-Based Encryption — simplified educational demo -->
<div class="panel">
  <h3>Step 1 — PKG Setup</h3>
  <div class="field-row">
    <label>Master secret <em>(s)</em></label>
    <input id="masterSecret" type="number" min="2" max="20" value="7" />
    <button id="btnSetup" type="button">Run Setup</button>
  </div>
  <div id="setupOut" class="output hidden"></div>
</div>
<div class="panel">
  <h3>Step 2 — Key Extraction</h3>
  <div class="field-row">
    <label>Identity (recipient)</label>
    <input id="identity" type="text" value="alice@example.com" placeholder="e.g. alice@example.com" />
    <button id="btnExtract" type="button">Extract Key</button>
  </div>
  <div id="extractOut" class="output hidden"></div>
</div>
<div class="panel">
  <h3>Step 3 — Encrypt to identity</h3>
  <div class="field-row">
    <label>Message (1–22)</label>
    <input id="message" type="number" min="1" max="22" value="10" placeholder="1 – 22" />
    <button id="btnEncrypt" type="button">Encrypt</button>
  </div>
  <div id="encryptOut" class="output hidden"></div>
</div>
<div class="panel">
  <h3>Step 4 — Decrypt with private key</h3>
  <button id="btnDecrypt" type="button">Decrypt</button>
  <div id="decryptOut" class="output hidden"></div>
</div>
/* IBE demo styles */
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; font-size: .9rem; }
h3 { margin: 0 0 .45rem; font-size: .93rem; color: #1d3557; }
.panel { background: #f4f7fa; border: 1px solid #cdd9e3; border-radius: 10px;
         padding: .7rem .9rem; margin-bottom: .6rem; }
.field-row { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; }
label { font-weight: 600; min-width: 7.5rem; }
input[type=text], input[type=number] { flex: 1; min-width: 0; padding: .32rem .5rem;
  border: 1px solid #adb1b8; border-radius: 6px; font-size: .88rem; }
button { font: 600 .84rem system-ui, sans-serif; padding: .35rem .78rem;
         border: 1px solid #1d3557; background: #1d3557; color: #fff;
         border-radius: 7px; cursor: pointer; white-space: nowrap; }
.output { margin-top: .5rem; background: #fff; border: 1px solid #cdd9e3;
          border-radius: 7px; padding: .45rem .7rem; font-size: .82rem;
          line-height: 1.65; font-family: ui-monospace, monospace; }
.output.ok { border-left: 3px solid #0a7d33; }
.output.bad { border-left: 3px solid #c92f3c; color: #c92f3c; }
.hidden { display: none; }
.kv { display: grid; grid-template-columns: auto 1fr; gap: .12rem .55rem; }
.kv b { color: #1d3557; white-space: nowrap; }
const fmt = (s, v) => s.replace(/%(\w+)%/g, (_, k) => String(v[k] ?? ''));
// IBE toy demo: Setup -> Extract -> Encrypt -> Decrypt
// Uses a tiny prime p=23 and discrete-log pairing stand-in so the math stays visible.

// Tiny prime — real IBE uses 256-bit fields
const P = 23;
// Generator of the multiplicative group mod p
const G = 5;

// Hash any identity string to an integer in [1, p-1]
function hashToInt(str) {
  let h = 0;
  for (let i = 0; i < str.length; i++) h = (h * 31 + str.charCodeAt(i)) % (P - 1) + 1;
  return h;
}

// Fast modular exponentiation
function modpow(base, exp, mod) {
  let result = 1; base = base % mod;
  while (exp > 0) {
    if (exp % 2 === 1) result = result * base % mod;
    exp = Math.floor(exp / 2); base = base * base % mod;
  }
  return result;
}

// Toy bilinear pairing: e(a, b) = g^(a*b) mod p
// In real IBE this is the Weil or Tate pairing on an elliptic curve
function pairing(a, b) {
  return modpow(G, a * b % (P - 1), P);
}

// Modular multiplicative inverse by brute force (fine for p=23)
function modinv(a, mod) {
  for (let i = 1; i < mod; i++) if (a * i % mod === 1) return i;
  return 1;
}

// Shared state across the four IBE steps
let s = 0, hID = 0, dIDexp = 0, storedR = 0, storedV = 0;

function show(id, html, cls) {
  const el = document.getElementById(id);
  el.innerHTML = html;
  el.className = 'output ' + (cls || '');
}

// Step 1 — PKG Setup: choose master secret s, publish g^s
document.getElementById('btnSetup').addEventListener('click', function () {
  const v = parseInt(document.getElementById('masterSecret').value, 10);
  if (isNaN(v) || v < 2 || v > 20) { show('setupOut', 'Master secret must be between 2 and 20.', 'bad'); return; }
  s = v;
  hID = 0; dIDexp = 0; storedR = 0; storedV = 0;
  ['extractOut','encryptOut','decryptOut'].forEach(function(id){ document.getElementById(id).className='output hidden'; });
  const Ppub = modpow(G, s, P);
  show('setupOut',
    fmt('<div class="kv"><b>p</b><span>%P% (toy field size)</span><b>g</b><span>%G% (group generator)</span><b>s</b><span>%s% <em>kept secret by PKG</em></span><b>P<sub>pub</sub> = g<sup>s</sup></b><span>%Ppub%</span></div><br><em>Public parameters (p, g, P_pub) are broadcast to everyone.</em>', { P: P, G: G, s: s, Ppub: Ppub }), 'ok');
});

// Step 2 — Key Extraction: PKG derives private key for identity
document.getElementById('btnExtract').addEventListener('click', function () {
  if (!s) { show('extractOut', 'Run PKG Setup first.', 'bad'); return; }
  const id = document.getElementById('identity').value.trim();
  if (!id) { show('extractOut', 'Please enter an identity string.', 'bad'); return; }
  hID = hashToInt(id);
  // Private key exponent: dID_exp = s * H(id) mod (p-1)
  dIDexp = s * hID % (P - 1);
  const dIDpub = modpow(G, dIDexp, P);
  storedR = 0; storedV = 0;
  document.getElementById('encryptOut').className = 'output hidden';
  document.getElementById('decryptOut').className = 'output hidden';
  show('extractOut',
    fmt('<div class="kv"><b>Identity</b><span>%id%</span><b>H(id)</b><span>%hID%</span><b>Key exponent</b><span>s · H(id) mod (p-1) = %dIDexp%</span><b>Private key d_ID</b><span>g<sup>%dIDexp%</sup> mod p = %dIDpub%</span></div><br><em>The PKG issues d_ID only to the authenticated identity holder.</em>', { id: id, hID: hID, dIDexp: dIDexp, dIDpub: dIDpub }), 'ok');
});

// Step 3 — Encrypt using identity as public key
document.getElementById('btnEncrypt').addEventListener('click', function () {
  if (!dIDexp) { show('encryptOut', 'Run Key Extraction first.', 'bad'); return; }
  const m = parseInt(document.getElementById('message').value, 10);
  if (isNaN(m) || m < 1 || m > P - 1) { show('encryptOut', fmt('Message must be a number between 1 and %v%', { v: P - 1 }), 'bad'); return; }
  // Pick a fresh ephemeral r for this encryption
  storedR = 2 + Math.floor(Math.random() * (P - 3));
  // Encrypt mask = pairing(H(id)*s, r) = g^(H(id)*s*r); sender uses s as 'Ppub' in toy
  const maskExp = hID * s % (P - 1) * storedR % (P - 1);
  const mask = modpow(G, maskExp, P);
  const U = modpow(G, storedR, P);
  storedV = m * mask % P;
  show('encryptOut',
    fmt('<div class="kv"><b>m</b><span>%m%</span><b>r</b><span>%storedR% <em>chosen fresh each time</em></span><b>Pairing mask</b><span>g<sup>H(id)&#xb7;s&#xb7;r</sup> mod p = %mask%</span><b>U = g<sup>r</sup></b><span>%U%</span><b>V = m&#xb7;mask</b><span>%storedV%</span></div><br><em>Ciphertext (U, V) is sent to the recipient.</em>', { m: m, storedR: storedR, mask: mask, U: U, storedV: storedV }), 'ok');
});

// Step 4 — Decrypt using private key
document.getElementById('btnDecrypt').addEventListener('click', function () {
  if (!storedR || !storedV) { show('decryptOut', 'Encrypt a message first.', 'bad'); return; }
  // Decryption: recover mask = pairing(dID_exp, r) = g^(s*H(id)*r), then m = V / mask
  // This equals the encryption mask because s*H(id)*r == H(id)*s*r
  const maskDec = pairing(dIDexp, storedR);
  const recovered = storedV * modinv(maskDec, P) % P;
  show('decryptOut',
    fmt('<div class="kv"><b>V received</b><span>%storedV%</span><b>Decryption mask</b><span>g<sup>d<sub>ID</sub>&#xb7;r</sup> mod p = %maskDec%</span><b>Recovered m</b><span>%recovered%</span></div><br><strong>Decrypted: %recovered% ✓</strong>', { storedV: storedV, maskDec: maskDec, recovered: recovered }), 'ok');
});
Result
Console

Notice what makes IBE different: the sender only needs a public string (the recipient's identity) and the public parameters broadcast by the PKG. The PKG's master secret is never seen by either party. Decryption only works for the legitimate key holder — anyone else who intercepts the ciphertext cannot recover the message without the PKG-issued private key.

The Real Complexity

IBE security does not rest on NP-completeness — it rests on a hardness assumption about a specific algebraic structure.

  • Bilinear pairing. A pairing e:G1×G1→G2e: G_1 \times G_1 \to G_2 is a map between two groups that satisfies e(aP,bQ)=e(P,Q)abe(aP, bQ) = e(P, Q)^{ab} for any points P,QP, Q and scalars a,ba, b. This "bilinearity" is what lets the PKG bind an identity string to a group element that the sender can use.
  • The Bilinear Diffie-Hellman (BDH) problem. Given PP, aPaP, bPbP, cPcP on an elliptic curve, compute e(P,P)abce(P, P)^{abc}. No efficient algorithm is known. Boneh and Franklin proved in the random oracle model that any attacker who breaks their IBE scheme can be converted into a solver for BDH — so if BDH is hard, IBE is secure.
  • Why not just use RSA or ECDH? Classical schemes need a public-key infrastructure (PKI) to bind identity to key. IBE folds identity into the key derivation itself. The price is a trusted PKG; the gain is zero infrastructure for senders.
  • Known after the fact. A subtlety: the PKG can derive anyone's private key, so IBE has key escrow built in. Variants like Hierarchical IBE (HIBE) and Attribute-Based Encryption (ABE) extend or mitigate this.

The Weil and Tate pairings on supersingular elliptic curves are the concrete instantiation Boneh and Franklin used. Compare this with discrete logarithm, whose hardness underpins classical Diffie-Hellman — IBE simply lives one algebraic layer higher.

Where It Matters

IBE solves a real bootstrapping problem and has spun off a rich family of constructions:

  • Encrypted email without PKI: a company can run its own PKG and let any employee encrypt to name@company.com without pre-distributing certificates.
  • Time-based forward security: encrypt today to alice@example.com||2026-07-01; Alice can only decrypt on that date, when the PKG releases the key for that identity string.
  • Attribute-Based Encryption (ABE): a generalization where the "identity" is a set of attributes (role=doctor AND clearance=level3) and decryption only works if the recipient's credentials satisfy the policy. ABE powers fine-grained access control in cloud storage.
  • Certificate-less cryptography: modern standards like Lattices / SVP-based IBE schemes aim to keep the zero-infrastructure benefit while resisting quantum attacks.
  • Broadcast encryption: IBE ideas underlie systems that encrypt once to a large group defined by a predicate rather than a list.

The Boneh-Franklin paper is one of the most cited in applied cryptography — not because IBE replaced PKI everywhere, but because pairings unlocked a completely new design space for cryptographic protocols.

Conclusion

Identity-Based Encryption achieved something elegant: it turned the question "how do I find your key?" into "I already have it — it's your name." Boneh and Franklin showed in 2001 that bilinear pairings on elliptic curves make this dream mathematically rigorous, with security provably as hard as the Bilinear Diffie-Hellman problem.

The catch — a trusted PKG that can derive any private key — keeps IBE out of fully decentralized systems. But the ideas it unlocked, from Attribute-Based Encryption to pairing-based signatures, have shaped a generation of cryptographic protocols. Next time you see a zero-knowledge proof or a threshold signature scheme, there is a good chance a bilinear pairing is quietly doing the heavy lifting.

For a related hardness story, see discrete logarithm — the classical problem IBE's assumptions descend from.

Share this article

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

Comments

Loading comments...

https://www.kipuhub.com/en/article/identity-based-encryption/Content licensed under CC BY-NC 4.0.