Week 9 | where Shor's gates go, how the same idea breaks Diffie–Hellman and elliptic curves, and why it stops at lattices | reading: de Wolf Ch. 6; Nielsen–Chuang §5.4
Lecture 15 treated each controlled multiplication as a black box. This lecture opens the box, counts what is inside, and then turns the algorithm on the other two public-key problems in use today: discrete logarithms in finite fields (Diffie–Hellman, DSA) and on elliptic curves (ECDH, ECDSA, Bitcoin). The last section shows that Simon's algorithm, order finding and discrete logs are one algorithm, the hidden subgroup algorithm, and explains why the same idea has not broken lattice-based cryptography. By the end you should be able to describe how controlled modular multiplication is built from adders and why it costs \(O(n^2)\) gates, run Shor's discrete-log algorithm on a small example, explain why elliptic-curve keys are an easier quantum target than RSA keys of comparable classical strength, and state the hidden subgroup problem with its known successes and failures.
For an \(n\)-bit modulus \(N\), order finding uses \(m\approx2n\) control qubits and two kinds of operations:
For \(j=30\), the constant \(c_{30}=a^{2^{30}}\bmod N\) is obtained .
List the constants \(c_j=2^{2^j}\bmod35\) for \(j=0,\dots,10\).
Square repeatedly mod 35: \(2,\ 4,\ 16,\ 256\equiv11,\ 121\equiv16,\ 11,\ 16,\dots\). So the list is \(2,4,16,11,16,11,16,11,16,11,16\). Compare Lecture 15's \(N=15\), where every constant from \(j=2\) on was 1 and could be deleted: here all eleven multiplications are genuine. The classical precomputation costs eleven squarings mod 35, nothing compared with the quantum work.
Every multiplication is a full \(n\)-bit modular multiplication, and there are about \(2n\) of them. Section 2 shows that each costs \(O(n^2)\) gates with schoolbook arithmetic, so modular exponentiation costs \(O(n^3)\), while the QFT costs at most \(O(n^2)\). For \(n=2048\) the ratio is roughly a factor of \(n\), about a thousand: the arithmetic is the algorithm, and every modern resource estimate is mostly a careful accounting of adders.
With schoolbook arithmetic, by roughly what factor does the gate count of order finding grow when the modulus goes from 1024 to 2048 bits?
Adders. Lecture 7 showed that any classical circuit can be made reversible with Toffoli gates. For addition there are very economical constructions. The ripple-carry adder of Cuccaro, Draper, Kutin and Moulton (2004) maps \(|a\rangle|b\rangle\mapsto|a\rangle|a+b\rangle\) for \(n\)-bit \(a,b\) using one ancilla, \(2n\) Toffolis and about \(4n\) CNOTs. It is built from two three-qubit blocks: MAJ, which computes the carry in place, and UMA, which uncomputes it and writes the sum bit (the code in Section 6 builds it and checks all inputs). Its cost is linear in \(n\). An alternative, Draper's QFT adder (2000), adds by rotating phases in the Fourier basis and uses no Toffolis at all, but \(O(n^2)\) controlled rotations.
Modular addition. To compute \(a+b\bmod N\) for \(a,b\lt N\): add, subtract \(N\), use the sign bit to decide whether to add \(N\) back, and then clean up the sign bit by comparing the result with \(a\). It costs a handful of adders and one extra ancilla.
Multiplication by a constant. To compute \(cy\bmod N\) for a classically known \(c\), write \(y=\sum_iy_i2^i\). Then
$$cy\equiv\sum_{i=0}^{n-1}y_i\,\big(c\,2^i\bmod N\big)\pmod N ,$$so \(|y\rangle|0\rangle\mapsto|y\rangle|cy\bmod N\rangle\) is a sequence of \(n\) modular additions of the precomputed constants \(c2^i\bmod N\), the \(i\)-th one controlled by the bit \(y_i\) (and all of them by the phase-estimation control qubit). That is \(n\) modular additions of \(n\)-bit numbers, hence \(O(n^2)\) gates. HW8 asks you to count the Toffolis to leading order.
One problem remains. Phase estimation needs \(U_c|y\rangle=|cy\rangle\) in place, but the construction above leaves \(|y\rangle\) behind. Reversibility forbids simply erasing it; we need to uncompute it, and the classical inverse of \(c\) does that.
Let \(c\in\mathbb Z_N^*\) with inverse \(c^{-1}\bmod N\). The three steps
$$|y\rangle|0\rangle\ \xrightarrow{\ +cy\ }\ |y\rangle|cy\rangle\ \xrightarrow{\ \text{SWAP}\ }\ |cy\rangle|y\rangle\ \xrightarrow{\ -c^{-1}\cdot(\text{first})\ }\ |cy\rangle|0\rangle$$(all arithmetic mod \(N\)) implement \(U_c\) on the first register and return the ancilla register to \(|0\rangle\). Each arithmetic step is a multiply-accumulate by a constant, so the in-place multiplication costs about twice an out-of-place one.
The first step adds \(cy\) to the zero register. After the swap, the third step subtracts \(c^{-1}\cdot(cy)\equiv y\) from the second register, which holds \(y\), leaving 0. Each step is reversible (its inverse adds instead of subtracting), so the composite is a unitary that acts as \(|y\rangle|0\rangle\mapsto|cy\rangle|0\rangle\). If \(\gcd(c,N)\gt1\) there is no \(c^{-1}\), and indeed \(y\mapsto cy\) is not a bijection (Lecture 15, exercise 4).
To multiply in place by \(c=5\) modulo \(N=23\), step 3 of Proposition 16.1 needs \(c^{-1}\bmod23\). What is it?
With schoolbook arithmetic, a controlled in-place modular multiplication of \(n\)-bit numbers costs \(O(n^2)\) gates, and order finding with \(m=O(n)\) control qubits costs \(O(n^3)\) gates and \(O(n)\) qubits. With the tricks below, \(2n+3\) logical qubits suffice (Beauregard, 2003); later constructions trade qubits and gates in both directions.
Proof sketch. \(O(n)\) modular additions of cost \(O(n)\) each per multiplication, and \(O(n)\) multiplications. The qubits are two \(n\)-qubit registers plus a few ancillas, and a single control qubit reused \(m\) times, as explained next.
In the inverse QFT, each control qubit only affects the later ones through controlled rotations, and a controlled gate followed by measurement of its control can be replaced by measuring first and applying the gate classically controlled (the deferred-measurement principle of Lecture 8, run backwards). So one can process the control qubits one at a time: prepare \(|+\rangle\), apply the controlled \(U^{2^j}\), rotate by an angle determined by the bits already measured, apply \(H\), measure, reset and reuse. This semiclassical QFT (Griffiths and Niu, 1996) replaces \(m\) control qubits by one, and the inverse QFT by \(m\) single-qubit rotations. It needs mid-circuit measurement and fast feed-forward, exactly the dynamic circuits of Lab 2.
The semiclassical QFT replaces the \(m\) control qubits by one. Which statement about it is correct?
Asymptotically faster multiplication (Karatsuba, Schönhage–Strassen) lowers the exponent below 3, but for 2048-bit numbers the constants matter more than the exponent. Practical estimates instead use windowing (look up several bits of the exponent at a time), approximate arithmetic, and careful layout on the error-correcting code; Lecture 17 reads one of them.
Let \(G\) be a cyclic group of order \(r\) generated by \(g\), written multiplicatively. Given \(h\in G\), the discrete logarithm of \(h\) is the unique \(x\in\{0,\dots,r-1\}\) with \(g^x=h\). The discrete logarithm problem (DLP) is to find \(x\) from \(g\) and \(h\).
The number 2 generates \(\mathbb Z_{13}^*\) (order \(r=12\)). Find the discrete logarithm of \(h=11\) to the base 2.
In Diffie–Hellman key exchange, Alice sends \(g^\alpha\), Bob sends \(g^\beta\), and both compute \(g^{\alpha\beta}\); an eavesdropper sees \(g^\alpha\) and \(g^\beta\). Anyone who solves the DLP recovers \(\alpha\) and the shared key. DSA, ECDSA, EdDSA, ECDH and X25519 all rest on the DLP, in the multiplicative group \(\mathbb Z_p^*\) (finite-field groups) or in an elliptic-curve group. Together with RSA, that is essentially all public-key cryptography deployed before 2024.
Classically, the best algorithms for \(\mathbb Z_p^*\) are subexponential (number field sieve variants, much like factoring), and for well-chosen elliptic curves only generic algorithms work, which take about \(\sqrt r\) group operations. That is why a 256-bit curve gives security comparable to 3072-bit RSA.
Shor's idea. Consider the function of two exponents
$$f(a,b)=g^a\,h^{-b}=g^{\,a-xb},\qquad a,b\in\mathbb Z_r .$$It takes the same value at \((a,b)\) and \((a',b')\) exactly when \(a-xb\equiv a'-xb'\pmod r\), that is, when \((a-a',\,b-b')\) lies in
$$H=\{(a,b)\in\mathbb Z_r\times\mathbb Z_r:\ a\equiv xb\pmod r\}=\{(xb\bmod r,\ b):\ b\in\mathbb Z_r\}.$$So \(f\) is periodic, not along a line of integers but along the hidden "direction" \((x,1)\), and the direction is the secret. Fourier sampling finds it.
Prepare \(\frac1r\sum_{a,b\in\mathbb Z_r}|a\rangle|b\rangle|f(a,b)\rangle\) (two controlled modular exponentiations), apply the Fourier transform over \(\mathbb Z_r\) to each of the first two registers, and measure them. The outcome \((c,d)\) is uniformly distributed over the \(r\) pairs with
$$d\equiv-xc\pmod r .$$Whenever \(c\) is invertible mod \(r\), \(x\equiv-d\,c^{-1}\pmod r\).
Measuring (or ignoring) the third register leaves a uniform superposition over a coset \((a_0,b_0)+H\), whose elements are \((a_0+xb,\ b_0+b)\) for \(b\in\mathbb Z_r\). With \(\omega=e^{2\pi i/r}\), the Fourier amplitude of \((c,d)\) is proportional to
$$\sum_{b\in\mathbb Z_r}\omega^{(a_0+xb)c+(b_0+b)d}=\omega^{a_0c+b_0d}\sum_{b}\omega^{\,b(xc+d)} ,$$which by Proposition 2.2 is \(r\,\omega^{a_0c+b_0d}\) if \(xc+d\equiv0\) and 0 otherwise. The \(r\) pairs \((c,-xc)\) therefore share the probability equally, whatever the coset. If \(\gcd(c,r)=1\), solve \(xc\equiv-d\).
Run Shor's discrete-log algorithm in the group of the last check (\(r=12\)) for an unknown \(x\). One run returns \((c,d)=(5,1)\). Use Theorem 16.3 to recover \(x\).
Let \(p=11\), \(g=2\) and \(h=9\). Find \(x\) classically, then describe the output of Shor's algorithm.
The powers of 2 mod 11 are \(1,2,4,8,5,10,9,7,3,6\) for exponents \(0,\dots,9\), so 2 generates \(\mathbb Z_{11}^*\) (order \(r=10\)) and \(2^6=64\equiv9\): \(x=6\). Theorem 16.3 predicts ten equally likely outcomes with \(d\equiv-6c\equiv4c\pmod{10}\):
$$(0,0),\ (1,4),\ (2,8),\ (3,2),\ (4,6),\ (5,0),\ (6,4),\ (7,8),\ (8,2),\ (9,6).$$The four with \(c\in\{1,3,7,9\}\) reveal \(x\) at once. For \((3,2)\): \(3^{-1}\equiv7\pmod{10}\), so \(x\equiv-2\cdot7=-14\equiv6\). The others carry partial information: \((5,0)\) says \(5x\equiv0\), so \(x\) is even.
Two practical remarks. First, the group order \(r\) must be known; for \(\mathbb Z_p^*\) it is \(p-1\), and for an elliptic-curve group it is public. If it were not, order finding would supply it. Second, real implementations use registers of \(m\approx\log_2r\) qubits with the QFT over \(\mathbb Z_{2^m}\) instead of \(\mathbb Z_r\), which gives approximately the same peaks, just as in Lecture 15.
An elliptic curve over the field \(\mathbb F_q\) (\(q\) a prime greater than 3) is the set of solutions of \(y^2=x^3+Ax+B\), together with a "point at infinity" \(\mathcal O\). The points form an abelian group: to add \(P\) and \(Q\), draw the line through them (the tangent if \(P=Q\)), find its third intersection with the curve, and reflect it in the \(x\)-axis. In coordinates, with \(\lambda\) the slope of that line,
$$\lambda=\frac{y_Q-y_P}{x_Q-x_P}\ \ (P\neq Q),\qquad \lambda=\frac{3x_P^2+A}{2y_P}\ \ (P=Q),$$ $$x_{P+Q}=\lambda^2-x_P-x_Q,\qquad y_{P+Q}=\lambda(x_P-x_{P+Q})-y_P ,$$all mod \(q\). The elliptic-curve discrete logarithm problem (ECDLP) is: given points \(P\) and \(Q=kP=P+\dots+P\), find \(k\).
On \(y^2=x^3+2x+2\) over \(\mathbb F_{17}\), let \(P=(5,1)\). Compute \(2P\) and \(3P\).
Doubling: \(\lambda=(3\cdot25+2)/(2\cdot1)=77/2\). Mod 17, \(77\equiv9\) and \(2^{-1}\equiv9\), so \(\lambda\equiv81\equiv13\). Then \(x=13^2-5-5=159\equiv6\) and \(y=13(5-6)-1=-14\equiv3\): \(2P=(6,3)\). Adding \(P\): \(\lambda=(1-3)/(5-6)=2\), \(x=4-6-5=-7\equiv10\), \(y=2(6-10)-3=-11\equiv6\): \(3P=(10,6)\). Continuing (verify_L16.py), \(P\) has order 19, which is the whole group: the curve has 18 affine points plus \(\mathcal O\). For instance \(13P=(16,4)\), so the discrete log of \((16,4)\) is 13.
Shor's algorithm applies unchanged: the function \(f(a,b)=aP-bQ\) has the hidden subgroup \(\{(kb,b)\}\), and Theorem 16.3 holds word for word with additive notation. What changes is the arithmetic. Each group operation needs a modular inversion (the division in \(\lambda\)), which is much more expensive than a multiplication when done reversibly. On the other hand, the numbers are much shorter: 256 bits instead of 2048 or 3072.
At equal classical security, elliptic-curve keys are far shorter than RSA keys, and Shor's cost depends on the key length, not on the classical difficulty. So the quantum attack on a 256-bit curve needs fewer logical qubits than the attack on RSA-2048, and in the most recent estimates also far fewer gates. The 2026 preprint above went further than earlier work in one respect worth noticing: "in the interest of responsible disclosure", its authors did not publish their circuits but released a zero-knowledge proof that circuits with the stated costs exist. Since Bitcoin and Ethereum signatures, TLS key exchange (X25519, P-256) and most code signing use elliptic curves, this is where a cryptographically relevant quantum computer would bite first.
P-256 and RSA-3072 are about equally hard to break classically, but the quantum attack on P-256 needs fewer logical qubits, because Shor's cost grows with .
Simon's algorithm, order finding and discrete logs share one structure: a function that is constant on the cosets of a hidden subgroup and distinct on different cosets.
Let \(G\) be a group and \(f:G\to S\) a function to some set. We say \(f\) hides the subgroup \(H\le G\) if \(f(g_1)=f(g_2)\) exactly when \(g_1\) and \(g_2\) lie in the same coset of \(H\) (\(g_1H=g_2H\)). The HSP is: given \(f\) as an oracle, find \(H\) (for example, a generating set), using a number of queries and gates polynomial in \(\log|G|\).
Let \(G=\mathbb Z_{12}\) under addition and \(f(x)=x\bmod4\). \(f\) hides a subgroup \(H\). How many elements does \(H\) have, and how many cosets?
If \(G\) is a finite abelian group whose Fourier transform can be implemented efficiently, the HSP over \(G\) can be solved with \(O(\log|G|)\) queries and polynomially many gates. The algorithm repeats: prepare \(\frac{1}{\sqrt{|G|}}\sum_g|g\rangle|f(g)\rangle\); Fourier-transform the first register; measure. Each outcome is a uniformly random character \(\chi\) with \(\chi(h)=1\) for all \(h\in H\); after \(O(\log|G|)\) samples, \(H\) is determined as the set of elements on which all sampled characters are 1.
Proof sketch. Theorem 16.3's calculation, in general: after measuring \(f\), the state is a uniform superposition over a coset \(g_0H\), and its Fourier transform is supported on the characters trivial on \(H\) (the "annihilator" \(H^\perp\)), each with the same probability. Random elements of a group generate it after \(O(\log|G|)\) samples, as in Proposition 10.3. See de Wolf, Ch. 6.
Identify \(G\), \(H\) and the information in one sample for Simon's algorithm, order finding and the DLP.
For non-abelian groups the story changes. Ettinger, Høyer and Knill (2004) showed that polynomially many queries always suffice to determine \(H\), but no one knows how to extract \(H\) from those samples with polynomial computation for the groups that matter.
| problem | group \(G\) | abelian? | efficient quantum algorithm? |
|---|---|---|---|
| Simon's problem | \(\mathbb Z_2^n\) | yes | yes (Simon 1994) |
| factoring, order finding | \(\mathbb Z\) | yes | yes (Shor 1994) |
| discrete log, \(\mathbb Z_p^*\) and elliptic curves | \(\mathbb Z_r\times\mathbb Z_r\) | yes | yes (Shor 1994) |
| Pell's equation, unit groups | \(\mathbb R\), \(\mathbb R^k\) | yes | yes (Hallgren 2002 and later) |
| graph isomorphism | \(S_n\) | no | none known |
| unique shortest vector in a lattice | dihedral \(D_N\) (via Regev) | no | subexponential only (Kuperberg) |
Lattice-based schemes such as ML-KEM and ML-DSA, the new NIST standards (Lecture 17), rest on problems like learning with errors: solve a system of linear equations mod \(q\) that has small random errors added. Without the errors, Gaussian elimination solves it instantly; with them, the best classical and quantum algorithms take exponential time. The natural route to a quantum attack goes through the dihedral HSP, where the best algorithm is subexponential and still impractical, and decades of effort have produced no Shor-like speedup. That is evidence, not proof: in 2024 a claimed polynomial-time quantum algorithm for lattice problems (Chen) circulated for about ten days before a bug was found. The lesson is that post-quantum security is a belief about the absence of an algorithm, and it is held more confidently the longer smart people fail to find one.
Tick every problem for which an efficient (polynomial-time) quantum algorithm is known.
import itertools import numpy as np from qiskit import QuantumCircuit from qiskit.circuit.library import CDKMRippleCarryAdder from qiskit.quantum_info import Statevector def maj(qc, c, b, a): # MAJ: a <- majority(a, b, c), and b, c become b^a, c^a qc.cx(a, b); qc.cx(a, c); qc.ccx(c, b, a) def uma(qc, c, b, a): # UMA: undo MAJ and leave the sum bit in b qc.ccx(c, b, a); qc.cx(a, c); qc.cx(c, b) def adder(n): """|a>|b> -> |a>|a+b>: qubit 0 is a zero ancilla, a_i on 1+2i, b_i on 2+2i, carry-out on 2n+1""" qc = QuantumCircuit(2 * n + 2) A = [1 + 2 * i for i in range(n)]; B = [2 + 2 * i for i in range(n)] maj(qc, 0, B[0], A[0]) for i in range(1, n): maj(qc, A[i - 1], B[i], A[i]) qc.cx(A[n - 1], 2 * n + 1) # copy out the top carry for i in reversed(range(1, n)): uma(qc, A[i - 1], B[i], A[i]) uma(qc, 0, B[0], A[0]) return qc, A, B n = 3 qc, A, B = adder(n) ok = True for a, b in itertools.product(range(2 ** n), repeat=2): prep = QuantumCircuit(2 * n + 2) for i in range(n): if (a >> i) & 1: prep.x(A[i]) if (b >> i) & 1: prep.x(B[i]) out = int(np.argmax(Statevector.from_instruction(prep.compose(qc)).probabilities())) s = sum(((out >> B[i]) & 1) << i for i in range(n)) + (((out >> (2 * n + 1)) & 1) << n) ok &= (s == a + b) print("3-bit adder correct on all 64 inputs:", ok) for n in (4, 8, 16, 32): ops = adder(n)[0].count_ops() print(f"n = {n:2d}: Toffolis {ops['ccx']:3d}, CNOTs {ops['cx']:3d}, qubits {2 * n + 2}") print("Qiskit's CDKMRippleCarryAdder(8), Toffolis:", CDKMRippleCarryAdder(8, kind="full").decompose(reps=2).count_ops()["ccx"])
3-bit adder correct on all 64 inputs: True n = 4: Toffolis 8, CNOTs 17, qubits 10 n = 8: Toffolis 16, CNOTs 33, qubits 18 n = 16: Toffolis 32, CNOTs 65, qubits 34 n = 32: Toffolis 64, CNOTs 129, qubits 66 Qiskit's CDKMRippleCarryAdder(8), Toffolis: 16
The adder uses exactly \(2n\) Toffolis and \(4n+1\) CNOTs, linear in \(n\), and matches Qiskit's library version. The carry ripples through MAJ blocks on the way up and is uncomputed by UMA blocks on the way down, so the only ancilla, qubit 0, ends in \(|0\rangle\). A modular multiplication uses about \(n\) such additions (plus comparisons), which is where Proposition 16.2's \(n^2\) comes from.
import numpy as np from math import gcd p, g, h = 11, 2, 9 # find x with 2^x = 9 (mod 11); the order of g is r = 10 r = 10 hinv = pow(h, -1, p) f = {(a, b): pow(g, a, p) * pow(hinv, b, p) % p for a in range(r) for b in range(r)} # state (1/r) sum_{a,b} |a>|b>|f(a,b)>, then the Fourier transform over Z_r on both registers w = np.exp(2j * np.pi / r) P = np.zeros((r, r)) for val in set(f.values()): coset = [ab for ab, v in f.items() if v == val] # the (a, b) with this value of f amp = np.array([[sum(w ** (a * c + b * d) for a, b in coset) for d in range(r)] for c in range(r)]) P += np.abs(amp) ** 2 / r ** 4 rng = np.random.default_rng(16) for _ in range(6): k = rng.choice(r * r, p=P.ravel()); c, d = divmod(int(k), r) if gcd(c, r) == 1: print(f"(c, d) = ({c}, {d}): x = -d * c^-1 mod {r} = {(-d * pow(c, -1, r)) % r}") else: print(f"(c, d) = ({c}, {d}): c is not invertible mod {r}; try again")
(c, d) = (5, 0): c is not invertible mod 10; try again (c, d) = (4, 6): c is not invertible mod 10; try again (c, d) = (0, 0): c is not invertible mod 10; try again (c, d) = (3, 2): x = -d * c^-1 mod 10 = 6 (c, d) = (6, 4): c is not invertible mod 10; try again (c, d) = (0, 0): c is not invertible mod 10; try again
Each run returns a pair on the line \(d\equiv-6c\); only those with \(c\in\{1,3,7,9\}\), four of the ten, solve the problem directly. Even the failures help: \((5,0)\) says \(5x\equiv0\pmod{10}\), so \(x\) is even, and \((4,6)\) says \(4x+6\equiv0\pmod{10}\), so \(x\in\{1,6\}\); together they force \(x=6\) (exercise 3).
Next time: what the resource estimates actually say about RSA and elliptic curves, harvest-now-decrypt-later, and the migration to post-quantum cryptography. HW8 (Lectures 15–16) is due at the start of Week 10.
all numbers and figures in these notes are computed in python (verify_L16.py) or taken from the cited estimates, and follow the page theme