Glossary

Dilithium

Dilithium, formally CRYSTALS-Dilithium, is a post-quantum digital signature scheme built on lattice mathematics, meant to resist quantum attacks. NIST standardized it as ML-DSA in FIPS 204, published August 13, 2024. It does the same job as Ed25519 or ECDSA, signing and verifying, but a large quantum computer is not believed to break it. Its keys and signatures are much larger than the classical ones.

How it works

The signer holds a private key and the verifier holds a public key. Signing hashes the message and produces a signature that the public key can check, in the same way as other signature schemes. ML-DSA uses a modulus q = 8380417 and a signing loop that retries until its output is safe to reveal, so signing time varies by message. FIPS 204 gives three parameter sets:

  • ML-DSA-44: security category 2, matrix A is 4 by 4.
  • ML-DSA-65: security category 3, matrix A is 6 by 5.
  • ML-DSA-87: security category 5, matrix A is 8 by 7.

FIPS 204 signs in a "hedged" way by default, mixing fresh randomness with a value held in the private key. A deterministic variant is allowed, but the standard warns against it on platforms exposed to side-channel or fault attacks. The next run uses a pure-Python implementation (dilithium-py 1.4.0), signs "hello" and verifies it, then verifies the same signature against "hellp".

from dilithium_py.ml_dsa import ML_DSA_44, ML_DSA_65, ML_DSA_87
for n, k in (("ML-DSA-44", ML_DSA_44), ("ML-DSA-65", ML_DSA_65), ("ML-DSA-87", ML_DSA_87)):
    pk, sk = k.keygen()
    s = k.sign(sk, b"hello")
    print(n, len(pk), len(sk), len(s), k.verify(pk, b"hello", s), k.verify(pk, b"hellp", s))
ML-DSA-44 1312 2560 2420 True False
ML-DSA-65 1952 4032 3309 True False
ML-DSA-87 2592 4896 4627 True False

The numbers are public key, private key and signature in bytes, matching Table 2 of FIPS 204. That library is for learning, so use a vetted one in production.

How big is a Dilithium signature?

An ML-DSA-65 signature is 3,309 bytes, and ML-DSA-44 and ML-DSA-87 signatures are 2,420 and 4,627 bytes. An Ed25519 signature is 64 bytes and its public key 32 bytes, and a quick run of Python cryptography printed 32 and 64. So an ML-DSA-44 public key and signature are roughly 41 and 38 times larger. Certificate chains and signed protocol messages feel this directly.

Is Dilithium the same as ML-DSA?

No, but ML-DSA is derived from it. FIPS 204 says the scheme is based on CRYSTALS-Dilithium and lists the changes in Appendix D, so older Dilithium code does not interoperate with ML-DSA. Specify ML-DSA when you need the standard.

Common pitfalls

  • Assuming a drop-in swap for Ed25519: sizes grow by more than an order of magnitude, which can break fixed-size fields, certificate limits and packet budgets.
  • Mixing up Dilithium and ML-DSA: FIPS 204 Appendix D lists differences from the Dilithium submission. Use ML-DSA.
  • Deterministic signing everywhere: FIPS 204 allows it but advises against it where fault attacks are a concern. Keep the hedged default.
  • Storing only the full private key: the 32-byte seed is enough to regenerate it, and storing only the seed saves space.
  • Trusting a pure-Python library: teaching code has no side-channel hardening. Use an audited implementation.

Related terms

  • Kyber — the lattice key-encapsulation scheme from the same project.
  • Ed25519 — the classical signature with a 64-byte output.
  • ECDSA — the elliptic-curve signature widely used in certificates.
  • RSA — the classical signature and encryption system quantum computers threaten.
  • ECC — the curve mathematics behind Ed25519 and ECDSA.

See also