Appendix D: Solutions for Chapter 8
This page collects solutions and editorial notes for the exercises in Chapter 8: The LWE problem. 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 lwe package under solutions/ch08-lwe. From a clone of the companion repository, pytest tests/ch08 runs its suite. Appendix C has the setup.
Exercise 1
Section titled “Exercise 1”The expected behavior is not a gradient. Over 100 seeds at each of , , and , returns None on 100 of 100 instances at every width, and never returns the true secret. Recovery has already failed completely at , which is the point the chapter’s own worked block makes when it prints recovered noisy = None. There is no at which the solver degrades gracefully. A single unit of noise is enough. The “wrong secret” outcome stays rare because either finds a candidate satisfying every consistency row or reports failure. Spurious-but-consistent secrets are unlikely with extra check rows.
The residual distribution is the reason, and it also does not change with . The consistency check on the last rows asks exactly. Those rows do not carry the raw error: forward elimination replaces each one with a -linear combination of every error coordinate, scaled by pivot inverses. Multiplying a small error by an arbitrary element of destroys its smallness. Measured over 200 seeds, the mean absolute residual in symmetric representatives is at and at . A value drawn uniformly from averages . The fraction of nonzero consistency rows runs from to across the same range. The residuals are indistinguishable from uniform as soon as any noise is present, which is why the failure is immediate rather than progressive.
A strong answer connects that to the final part of the question. The check detects noise but extracts nothing from it, so it is not an attack: it says an instance is noisy without narrowing the search for . The regime where a consistent but wrong secret comes back is , where there are no consistency rows left to fire, and it is reached by varying rather than .
Exercise 2
Section titled “Exercise 2”The brute force enumerates candidate secrets. For the loop runs iterations, each computing in work. Write it as a per-candidate Python loop and it takes about fourteen minutes at roughly candidates per second; batch the candidates through numpy and the same enumeration finishes in about thirty seconds. Either is fine for one instance, and neither scales.
On a real LWE pair the minimum residual is at most , achieved at the true secret. On a uniform pair it is not , and assuming so would break the distinguisher. The minimum is taken over candidates, so it is the smallest of about million draws. A residual of -norm at most has probability . Setting at gives . Measured over six uniform pairs, the minimum residual came out , , , , , . The distinguisher still separates cleanly at the threshold , but the margin is one unit against four, not one against forty-eight.
Cost is . For fixed this is polynomial in . For fixed it is , exponential in . ML-KEM-768 is Module-LWE at module rank over a degree- ring, so its flat-LWE dimension is . The brute force is infeasible there by many hundreds of orders of magnitude, and lattice cryptography rests on exactly that gap.
print(97 ** 4)# ==> 88529281Exercise 3
Section titled “Exercise 3”The expected output: , and for every row of . The construction depends on having full column rank modulo . In the chapter’s notation, has determinant exactly when has rank modulo . If is rank-deficient mod , the lattice has smaller determinant and the constructed basis fails the orthogonality check on the extra rows.