Skip to content

Appendix D: Solutions for Chapter 9

This page collects solutions and editorial notes for the exercises in Chapter 9: Ring-LWE and Module-LWE. 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 ring_lwe package under solutions/ch09-ring-lwe. From a clone of the companion repository, pytest tests/ch09 runs its suite. Appendix C has the setup.

The exercise walks the calculation. Key checks: x9≡x⋅x8≡x⋅(−1)=−x≡16x(modx8+1,17)x^9 \equiv x \cdot x^8 \equiv x \cdot (-1) = -x \equiv 16 x \pmod{x^8 + 1, 17}, and x8≡−1≡16(modx8+1,17)x^8 \equiv -1 \equiv 16 \pmod{x^8 + 1, 17}. The negacyclic minus sign is the difference between this ring and the cyclic ring Z[x]/(xn−1)\mathbb{Z}[x]/(x^n - 1). In the cyclic ring x9≡xx^9 \equiv x rather than −x-x.

def ring_mul(f, g, n=8, q=17):
out = [0] * n
for i in range(n):
for j in range(n):
k = i + j
sign = 1 if k < n else -1
out[k % n] = (out[k % n] + sign * f[i] * g[j]) % q
return out
f = [0] * 8; f[5] = 1 # x^5
g4 = [0] * 8; g4[4] = 1 # x^4
g3 = [0] * 8; g3[3] = 1 # x^3
print(ring_mul(f, g4))
print(ring_mul(f, g3))
# ==> [0, 16, 0, 0, 0, 0, 0, 0]
# ==> [16, 0, 0, 0, 0, 0, 0, 0]

The negacyclic NTT evaluates f(x)f(x) at the odd powers of ψ\psi, where ψ\psi is a primitive 2n2n-th root of unity in Zq\mathbb{Z}_q. For f=xf = x, the evaluation is f(ψ2k+1)=ψ2k+1f(\psi^{2k+1}) = \psi^{2k+1}, which gives the sequence (ψ1,ψ3,ψ5,ψ7)(\psi^1, \psi^3, \psi^5, \psi^7) modulo qq. With ψ=2,q=17\psi = 2, q = 17: ψ1=2\psi^1 = 2, ψ3=8\psi^3 = 8, ψ5=32 mod 17=15\psi^5 = 32 \bmod 17 = 15, ψ7=128 mod 17=9\psi^7 = 128 \bmod 17 = 9.

print([pow(2, 2 * k + 1, 17) for k in range(4)])
# ==> [2, 8, 15, 9]

The verification is a transcription of the Module-LWE definition. For each output row ii, recompute b[i]=∑j=0k−1A[i,j]⋅s[j]+e[i]\mathbf{b}[i] = \sum_{j=0}^{k-1} \mathbf{A}[i,j] \cdot \mathbf{s}[j] + \mathbf{e}[i] in the ring RqR_q, then assert termwise equality with the package-returned b\mathbf{b}. The test in tests/ch09/test_module_collapses_to_ring.py does this for k=1,2,3k = 1, 2, 3 and is the reference. Writing it yourself reinforces where the two indices go. The mm rows are the samples; the kk columns are the components of the secret. At k=1k = 1 each row is a single ring product, so the mm rows are mm Ring-LWE samples sharing one secret. At k>1k > 1 each row sums kk ring products against a rank-kk secret, and those kk terms are never observed separately. At this exercise’s (k,m)=(3,4)(k, m) = (3, 4) that is four samples, not three.

The condition 16∣q−116 \mid q - 1 is the existence requirement for a primitive 1616-th root of unity in Zq∗\mathbb{Z}_q^*, which has order q−1q - 1. The primes below 200 satisfying this are 17,97,113,19317, 97, 113, 193. Once ψ\psi is found, the order check ψ16≡1,ψ8≢1\psi^{16} \equiv 1, \psi^8 \not\equiv 1 rules out roots of order 1, 2, 4, or 8. The order must divide 16 and be larger than 8, so the order is 16.

def is_prime(n):
return n > 1 and all(n % i for i in range(2, int(n ** 0.5) + 1))
primes = [q for q in range(3, 200) if is_prime(q) and (q - 1) % 16 == 0]
print(primes)
# ==> [17, 97, 113, 193]

The identity holds at 22 because 24+1=17≡0(mod17)2^4 + 1 = 17 \equiv 0 \pmod{17}, so reducing modulo x4+1x^4 + 1 does not change a polynomial’s value at 22. What changes is the error’s image. With each ei∈{−1,0,1}e_i \in \{-1, 0, 1\}, e(2)=e0+2e1+4e2+8e3e(2) = e_0 + 2e_1 + 4e_2 + 8e_3 takes every integer value from −15-15 to 1515, so the widened window holds 3131 values, more than the 1717 elements of Z17\mathbb{Z}_{17}. Every residual passes, and the test keeps all 1717 guesses on Ring-LWE samples and on uniform ones alike. It distinguishes nothing. The other roots, 88, 1515 and 99, behave the same way, because their powers are 11, 22, 44 and 88 up to sign and order.

What made x=1x = 1 useful is that every power of 11 is 11, so e(1)e(1) is a plain sum of nn short coefficients and stays within nB=4nB = 4 of 00, which is 99 residues out of 1717. No root of xn+1x^n + 1 is 11, since 1n+1=21^n + 1 = 2, and when 2n∣q−12n \mid q - 1 the roots it does have are the odd powers of ψ\psi at which the NTT evaluates. The window test needs a root at which a short error keeps a short image. That claim is about this test only. At the toy parameters e(2)e(2) still lands on some residues more often than others, so a test that counts how often each residual appears could separate the two kinds of sample, given enough of them.