QianHeng乾珩 PQC Docs Hub量子文档 ✦ Ask AI✦ 问问文档 ⚐ Scan⚐ 扫一扫

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 setSecurity levelPublic keySignature
ML-DSA-44Category 213122420
ML-DSA-65 (common default)Category 319523309
ML-DSA-87Category 525924627

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)
Note
When using deterministic signing, ensure the message-hashing context is correct and that the same key is never used across incompatible domains. While deterministic ML-DSA is robust against bad RNGs, hedged (randomized) signing is recommended in production to provide an extra defense against fault-injection attacks.

Standards & references

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等级 213122420
ML-DSA-65 常用默认等级 319523309
ML-DSA-87等级 525924627

优势与取舍

  • 快且简洁。签名与验证迅速,实现仅用整数运算、不涉及浮点,恒定时间代码易于编写。
  • 稳健。拒绝采样设计经受住了分析,且避开浮点也绕过了 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)
说明
使用确定性签名时,务必确保消息哈希的上下文正确,且同一密钥绝不跨不兼容域复用。确定性 ML-DSA 虽对劣质随机源具有鲁棒性,但生产环境推荐加噪(随机化)签名,以增加一层针对故障注入攻击的防护。

标准与参考

相关页面

⚑ Report an error⚑ 纠错与校正