ML-DSA vs. SLH-DSA ist die wichtigste Entscheidung zwischen den standardisierten Post-Quanten-Signaturen des NIST; beide wurden am 13. August 2024 veröffentlicht. ML-DSA (FIPS 204, hervorgegangen aus CRYSTALS-Dilithium) beruht auf strukturierten Gittern, SLH-DSA (FIPS 205, hervorgegangen aus SPHINCS+) nur auf der Sicherheit seiner Hashfunktion. Größe und Geschwindigkeit unterscheiden sich so stark, dass die meisten Systeme ML-DSA verwenden werden und SLH-DSA dort, wo seine konservativen Annahmen die Kosten rechtfertigen.
Auf einen Blick
| ML-DSA (FIPS 204) | SLH-DSA (FIPS 205) | |
|---|---|---|
| Annahme | Gitterprobleme Module-LWE und Module-SIS | Nur Eigenschaften von SHA-2 oder SHAKE |
| Parametersätze | ML-DSA-44, -65, -87 | 12 Sätze: SHA2 oder SHAKE × 128/192/256 × s (klein) oder f (schnell) |
| Sicherheitskategorien | 2, 3, 5 | 1, 3, 5 |
| Öffentlicher Schlüssel | 1.312 / 1.952 / 2.592 Byte | 32 / 48 / 64 Byte |
| Signatur | 2.420 / 3.309 / 4.627 Byte | 7.856 (128s) bis 49.856 Byte (256f) |
| Privater Schlüssel | 2.560–4.896 Byte expandiert oder ein 32-Byte-Seed | 64 / 96 / 128 Byte |
| Signieren pro Sekunde (OpenSSL 3.6.5) | etwa 3.900 (44), 2.400 (65), 2.050 (87) | etwa 7 (SHA2-128s), 144 (SHA2-128f), 3,5 (SHA2-192s) |
| Prüfen pro Sekunde | etwa 20.800 (44), 13.600 (65), 8.500 (87) | etwa 7.400 (SHA2-128s), 2.400 (SHA2-128f) |
| Schlüsselerzeugung pro Sekunde | etwa 22.000 (44) | etwa 55 (128s), 3.400 (128f) |
| Zufall beim Signieren | Standardmäßig in der Hedged-Variante, deterministische Variante erlaubt | Standardmäßig in der Hedged-Variante, deterministische Variante erlaubt |
| Kontext-String | Bis zu 255 Byte | Bis zu 255 Byte |
| Pre-Hash-Variante | 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 …) |
Die Geschwindigkeiten wurden mit openssl speed auf einem Kern eines Apple M4 Max gemessen; ML-DSA ist in OpenSSL portabler C-Code, und optimierte Implementierungen signieren um ein Mehrfaches schneller.
Sicherheitsannahmen
ML-DSA ist ein gitterbasiertes Verfahren nach dem Prinzip Fiat–Shamir with Aborts. Seine Sicherheit beruht auf Module Learning With Errors und Module Short Integer Solution. Diese Probleme werden seit etwa zwei Jahrzehnten untersucht und haben klassischen wie Quantenangriffen standgehalten, ihre konkreten Sicherheitsschätzungen verschieben sich aber weiter, je besser die Techniken der Gitterreduktion werden. NIST hat jeden Parametersatz mit Spielraum gegenüber diesen Schätzungen gewählt.
SLH-DSA baut Signaturen aus hashbasierten Einmal- und Few-Time-Signaturen auf, die in einem Hypertree angeordnet sind. Solange SHA-256 oder SHAKE256 ihre Urbildresistenz und verwandte Eigenschaften behalten, bleibt SLH-DSA sicher; es gibt keine algebraische Struktur, die sich angreifen ließe. Damit ist es die konservativste Signatur, die NIST standardisiert hat, und die naheliegende Absicherung für den Fall, dass bei Gittern je ein Durchbruch gelingt. Anders als die zustandsbehafteten hashbasierten Verfahren LMS und XMSS braucht es keinen Zustand: Jeder Schlüssel kann bis zu 2⁶⁴ Nachrichten signieren.
Größen und Geschwindigkeit in der Praxis
Das folgende Skript signiert mit OpenSSL 3.6.5 dieselbe Nachricht mit jedem der Algorithmen.
#!/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
Die Profile sind spiegelbildlich. ML-DSA hat öffentliche Schlüssel und Signaturen im Kilobytebereich und schafft Tausende Signaturen pro Sekunde. SLH-DSA hat winzige öffentliche Schlüssel (so klein wie bei Ed25519), aber Signaturen von 8 bis 50 KB, und seine kleinen Sätze s brauchen auf diesem Rechner etwa 137 ms pro Signatur (die Sätze f nehmen doppelt so große Signaturen in Kauf und signieren dafür etwa 20-mal schneller). Die Prüfung ist bei beiden schnell. Für eine Zertifikatskette oder einen TLS-Handshake ist ML-DSA praktikabel und SLH-DSA nicht; für ein Firmware-Image, das einmal pro Release signiert und bei jedem Bootvorgang geprüft wird, spielen die Kosten von SLH-DSA keine Rolle, und sein winziger öffentlicher Schlüssel passt ins Boot-ROM.
Details für den Betrieb
- Signieren in der Hedged-Variante. Beide Standards mischen standardmäßig frischen Zufall mit aus dem Schlüssel abgeleiteten Werten und erlauben eine deterministische Variante für Plattformen ohne Zufallszahlengenerator; Verifizierer können den Unterschied nicht erkennen.
- Kontexte. Beide binden einen Kontext-String von bis zu 255 Byte in jede Signatur ein; Protokolle sollten ihn nutzen, um Verwendungszwecke voneinander zu trennen.
- Reine und Pre-Hash-Varianten. HashML-DSA und HashSLH-DSA signieren einen Digest und binden dabei die OID der Hashfunktion ein; es sind eigene Algorithmen mit eigenen OIDs, und FIPS 204 empfiehlt, einen Schlüssel nur für eine der beiden Varianten zu verwenden.
- Formate privater Schlüssel. ML-DSA-Schlüssel lassen sich als 32-Byte-Seed speichern, was RFC 9881 in seinen Kodierungen
seedundbotherlaubt; Interoperabilitätsprobleme entstehen, wenn eine Seite den expandierten Schlüssel erwartet. - Hardware und FIPS-Validierung. Validierte Module mit ML-DSA und SLH-DSA gibt es seit 2024; prüfe im Zertifikat des Moduls, welche Parametersätze genau abgedeckt sind.
Wann welches Verfahren passt
- Private PKI, internes mTLS, Dokument- und Codesignatur: ML-DSA-65 (oder 44).
- Firmware, Secure Boot, Hardware-Roots-of-Trust: SLH-DSA-128s oder 192s, oder die zustandsbehafteten Verfahren LMS und XMSS, die CNSA 2.0 für diesen Fall vorschreibt, sofern du den Zustand des Signierers verwalten kannst.
- Langzeitarchive und Root-Zertifikate, die Jahrzehnte halten sollen: SLH-DSA, eventuell zusammen mit ML-DSA als Doppelsignatur.
- Signieren in großen Mengen (Tokens, Transaktionen, Logs): ML-DSA; SLH-DSA kommt da nicht mit.
- Protokolle mit knapper Bandbreite: Keines der beiden ist klein; ML-DSA-44 ist heute die kleinste standardisierte Option, und FN-DSA (FIPS 206 im Entwurf) soll noch kompakter ausfallen.
- Öffentliches TLS in der Web-PKI: Browser akzeptieren heute keines der beiden; den Stand des Übergangs zeigt ML-DSA vs. ECDSA.
Hinweise zur Migration
- Erfasse Signaturanwendungen nach Lebensdauer und Volumen: Langlebige, selten signierte Artefakte sind Kandidaten für SLH-DSA, alles andere für ML-DSA.
- Wähle Bibliotheksversionen, die die finalen Standards umsetzen: OpenSSL ab 3.5 (April 2025), Bouncy Castle für Java ab 1.79 (ab 1.81 für die standardisierte Kodierung privater Schlüssel),
crypto/mldsaaus Go 1.27 für ML-DSA. Ausgaben von Dilithium und SPHINCS+ aus der Zeit vor der Standardisierung sind nicht kompatibel. - Plane die Größe ein: Erhöhe die Limits für Zertifikats-, Token- und Signaturfelder; ML-DSA-65-Zertifikate sind etwa 5,5 KB groß (siehe den zugehörigen Vergleich), und SLH-DSA-Signaturen können übliche Größengrenzen für Header oder Records überschreiten.
- Erwäge hybride Verfahren für den Übergang: Composite-Zertifikate mit ML-DSA plus ECDSA oder EdDSA (ein IETF-Entwurf) oder Doppelsignaturen sorgen dafür, dass klassische Verifizierer weiter funktionieren.
- Lege den Kontext-String und die Variante fest (rein oder Pre-Hash): Schreib beides in deine Protokollspezifikation, damit alle Implementierungen übereinstimmen.