std.crypto.pqc.slhdsa

SLH-DSA (SPHINCS+, NIST FIPS 205) ist ein hash-basiertes Post-Quantum-Signaturverfahren. Die Sicherheit beruht ausschließlich auf der Kollisionsresistenz von SHA-256 — keine gittertheoretischen Annahmen wie bei ML-DSA.

 
Rechenzeit einplanen. SLHDSAKeyGen mit SLHParams128s braucht rund 8 Sekunden, das vollständige Beispiel unten (KeyGen, Sign, Verify) rund 75 Sekunden. Einzelheiten und der Vergleich mit SLHParamsMini stehen unter Laufzeiten.

Für Versuche und Tests eignet sich SLHParamsMini. Dieser Parametersatz ist allerdings nicht FIPS-konform und gehört nicht in Produktivcode.

===== Laufzeiten =====

Gemessen mit lyxc 1.0.21A auf einem Arbeitsplatzrechner (ThinkPad T480, Linux 6.8). Die absoluten Werte hängen an der Maschine — das Verhältnis der Parametersätze zueinander nicht.

Parametersatz KeyGen KeyGen + Sign + Verify Signaturlänge
SLHParams128s 8,3 s 75,0 s 7856 Byte
SLHParamsMini < 0,1 s 0,21 s 1392 Byte

Der Löwenanteil geht ins Signieren, nicht in die Schlüsselerzeugung: bei SLHParams128s entfallen rund 8 Sekunden auf KeyGen und rund 67 Sekunden auf Sign und Verify zusammen. Wer nur den Ablauf ausprobieren will, nimmt SLHParamsMini — derselbe Code, derselbe Ausgang, in einer Fünftelsekunde statt in gut einer Minute.

