Appendix D: Solutions for Chapter 13
This page collects solutions and editorial notes for the exercises in Chapter 13: Lattice cryptanalysis. Compute and derivation exercises have worked solutions; open-ended exercises have an editorial note describing what a strong answer addresses.
The fuller versions of these routines are in the cryptanalysis package under solutions/ch13-lattice-cryptanalysis. From a clone of the companion repository, pytest tests/ch13 runs its suite. Appendix C has the setup.
Exercise 1
Section titled “Exercise 1”The classical core-SVP cost is bits and the quantum cost is bits. Both scale linearly in , so monotonicity is automatic. ML-KEM-768’s falls between the rows for and . Floor the products rather than rounding them, which is what the Kyber security script does: it prints int(floor(...)), and the chapter’s core_svp_classical uses int() for the same reason. At the rounded exponents give classical and quantum. Table 4 prints and , which flooring the unrounded and reproduces; so does rounding the headline products to nearest, so the reproduction does not settle which arithmetic the table used. Either way it is the one-bit effect the chapter’s estimator section walks. Either way the figure sits well below the -bit classical floor the NIST Call for Proposals sets for category 3. The Kyber Round 3 submission argues that core-SVP conservatism covers the gap, and its refined gate count of bits is what clears the floor (Avanzi et al., 2021).
for beta in (100, 200, 400, 600, 626, 800, 1000): print(beta, int(0.292 * beta), int(0.265 * beta))# ==> 100 29 26# ==> 200 58 53# ==> 400 116 106# ==> 600 175 159# ==> 626 182 165# ==> 800 233 212# ==> 1000 292 265Exercise 2
Section titled “Exercise 2”The sweep gives the following, with the last row landing on ML-KEM-768’s own block size:
import math
def delta_beta(beta): numerator = ((math.pi * beta) ** (1.0 / beta)) * beta return (numerator / (2.0 * math.pi * math.e)) ** (1.0 / (2.0 * (beta - 1)))
def primal_succeeds(beta, d, q, m, sigma): log_lhs = math.log(sigma * math.sqrt(beta)) log_rhs = (2 * beta - d - 1) * math.log(delta_beta(beta)) + (m / d) * math.log(q) return log_lhs <= log_rhs
def smallest_beta(n_unknowns, q=3329, sigma=1.0): for beta in range(50, 1200): for m in range(1, 2 * n_unknowns + 1): if primal_succeeds(beta, m + n_unknowns + 1, q, m, sigma): return beta raise AssertionError("no beta in range")
for n_unknowns in (50, 100, 200, 300, 400, 512, 640, 768): print(n_unknowns, smallest_beta(n_unknowns))# ==> 50 50# ==> 100 50# ==> 200 105# ==> 300 191# ==> 400 280# ==> 512 382# ==> 640 502# ==> 768 624The block size climbs steadily with the number of unknowns once the instance is large enough to be interesting, and the final row reproduces the the chapter’s free search returns for ML-KEM-768. The two equal rows are the point of the exercise. At and the search returns because is where it starts, not because the condition first becomes satisfiable there.
Searching below would not repair that, and this is the part worth writing down. The closed form for is an asymptotic approximation that the chapter states is valid for . Run it at and the condition is satisfied at a single sample, which is not a security estimate but a formula evaluated outside its range. So the honest answer for these two instances is that the model cannot express how weak they are, only that they are weaker than anything it covers. That is a property of the estimator, not of the instances, and it is the reason the chapter’s core_svp_beta starts its sweep at rather than at .
Toy parameter sets are pedagogically useful and offer no cryptographic strength. What the sweep shows is that the estimator has a floor beneath which it stops distinguishing between degrees of broken.
Exercise 3
Section titled “Exercise 3”The Albrecht-Bai-Ducas attack works only when is large enough relative to that the secret vector becomes shorter than the Gaussian heuristic in a subfield projection of the lattice. This is the “overstretched” regime. Ducas and van Woerden 2021 place the fatigue point for ternary NTRU at (Ducas & van Woerden, 2021). At that is around , about . So sits far past it, while sits below it by a factor of about six at this (at ML-KEM’s own the point is near , as the chapter notes). The two moduli differ by a factor of roughly .
Two things carry more weight than the modulus, though, and a strong answer says both. First, the attack maps the lattice into a subfield of the cyclotomic by a norm or trace map. It is not modulus switching, which is a dual-attack refinement and belongs to a different family. Second, and this is the substantive point, the attack is a statement about the NTRU key distribution, where the secret is a ratio of two short ring elements, and not about the Module-LWE public key ML-KEM publishes. Langlois and Stehlé 2015 is the worst-case to average-case foundation of the Module-LWE family (Langlois & Stehlé, 2015, sec. 4.1). It is a reduction with hypotheses, not a statement about overstretched parameters: it is stated for an elliptical Gaussian error family and, for its direct search-to-decision route, for a prime modulus that splits completely, with a modulus-switching route (Theorem 4.8) that reaches other moduli at enlarged Gaussian noise, so on either route it certifies the family rather than ML-KEM’s centered-binomial instance at . Carrying the NTRU threshold across to ML-KEM is the error the exercise is testing for, and so is reading the reduction as a certificate for the standardized parameters.
Exercise 4
Section titled “Exercise 4”The Fluhrer attack picks to push the decryption sum into the boundary between bit 0 and bit 1, where the noise margin is exactly the size . The two queries probe the boundary from above and below. The query gives , so it crosses into bit exactly when . The query gives and crosses exactly when . The pair is therefore if , if , and if . That identifies uniquely. The fourth case does not occur for . Total oracle calls is for the small-secret toy at Chapter 10’s parameters. The attack scales as in the absence of an FO transform, which is why every lattice- and code-based KEM in this book wraps its PKE in one.