Loading...
Loading...
The first quantum cryptographic protocol
BB84, proposed by Bennett and Brassard in 1984, is the first quantum key distribution protocol. It exploits the no-cloning theorem and the fact that measuring a quantum state disturbs it, enabling two parties to detect eavesdropping while establishing a shared secret key.
BB84 enables two parties, traditionally named Alice and Bob, to generate a shared random secret key over a public quantum channel. Alice begins by generating two random bit strings: one representing the raw key bits she wishes to transmit, and another representing the bases in which she will encode them.
For each bit, Alice encodes it into the polarization state of a single photon. She uses the rectilinear basis (Z basis) for basis bit 0, encoding 0 as |0⟩ and 1 as |1⟩. She uses the diagonal basis (X basis) for basis bit 1, encoding 0 as |+⟩ = (|0⟩ + |1⟩)/√2 and 1 as |-⟩ = (|0⟩ - |1⟩)/√2. She then sends the photons to Bob.
Bob does not know which basis Alice used for each photon, so he guesses by generating his own random basis string. He measures each incoming photon in his chosen basis. After all photons are transmitted and measured, Alice and Bob publicly compare their basis strings over a classical authenticated channel. They keep only those bits for which their bases matched, discarding the rest. The remaining bits form their shared secret key.
Rectilinear basis states
Diagonal basis states
Eavesdropper error rate
The security of BB84 rests on fundamental principles of quantum mechanics rather than computational assumptions. The no-cloning theorem states that it is impossible to create an identical copy of an arbitrary unknown quantum state. This prevents an eavesdropper, Eve, from simply making a copy of each photon to store for later analysis while forwarding the original to Bob.
If Eve attempts to measure the photons in a randomly chosen basis, she will guess the correct basis only 50% of the time. When she guesses incorrectly and resends the photon based on her wrong measurement outcome, she introduces a 25% error rate in Bob's results for those bits. By publicly comparing a randomly chosen subset of their sifted key, Alice and Bob can estimate the quantum bit error rate (QBER). If the QBER exceeds a threshold—typically around 11% for BB84 with one-way classical post-processing—they abort the protocol.
Even when no eavesdropper is present, real quantum channels suffer from noise and loss. The distinction between innocent noise and malicious eavesdropping is handled by assuming all noise is due to Eve, then applying privacy amplification. This classical post-processing step compresses the partially secure raw key into a shorter, information-theoretically secure final key about which Eve has negligible knowledge.
QBER definition
Secure key rate
BB84 states
Runnable implementations you can copy and experiment with.
This Qiskit example simulates the BB84 protocol between Alice and Bob on a noise-free simulator. Random bits and bases are generated, photons are encoded and measured, and the sifted key is printed.
from qiskit import QuantumCircuit, transpile
from qiskit_aer import AerSimulator
import numpy as np
n = 16
alice_bits = np.random.randint(0, 2, size=n)
alice_bases = np.random.randint(0, 2, size=n)
bob_bases = np.random.randint(0, 2, size=n)
simulator = AerSimulator()
key = []
for i in range(n):
qc = QuantumCircuit(1, 1)
if alice_bits[i] == 1:
qc.x(0)
if alice_bases[i] == 1:
qc.h(0)
if bob_bases[i] == 1:
qc.h(0)
qc.measure(0, 0)
job = simulator.run(transpile(qc, simulator), shots=1)
result = job.result().get_counts()
measured_bit = int(list(result.keys())[0])
if alice_bases[i] == bob_bases[i]:
key.append(measured_bit)
print("Alice bits: ", alice_bits.tolist())
print("Alice bases: ", alice_bases.tolist())
print("Bob bases: ", bob_bases.tolist())
print("Shared key: ", key)
print("Key length: ", len(key))This PennyLane example implements BB84 as a QNode. Each photon is prepared according to Alice's bit and basis, then Bob measures in his randomly chosen basis. Matching bases yield correlated key bits.
import pennylane as qml
import pennylane.numpy as np
dev = qml.device("default.qubit", wires=1, shots=1)
@qml.qnode(dev)
def bb84_circuit(bit, alice_basis, bob_basis):
if bit == 1:
qml.PauliX(wires=0)
if alice_basis == 1:
qml.Hadamard(wires=0)
if bob_basis == 1:
qml.Hadamard(wires=0)
return qml.sample(qml.PauliZ(0))
n = 16
alice_bits = np.random.randint(0, 2, size=n)
alice_bases = np.random.randint(0, 2, size=n)
bob_bases = np.random.randint(0, 2, size=n)
key = []
for i in range(n):
sample = bb84_circuit(alice_bits[i], alice_bases[i], bob_bases[i])
if alice_bases[i] == bob_bases[i]:
key.append(int(sample))
print("Shared key:", key)
print("Key length:", len(key))