Es hängt nicht, es rechnet. Die Zeit geht in die Hash-Bäume; die Speicheranforderung ist seit dem Kleinspeicher-Pool in alloc nicht mehr der Engpass (#1258, #1319).

Fassung KeyGen SLHParams128s
1.0.15G 21 s
1.0.16F 11 s
vor dem Pool-Fix 86 s
1.0.17K bis 1.0.20A 8,3–8,7 s

Klassifikation: Asymmetrisches, hash-basiertes Signaturverfahren. Zustandslos (stateless) — keine Signaturzähler nötig wie bei XMSS/LMS.

import std.crypto.pqc.slhdsa;

std.crypto.pqc · std.crypto.pqc.pqc (High-Level API) · std.crypto


Parametersätze

Parametersatz n h Quantensicherheit SK PK Signatur Empfehlung
SLH-DSA-SHA2-128s 16 63 ~128-Bit 64 B 32 B 7856 B Standardwahl
SLH-DSA-SHA2-256s 32 64 ~256-Bit 128 B 64 B 29792 B Höchste Sicherheit
Mini (nicht FIPS) 16 4 64 B 32 B 1392 B Nur für Tests

Vergleich mit ML-DSA: SLH-DSA erzeugt größere Signaturen (7856 B vs. 3293 B für ~128-Bit), hat aber kleinere Schlüssel (PK nur 32 B). Vorteil: rein hash-basierte Sicherheitsannahmen, breit konservativ.


Konstanten

Konstante Wert Bedeutung
SLH_128S_SK 64 SK-Größe SLH-DSA-128s in Bytes
SLH_128S_PK 32 PK-Größe SLH-DSA-128s in Bytes
SLH_128S_SIG 7856 Signaturlänge SLH-DSA-128s in Bytes
SLH_256S_SK 128 SK-Größe SLH-DSA-256s in Bytes
SLH_256S_PK 64 PK-Größe SLH-DSA-256s in Bytes
SLH_256S_SIG 29792 Signaturlänge SLH-DSA-256s in Bytes
SLH_MINI_SIG 1392 Signaturlänge Mini-Params (nicht FIPS)
SLH_PS 96 Größe des Parameter-Blocks in Bytes

ADRS-Typ-Codes (intern, für eigene ADRS-Konstruktionen): SLH_WOTS=0, SLH_WOTS_PK=1, SLH_TREE=2, SLH_FORS_TREE=3, SLH_FORS_ROOTS=4, SLH_WOTS_PRF=5, SLH_FORS_PRF=6


Funktionen

Parameter-Initialisierung (muss vor KeyGen/Sign/Verify aufgerufen werden):

Funktion Beschreibung
SLHParams128s(ps) Füllt 96-Byte-Parameterblock ps für SLH-DSA-SHA2-128s
SLHParams256s(ps) Füllt 96-Byte-Parameterblock ps für SLH-DSA-SHA2-256s
SLHParamsMini(ps) Füllt Parameterblock für Mini-Satz (n=16, h=4 — nur Tests, nicht FIPS-konform)

Schlüssel und Signatur:

Funktion Beschreibung
SLHDSAKeyGen(ps, skseed, skprf, pkseed, sk, pk) Erzeugt Schlüsselpaar aus drei Seeds (je n Bytes). sk: SLH_xxx_SK Bytes; pk: SLH_xxx_PK Bytes.
SLHDSASign(ps, sk, msg, mlen, optrand, sig): int64 Signiert msg (mlen Bytes). optrand: 0 für deterministische Signatur (empfohlen). sig: caller-alloziert mit SLH_xxx_SIG Bytes. Gibt tatsächliche Signaturlänge zurück.
SLHDSAVerify(ps, pk, msg, mlen, sig): int64 Verifiziert Signatur. Gibt 1 bei gültig, 0 bei ungültig.

Verwendungsbeispiel

import std.crypto.pqc.slhdsa;
import std.crypto.rand;
import std.alloc;

fn main(): int64 {
  // Parameter-Block initialisieren (SLH-DSA-128s)
  var ps: int64 := alloc(SLH_PS);
  SLHParams128s(ps);

  // Seeds: skseed[16], skprf[16], pkseed[16] (n=16 für 128s)
  var seeds: int64 := alloc(48);
  RandBytesExact(seeds, 48);

  // Schlüsselpaar erzeugen
  var sk: int64 := alloc(SLH_128S_SK);
  var pk: int64 := alloc(SLH_128S_PK);
  SLHDSAKeyGen(ps, seeds, seeds + 16, seeds + 32, sk, pk);

  // Signieren
  var msg: pchar := "Hello, SLH-DSA!"c;
  var m_len: int64 := 15;
  var sig: int64 := alloc(SLH_128S_SIG);
  var sig_len: int64 := SLHDSASign(ps, sk, msg as int64, m_len, 0, sig);

  // Verifizieren
  var ok: int64 := SLHDSAVerify(ps, pk, msg as int64, m_len, sig);
  // ok == 1 wenn gültig

  free(ps, SLH_PS); free(seeds, 48);
  free(sk, SLH_128S_SK); free(pk, SLH_128S_PK);
  free(sig, SLH_128S_SIG);
  return 0;
}

Hinweis: Für den einfachsten Einstieg → std.crypto.pqc.pqc verwenden (kein manuelles Parameter-Block-Management).


Sicherheitseigenschaften

Eigenschaft Ergebnis
NIST-Standard FIPS 205 (2024) — offiziell standardisiert
Sicherheitsannahme Nur SHA-256-Kollisionsresistenz (konservativste aller PQC-Optionen)
Quantensicherheit ~128-Bit (128s) / ~256-Bit (256s)
Signatur-Overhead 7856 B (128s) — größer als ML-DSA, aber kleinster Public Key (32 B)
Zustandslos Ja — keine Signaturzähler nötig (anders als XMSS/LMS)

Letzte Aktualisierung: 2026-08-15 — Laufzeiten mit lyxc 1.0.20A neu gemessen, je Parametersatz getrennt nach KeyGen und Gesamtlauf (#1319)

Codebeispiele geprüft: gegen lyxc 1.2.5C übersetzt (Prüflauf 2026-09-08 über die gesamte Doku: 574 Vollprogramme, 0 echte Fehler; zusätzlich 5159 Aufrufe gegen die pub fn-Signaturen in aurum/std gehalten, 0 Abweichungen).