Key Generation
August 25, 20264 min readbeginner
Key generation is the most familiar part of ML-DSA, because it is almost the same Module-LWE sample as ML-KEM's.
Key generation is the most familiar part of ML-DSA, because it is almost the same Module-LWE sample as ML-KEM's. One step at the end is new, and it creates a problem that the rest of the chapter has to solve.
01.The steps
K1. Expand the seed. Start from 32 random bytes and hash into three pieces:
with being 32 bytes, 64, and 32.
generates the public matrix. generates the secrets. is a per-key salt kept for later, used inside signing to derive the commitment randomness.
K2. Expand . Rejection-sample SHAKE128 keyed by into a uniform matrix . Same "regenerate rather than transmit" arrangement as the KEM: the matrix travels as a 32-byte seed.
K3. Sample the secrets. From , draw and , all coefficients from so they lie in .
K4. Form the Module-LWE sample.
Exactly the shape from Chapter 4, with as secret and as error. Recovering from is Module-LWE hard.
K5. Truncate . This is the new step. Split every coefficient of into a high part and a low part:
with . So holds the top ten bits of each 23-bit coefficient and holds the bottom thirteen.
Only goes into the public key. The low part is kept in the secret key.
K6. Precompute , a digest of the public key, so signing does not recompute it.
K7. Output.
At ML-DSA-65 that is about 1952 bytes of public key and 4032 bytes of secret key.
02.Why truncate
Step K5 is pure bandwidth economics.
Each coefficient of is 23 bits, and there are of them. At that is 1536 coefficients, so a full costs about 4416 bytes. Keeping only the top ten bits costs 1920.
Public keys travel inside certificates, and certificate chains are already the largest thing in a TLS handshake. Halving the key is worth real effort.
03.The problem it creates
Discarding means the signer and the verifier no longer hold the same value.
The signer knows exactly. The verifier has only , from which it can compute . The two differ by , which the verifier does not have and cannot derive, since it is part of the secret key.
That discrepancy would not matter if the verification equation used linearly and the error simply passed through. It does not. As Verification shows, enters the verifier's computation multiplied by the challenge, as , and then that result is rounded. Rounding is not linear, and a small perturbation just below a rounding boundary produces a completely different answer just above it.
So most coefficients round the same way for both parties, and a handful do not.
The design response is the one flagged in the source and worth stating as a principle: drop , bank the savings, and pay the cost later with a short hint. The hint vector in Signing is a list of exactly which coefficients rounded differently, and it is small because there are few of them.
That is a trade worth noticing as engineering. A cleaner design would send the full and need no hint at all. ML-DSA instead accepts a genuinely intricate piece of machinery, the hint, in exchange for halving the thing that travels most often. The intricacy is confined to the scheme's internals, where it can be specified once and tested exhaustively, while the saving is paid out on every connection forever.