Ring-LWE is Learning With Errors where the secret, the noise and the public values are polynomials in a ring such as Zq[X]/(Xn+1)\mathbb{Z}_q[X]/(X^n+1). One random polynomial takes the place of a whole n×nn \times n matrix, so keys shrink from about n2n^2 numbers to nn. Module-LWE sits in between: it uses a small k×kk \times k matrix of such polynomials. ML-KEM (Kyber) and ML-DSA (Dilithium) are both built on Module-LWE.

Plain LWE and its size problem

In Learning With Errors you are given a random matrix A∈Zqm×nA \in \mathbb{Z}_q^{m \times n} and a vector b=As+e mod qb = As + e \bmod q, where ss is secret and ee is a vector of small errors. Recovering ss, or even telling bb apart from uniform, is believed hard. The cost is size: with m=nm = n, the matrix alone holds n2n^2 numbers. At the dimension used by ML-KEM-768, n=768n = 768, that is 589,824 entries, and every multiplication by AA takes about as many operations.

What is Ring-LWE?

Ring-LWE replaces vectors of integers with polynomials and the matrix with a single polynomial. Work in the ring

Rq=Zq[X]/(Xn+1),R_q = \mathbb{Z}_q[X]/(X^n + 1),

whose elements are polynomials of degree below nn with coefficients mod qq. Multiplication is ordinary polynomial multiplication followed by the rule Xn=−1X^n = -1. The ring notation is summarised in 8.4 Rings and polynomials.

Definition — Ring-LWE sample

Fix a secret s∈Rqs \in R_q with small coefficients. A Ring-LWE sample is a pair (a, b=a⋅s+e)(a,\ b = a \cdot s + e) where a∈Rqa \in R_q is uniformly random and e∈Rqe \in R_q has small coefficients. Search Ring-LWE asks for ss; decision Ring-LWE asks whether pairs come from this distribution or are uniform.

One polynomial is a structured matrix

Multiplying by a fixed aa is a linear map on the coefficient vector of ss, so it has a matrix. Column jj of that matrix holds the coefficients of a⋅Xja \cdot X^j: the coefficients of aa shifted down by jj places, with every coefficient that wraps around negated. Take n=4n = 4, q=17q = 17 and a=3+X+4X2+X3a = 3 + X + 4X^2 + X^3:

Ma=(3−1−4−113−1−4413−11413)(mod17)M_a = \begin{pmatrix} 3 & -1 & -4 & -1 \\ 1 & 3 & -1 & -4 \\ 4 & 1 & 3 & -1 \\ 1 & 4 & 1 & 3 \end{pmatrix} \pmod{17}

Four numbers determine all sixteen entries. With the small secret s=1−X2+X3s = 1 - X^2 + X^3, coefficient vector (1,0,−1,1)(1, 0, -1, 1), both a⋅sa \cdot s and MasM_a s give (6,15,0,3)(6, 15, 0, 3) mod 17. Adding the error e=(1,−1,0,1)e = (1, -1, 0, 1) gives the public value b=(7,14,0,4)b = (7, 14, 0, 4). Seen as a lattice problem, a Ring-LWE sample is an LWE sample whose matrix happens to be negacyclic.

The saving goes beyond storage. Because q=3329q = 3329 is chosen so that X256+1X^{256} + 1 splits mod qq, products in RqR_q can be computed with the number theoretic transform in O(nlog⁡n)O(n \log n) operations instead of O(n2)O(n^2).

How hard is Ring-LWE?

Lyubashevsky, Peikert and Regev (2010) showed that, for rings such as Z[X]/(Xn+1)\mathbb{Z}[X]/(X^n+1) with nn a power of two, solving Ring-LWE on average is at least as hard as solving approximate shortest-vector problems on ideal lattices in the worst case, using a quantum reduction. Ideal lattices are a special class, so this is a weaker foundation than the reduction for plain LWE, which starts from arbitrary lattices. In practice, the best known attacks on Ring-LWE at cryptographic parameters are the same lattice-reduction attacks used against plain LWE of the same dimension.

What is Module-LWE?

Module-LWE keeps the polynomial ring but brings back a small matrix. The secret is a vector of kk polynomials and the public matrix is k×kk \times k polynomials.

Definition — Module-LWE sample

Fix a secret s∈Rqks \in R_q^k with small coefficients. A Module-LWE sample is (A, b=As+e)(A,\ b = A s + e) with A∈Rqk×kA \in R_q^{k \times k} uniformly random and e∈Rqke \in R_q^k small. Here kk is the module rank, and the underlying lattice has dimension k⋅nk \cdot n.

The two earlier problems are special cases. With k=1k = 1 the matrix is a single polynomial: that is Ring-LWE. With n=1n = 1 the ring is just Zq\mathbb{Z}_q and AA is an ordinary integer matrix: that is plain LWE. Langlois and Stehlé (2015) gave worst-case to average-case reductions for Module-LWE from problems on module lattices, which contain the ideal lattices of Ring-LWE as the rank-one case.

A toy Module-LWE sample in Python

The code below builds one sample with n=8n = 8, k=2k = 2 and q=3329q = 3329, using plain Python. It draws small values uniformly from {−2,…,2}\{-2, \dots, 2\} for simplicity; ML-KEM uses a centred binomial distribution instead.

import random

