ML-DSA (FIPS 204)
ML-DSA is the NIST-standardized digital-signature algorithm derived from CRYSTALS-Dilithium. Based on Module-LWE and Module-SIS lattice problems via the "Fiat-Shamir with Aborts" paradigm, it is one of NIST's recommended general-purpose post-quantum signature schemes.
How it works
ML-DSA is a digital signature scheme: a private key signs a message and the corresponding public key verifies the signature. Its security rests on two lattice problems over module rings — Module-LWE (hiding the secret key) and Module-SIS (making forgery hard).
Signing follows the Fiat-Shamir with Aborts paradigm. The signer commits to a random masking vector, derives a challenge by hashing the commitment and message, and computes a candidate signature. To avoid leaking the secret key, the signer performs rejection sampling: if the candidate falls outside a safe range it is discarded and a fresh attempt is made (the "abort"). This means signing time varies slightly, but the output never depends on the secret in a way that leaks it.
ML-DSA supports both deterministic signing (signature is a pure function of key and message) and hedged (randomized) signing, where fresh randomness is mixed in to harden against fault and side-channel attacks. FIPS 204's default ML-DSA.Sign uses hedged/randomized signing; a deterministic variant can be obtained by fixing the random input to an all-zero string, but most deployments are better served by keeping the randomized/hedged version.
Parameter sets
Three sets target NIST categories 2, 3, and 5. Sizes in bytes.
| Parameter set | Security level | Public key | Signature |
|---|---|---|---|
| ML-DSA-44 | Category 2 | 1312 | 2420 |
| ML-DSA-65 (common default) | Category 3 | 1952 | 3309 |
| ML-DSA-87 | Category 5 | 2592 | 4627 |
Strengths & tradeoffs
- Fast and simple. Signing and verification are quick, and the implementation uses only integer arithmetic — no floating point — which makes constant-time code straightforward.
- Robust. The rejection-sampling design has held up well under analysis, and avoiding floating point sidesteps Falcon's portability hazards.
- Tradeoff: public keys (~1.3-2.6 KB) and signatures (~2.4-4.6 KB) are larger than classical ECDSA/Ed25519, and notably larger than Falcon signatures. Variable signing time (due to aborts) is benign but worth noting for tight latency budgets.
When to use it
ML-DSA is a common choice for most signing needs: TLS certificate signatures, code signing, document signing, software-update authentication, and PKI. Choose it over Falcon unless signature/key size is the dominant constraint and you can safely manage floating-point sampling; choose it over SLH-DSA when performance and size matter more than the most conservative hash-only security assumption.
Code example
Sign and verify with liboqs-python:
import oqs
alg = "ML-DSA-65"
message = b"firmware image v1.2.3"
with oqs.Signature(alg) as signer:
public_key = signer.generate_keypair()
signature = signer.sign(message)
print("signature bytes:", len(signature)) # 3309
# Verification only needs the public key
with oqs.Signature(alg) as verifier:
ok = verifier.verify(message, signature, public_key)
print("valid:", ok)
Standards & references
- FIPS 204 (ML-DSA) — the official ML-DSA standard.
- CRYSTALS-Dilithium project — the design ML-DSA is derived from.
- Open Quantum Safe — liboqs implementation used in the code example.
- Resources — full standards register
Related
ML-DSA FIPS 204
ML-DSA 是 NIST 标准化的数字签名算法,源自 CRYSTALS-Dilithium。它基于 Module-LWE 与 Module-SIS 格问题,采用带中止的 Fiat-Shamir 范式,是 NIST 推荐的主力通用 PQC 签名之一。
工作原理
ML-DSA 是一种数字签名方案:私钥对消息签名,对应公钥验证签名。其安全性建立在模环上的两个格问题之上——Module-LWE(隐藏私钥)与 Module-SIS(使伪造困难)。
签名遵循带中止的 Fiat-Shamir 范式。签名者先承诺一个随机掩码向量,通过哈希承诺值与消息导出挑战,再计算候选签名。为避免泄露私钥,签名者执行拒绝采样:若候选值落在安全范围之外便丢弃并重试(即“中止”)。这会使签名耗时略有波动,但输出绝不会以泄露私钥的方式依赖于秘密。
ML-DSA 同时支持确定性签名(签名是密钥与消息的纯函数)与加噪(随机化)签名,后者混入新鲜随机数以抵御故障注入与侧信道攻击。FIPS 204 默认的 ML-DSA.Sign 使用 hedged/randomized signing;确定性变体可通过将随机输入设为固定零串实现,但一般部署更推荐保留随机化/hedged 版本。
参数集
三组参数对应 NIST 等级 2、3、5。尺寸单位为字节。
| 参数集 | 安全等级 | 公钥 | 签名 |
|---|---|---|---|
| ML-DSA-44 | 等级 2 | 1312 | 2420 |
| ML-DSA-65 常用默认 | 等级 3 | 1952 | 3309 |
| ML-DSA-87 | 等级 5 | 2592 | 4627 |
优势与取舍
- 快且简洁。签名与验证迅速,实现仅用整数运算、不涉及浮点,恒定时间代码易于编写。
- 稳健。拒绝采样设计经受住了分析,且避开浮点也绕过了 Falcon 的可移植性隐患。
- 取舍:公钥(约 1.3-2.6 KB)与签名(约 2.4-4.6 KB)大于经典 ECDSA/Ed25519,也明显大于 Falcon 签名。中止导致签名耗时波动属正常现象,但在严苛时延场景中值得留意。
适用场景
ML-DSA 是多数签名需求的常用之选:TLS 证书签名、代码签名、文档签名、软件更新认证与 PKI。除非签名/密钥尺寸是首要约束且你能安全管理浮点采样,否则应优先选它而非 Falcon;当性能与尺寸比“仅依赖哈希的最保守假设”更重要时,应优先选它而非 SLH-DSA。
代码示例
使用 liboqs-python 签名并验证:
import oqs
alg = "ML-DSA-65"
message = b"firmware image v1.2.3"
with oqs.Signature(alg) as signer:
public_key = signer.generate_keypair()
signature = signer.sign(message)
print("签名字节数:", len(signature)) # 3309
# 验证只需公钥
with oqs.Signature(alg) as verifier:
ok = verifier.verify(message, signature, public_key)
print("有效:", ok)
标准与参考
- FIPS 204 ML-DSA — ML-DSA 官方标准。
- CRYSTALS-Dilithium 项目 — ML-DSA 所源自的设计。
- Open Quantum Safe — 代码示例所用的 liboqs 实现。
- 资源链接 — 完整标准登记册