ML-DSA vs SLH-DSA is the main choice among NIST's standardized post-quantum signatures, both published on 13 August 2024. ML-DSA (FIPS 204, from CRYSTALS-Dilithium) relies on structured lattices; SLH-DSA (FIPS 205, from SPHINCS+) relies only on the security of its hash function. Their size and speed profiles are so different that most systems will use ML-DSA, and SLH-DSA where its conservative assumptions justify the cost.
At a glance
| ML-DSA (FIPS 204) | SLH-DSA (FIPS 205) | |
|---|---|---|
| Assumption | Module-LWE and Module-SIS lattice problems | Properties of SHA-2 or SHAKE only |
| Parameter sets | ML-DSA-44, -65, -87 | 12 sets: SHA2 or SHAKE × 128/192/256 × s (small) or f (fast) |
| Security categories | 2, 3, 5 | 1, 3, 5 |
| Public key | 1,312 / 1,952 / 2,592 bytes | 32 / 48 / 64 bytes |
| Signature | 2,420 / 3,309 / 4,627 bytes | 7,856 (128s) to 49,856 bytes (256f) |
| Private key | 2,560–4,896 bytes expanded, or a 32-byte seed | 64 / 96 / 128 bytes |
| Sign per second (OpenSSL 3.6.5) | about 3,900 (44), 2,400 (65), 2,050 (87) | about 7 (SHA2-128s), 144 (SHA2-128f), 3.5 (SHA2-192s) |
| Verify per second | about 20,800 (44), 13,600 (65), 8,500 (87) | about 7,400 (SHA2-128s), 2,400 (SHA2-128f) |
| Key generation per second | about 22,000 (44) | about 55 (128s), 3,400 (128f) |
| Signing randomness | Hedged by default, deterministic variant allowed | Hedged by default, deterministic variant allowed |
| Context string | Up to 255 bytes | Up to 255 bytes |
| Prehash variant | HashML-DSA (§5.4) | HashSLH-DSA (§10.2.2) |
| X.509 | RFC 9881 (id-ml-dsa-44 = 2.16.840.1.101.3.4.3.17 …) | RFC 9909 (id-slh-dsa-sha2-128s = …3.4.3.20 …) |
Speeds measured with openssl speed on one core of an Apple M4 Max; OpenSSL's ML-DSA is portable C, and optimized implementations sign several times faster.
Security assumptions
ML-DSA is a Fiat–Shamir-with-aborts lattice scheme. Its security rests on Module Learning With Errors and Module Short Integer Solution, problems that have been studied for about two decades and resisted both classical and quantum attacks, but whose concrete security estimates still move as lattice-reduction techniques improve. NIST chose parameter sets with margins against those estimates.
SLH-DSA builds signatures from one-time and few-time hash-based signatures arranged in a hypertree. If SHA-256 or SHAKE256 keep their preimage and related properties, SLH-DSA stays secure; there is no algebraic structure to attack. That makes it the most conservative signature NIST has standardized, and the natural hedge if a lattice breakthrough ever arrives. Unlike the stateful hash-based schemes LMS and XMSS, it needs no state: each key can sign up to 2⁶⁴ messages.
Sizes and speed in practice
The script below signs the same message with each algorithm using OpenSSL 3.6.5.
#!/bin/sh
dir=$(mktemp -d)
cd "$dir" || exit 1
printf 'firmware-2026.10.bin digest' > msg
for alg in ML-DSA-44 ML-DSA-65 SLH-DSA-SHA2-128s SLH-DSA-SHA2-128f ED25519; do
openssl genpkey -algorithm "$alg" -out key.pem 2>/dev/null
openssl pkeyutl -sign -rawin -inkey key.pem -in msg -out sig.bin 2>/dev/null
openssl pkey -in key.pem -pubout -outform DER -out pub.der 2>/dev/null
openssl pkey -in key.pem -pubout -out pub.pem 2>/dev/null
if openssl pkeyutl -verify -rawin -pubin -inkey pub.pem -in msg -sigfile sig.bin >/dev/null 2>&1; then ok=yes; else ok=no; fi
printf '%-18s public key (SPKI DER) %5s bytes, signature %6s bytes, verifies: %s\n' "$alg" \
"$(wc -c < pub.der | tr -d ' ')" "$(wc -c < sig.bin | tr -d ' ')" "$ok"
done
cd / && rm -rf "$dir"
ML-DSA-44 public key (SPKI DER) 1334 bytes, signature 2420 bytes, verifies: yes
ML-DSA-65 public key (SPKI DER) 1974 bytes, signature 3309 bytes, verifies: yes
SLH-DSA-SHA2-128s public key (SPKI DER) 50 bytes, signature 7856 bytes, verifies: yes
SLH-DSA-SHA2-128f public key (SPKI DER) 50 bytes, signature 17088 bytes, verifies: yes
ED25519 public key (SPKI DER) 44 bytes, signature 64 bytes, verifies: yes
The profiles are mirror images. ML-DSA has kilobyte-sized public keys and signatures, and signs thousands of times per second. SLH-DSA has tiny public keys (as small as Ed25519's) but signatures of 8 to 50 KB, and its small s sets take about 137 ms per signature on this machine (the f sets trade a doubled signature size for about 20 times faster signing). Verification is fast for both. For a certificate chain or a TLS handshake, ML-DSA is workable and SLH-DSA is not; for a firmware image signed once per release and verified at every boot, SLH-DSA's cost is irrelevant and its tiny public key fits in boot ROM.
Operational details
- Hedged signing. Both standards default to mixing fresh randomness with key-derived values and allow a deterministic variant for platforms without a random number generator; verifiers cannot tell the difference.
- Contexts. Both bind a context string of up to 255 bytes into every signature, which protocols should use to separate purposes.
- Pure and prehash variants. HashML-DSA and HashSLH-DSA sign a digest with the hash's OID bound in; they are separate algorithms with separate OIDs, and FIPS 204 recommends using a key for only one of the two.
- Private key formats. ML-DSA keys can be stored as the 32-byte seed, which RFC 9881 allows in its
seedorbothencodings; interop problems arise when one side expects the expanded key. - Hardware and FIPS validation. Validated modules with ML-DSA and SLH-DSA appeared from 2024 onward; check the module's certificate for the exact parameter sets.
When to choose which
- Private PKI, internal mTLS, document and code signing: ML-DSA-65 (or 44).
- Firmware, secure boot, hardware roots of trust: SLH-DSA-128s or 192s, or the stateful LMS and XMSS that CNSA 2.0 mandates for this case if you can manage signer state.
- Long-term archives and root certificates meant to last decades: SLH-DSA, possibly alongside ML-DSA as a dual signature.
- High-volume signing (tokens, transactions, logs): ML-DSA; SLH-DSA cannot keep up.
- Bandwidth-constrained protocols: neither is small; ML-DSA-44 is the smallest standardized option today, and FN-DSA (draft FIPS 206) aims lower.
- Public WebPKI TLS: neither is accepted by browsers today; see ML-DSA vs ECDSA for the transition picture.
Migration notes
- Inventory signature uses by lifetime and volume: long-lived and rarely signed artifacts are SLH-DSA candidates; everything else ML-DSA.
- Pick library versions that implement the final standards: OpenSSL 3.5 or later (April 2025), Bouncy Castle for Java 1.79 or later (1.81 for the standardized private key encoding), Go 1.27's
crypto/mldsafor ML-DSA. Pre-standard Dilithium and SPHINCS+ outputs are not compatible. - Plan for size: increase limits for certificate, token and signature fields; ML-DSA-65 certificates are about 5.5 KB (see the companion comparison) and SLH-DSA signatures can exceed common header or record limits.
- Consider hybrids during the transition: composite ML-DSA plus ECDSA or EdDSA certificates (an IETF draft) or dual signatures let classical verifiers keep working.
- Fix the context string and variant (pure or prehash) in your protocol specification so every implementation agrees.