n, q, k, eta = 8, 3329, 2, 2          # toy sizes; ML-KEM uses n = 256
rng = random.Random(1)

def polymul(a, b):
    """Multiply in Z_q[X]/(X^n + 1): wrap-around terms change sign."""
    c = [0] * n
    for i, ai in enumerate(a):
        for j, bj in enumerate(b):
            if i + j < n:
                c[i + j] = (c[i + j] + ai * bj) % q
            else:
                c[i + j - n] = (c[i + j - n] - ai * bj) % q
    return c

def add(a, b):
    return [(x + y) % q for x, y in zip(a, b)]

def uniform():
    return [rng.randrange(q) for _ in range(n)]

def small():
    return [rng.randint(-eta, eta) % q for _ in range(n)]

A = [[uniform() for _ in range(k)] for _ in range(k)]  # k x k matrix of polynomials
s = [small() for _ in range(k)]                         # secret: k small polynomials
e = [small() for _ in range(k)]                         # error: k small polynomials

b = []
for i in range(k):
    row = e[i]
    for j in range(k):
        row = add(row, polymul(A[i][j], s[j]))
    b.append(row)

centered = lambda p: [x - q if x > q // 2 else x for x in p]
print("s[0] =", centered(s[0]))
print("b[0] =", b[0])
print("numbers in A:", k * k * n, "  plain LWE would need:", (k * n) ** 2)
s[0] = [0, -2, -2, -2, 2, -2, 1, -1]
b[0] = [1055, 8, 2628, 307, 706, 570, 860, 3310]
numbers in A: 32   plain LWE would need: 256

The secret stays small while bb looks like random numbers mod 3329. At ML-KEM-768 sizes, k=3k = 3 and n=256n = 256, the matrix has 2,304 coefficients instead of 589,824, and ML-KEM does not even store those: it regenerates AA from a 32-byte seed.

Ring-LWE vs Module-LWE vs plain LWE

Plain LWERing-LWEModule-LWE
Public matrixn×nn \times n integersone polynomial of degree <n< nk×kk \times k polynomials of degree <n< n
Lattice dimensionnnnnknk n
Numbers in the matrixn2n^2nnk2nk^2 n
Multiplication costO(n2)O(n^2)O(nlog⁡n)O(n \log n) with the NTTO(k2nlog⁡n)O(k^2 n \log n)
Structure an attacker could usenonemost (ideal lattice)less (module lattice)
Changing the security levelchange nnchange the ringchange kk, keep the ring

Why ML-KEM and ML-DSA use Module-LWE

Module-LWE gives most of the size and speed of Ring-LWE while keeping one ring for every security level. ML-KEM (FIPS 203) fixes n=256n = 256 and q=3329q = 3329 and sets k=2,3,4k = 2, 3, 4 for ML-KEM-512, -768 and -1024. The same NTT code, the same polynomial arithmetic and the same hardware serve all three. ML-DSA (FIPS 204) does the same with n=256n = 256 and q=8,380,417q = 8{,}380{,}417, using a k×ℓk \times \ell matrix of size 4×44 \times 4, 6×56 \times 5 and 8×78 \times 7 for its three parameter sets. There the security relies on Module-LWE for the keys and on Module-SIS for the signatures.

Parameter setnnqqModule shapeLattice dimension
ML-KEM-5122563329k=2k = 2512
ML-KEM-7682563329k=3k = 3768
ML-KEM-10242563329k=4k = 41024
ML-DSA-442568,380,4174×44 \times 41024 (secret)
ML-DSA-652568,380,4176×56 \times 51280 (secret)
ML-DSA-872568,380,4178×78 \times 71792 (secret)

Does the ring structure make it weaker?

Structure is a risk in principle, and it is the main reason the reductions are stated for ideal or module lattices rather than all lattices. Some algebraic attacks do exist: for example, there are quantum algorithms that find unusually short vectors in principal ideal lattices better than general lattice reduction can. None of these translate into a practical attack on Ring-LWE or Module-LWE at the parameters of ML-KEM or ML-DSA, whose security estimates come from the same primal and dual lattice attacks used against plain LWE. The power-of-two cyclotomic ring Z[X]/(Xn+1)\mathbb{Z}[X]/(X^n+1) is chosen because it is fast, well studied and has no known weakness for these problems. Module-LWE adds a margin over Ring-LWE because the lattice has less algebraic symmetry.

Common mistakes

Further reading

V. Lyubashevsky, C. Peikert and O. Regev, On Ideal Lattices and Learning with Errors over Rings, Eurocrypt 2010. A. Langlois and D. Stehlé, Worst-case to Average-case Reductions for Module Lattices, Designs, Codes and Cryptography, 2015. NIST FIPS 203 (ML-KEM) and FIPS 204 (ML-DSA), 2024, for the exact parameter sets. The first two references are cited from memory. See also the q-ary lattices guide for the lattice behind LWE samples.

Check Your Understanding

  1. Q1. In Zq[X]/(Xn+1)\mathbb{Z}_q[X]/(X^n+1), what happens to the coefficient that wraps past Xn−1X^{n-1} when you multiply by XX?

  2. Q2. Module-LWE with module rank k=1k = 1 is the same as which problem?

  3. Q3. ML-KEM-512, ML-KEM-768 and ML-KEM-1024 differ mainly in which parameter?