Es lohnt sich, bei den Daten, die Ihre Anwendung heute verarbeitet, eine Frage zu stellen: Wie lange bleiben sie sensibel? Eine Krankenakte, ein Vertrag, eine Gehaltsabrechnung, ein Satz Zugangsdaten. Wenn die Antwort mehr als ein paar Jahre lautet, dann ist die eigentliche Bedrohung nicht ein Angreifer, der Ihre Verschlüsselung heute bricht. Es ist ein Angreifer, der den Datenverkehr schon jetzt aufzeichnet, speichert und später entschlüsselt, sobald die Werkzeuge dafür so weit sind. Diese Praxis hat einen Namen, harvest now, decrypt later (jetzt sammeln, später entschlüsseln), und dafür muss heute niemand einen Quantencomputer bauen. Es reicht, wenn jemand glaubt, dass es irgendwann einer tun wird.
Deshalb haben sich die Standards zuerst bewegt. NIST hat die Algorithmen 2024 veröffentlicht, Browser und CDNs haben 2025 den hybriden Schlüsselaustausch aktiviert, und die Fristen für die Ablösung des Schlüsselaustauschs mit RSA und elliptischen Kurven stehen inzwischen in den öffentlichen Richtlinien. sgcWebSockets 2026.10 bringt das gesamte Paket nach Delphi, geschrieben in Object Pascal innerhalb des sgcCrypto-Pakets, ohne externe Bibliothek, die installiert oder mit ausgeliefert werden müsste.
Drei Algorithmen, ein Paket
Die drei NIST-Standards erfüllen unterschiedliche Aufgaben, und normalerweise werden Sie die ersten beiden verwenden:
- ML-KEM (FIPS 203) handelt ein gemeinsames Geheimnis aus. Es ersetzt die Aufgabe, die heute Diffie-Hellman übernimmt.
- ML-DSA (FIPS 204) signiert. Es ersetzt RSA- und ECDSA-Signaturen.
- SLH-DSA (FIPS 205) signiert ebenfalls, beruht aber ausschließlich auf Hashfunktionen, für den Fall, dass Sie die konservativste verfügbare Annahme wollen und die Signaturgröße in Kauf nehmen können.
Einen Schlüssel mit ML-KEM aushandeln
Ein Schlüsselkapselungsmechanismus ist einfacher zu benutzen als Diffie-Hellman. Der Absender nimmt den öffentlichen Schlüssel des Empfängers und erzeugt zwei Dinge: ein frisches gemeinsames Geheimnis und einen Chiffretext, der es überträgt. Der Empfänger verwandelt den Chiffretext wieder in dasselbe Geheimnis.
uses
sgcCrypto_MLKEM;
var
oPublicKey, oPrivateKey, oCiphertext, oSecret, oSame: TBytes;
begin
sgcMLKEM_GenerateKeyPair(mlkem768, oPublicKey, oPrivateKey);
// the sender, who only ever sees the public key
sgcMLKEM_Encapsulate(mlkem768, oPublicKey, oCiphertext, oSecret);
// the recipient, who holds the private key, gets the same 32 bytes
oSame := sgcMLKEM_Decapsulate(mlkem768, oPrivateKey, oCiphertext);
end;
Die Parametersätze sind mlkem512, mlkem768 und mlkem1024. Die von FIPS 203 geforderten Eingabeprüfungen laufen vor allem anderen, sodass ein fehlerhaft geformter öffentlicher Schlüssel eine Exception auslöst, statt still ein Geheimnis zu erzeugen, und ein Chiffretext, der sich nicht entschlüsseln lässt, ein pseudozufälliges Geheimnis liefert statt eines Fehlers, was genau die implizite Zurückweisung ist, die der Standard verlangt.
X-Wing, wenn Sie sich nicht festlegen wollen
Einen neuen Algorithmus einzusetzen bedeutet, ihm zu vertrauen. Hybride Konstruktionen nehmen Ihnen diese Entscheidung ab: Sie kombinieren einen klassischen Algorithmus mit einem post-quantenfähigen, sodass das Ergebnis sicher bleibt, solange eine der beiden Hälften hält. X-Wing kombiniert X25519 mit ML-KEM-768 und stellt ein einziges Schlüsselpaar bereit.
uses
sgcCrypto_MLKEM_Hybrid;
var
oPublicKey, oPrivateKey, oCiphertext, oSecret: TBytes;
begin
sgcXWing_GenerateKeyPair(oPublicKey, oPrivateKey);
sgcXWing_Encapsulate(oPublicKey, oCiphertext, oSecret);
oSecret := sgcXWing_Decapsulate(oPrivateKey, oCiphertext);
end;
Signieren mit ML-DSA
Das Signieren nimmt den Parametersatz, den privaten Schlüssel, die Nachricht und eine Kontextzeichenfolge entgegen, die normalerweise leer ist:
uses
sgcCrypto_MLDSA;
var
oSeed, oPublicKey, oPrivateKey, oSignature: TBytes;
begin
sgcMLDSA_GenerateKeyPairAndSeed(mldsa65, oSeed, oPublicKey, oPrivateKey);
oSignature := sgcMLDSA_Sign(mldsa65, oPrivateKey, aMessage, nil);
if sgcMLDSA_Verify(mldsa65, oPublicKey, aMessage, oSignature, nil) then
ShowMessage('signature is valid');
end;
Beachten Sie den Seed. Ein privater ML-DSA-Schlüssel lässt sich als die 32 Bytes speichern, aus denen er erzeugt wurde, als der expandierte Schlüssel, oder als beides, und die Bibliothek liest und schreibt alle drei Formen. Der Seed ist die Form, die Sie in einer Konfigurationsdatei wollen: Er ist klein, und der expandierte Schlüssel wird deterministisch aus ihm abgeleitet.
Schlüssel, die reisen
Ein Algorithmus, mit dem niemand Schlüssel austauschen kann, nützt wenig, deshalb folgen die Kodierungen den veröffentlichten Profilen: SubjectPublicKeyInfo und PKCS#8, in DER oder PEM, nach RFC 9935 für ML-KEM, RFC 9881 für ML-DSA und RFC 9909 für SLH-DSA.
var
vPublicPEM, vPrivatePEM: string;
begin
vPublicPEM := sgcMLDSA_ExportPublicKeyPEM(mldsa65, oPublicKey);
vPrivatePEM := sgcMLDSA_ExportPrivateKeyPEM(mldsa65, oSeed, nil);
end;
Das sind gewöhnliche BEGIN PUBLIC KEY- und BEGIN PRIVATE KEY-Blöcke, die andere Implementierungen lesen können. Ein privater Schlüssel wird beim Import geprüft: Die öffentliche Hälfte wird erneut abgeleitet und verglichen, sodass ein Schlüssel, der nicht zu seinem Zertifikat gehört, sofort zurückgewiesen wird, statt Signaturen zu erzeugen, die niemand verifizieren kann.
Zertifikate und eine post-quantenfähige CA
Zertifikate und Zertifikatsanfragen können post-quantenfähige Schlüssel tragen, und auch eine Zertifizierungsstelle kann einen solchen besitzen, sodass eine ganze Kette post-quantenfähig sein kann:
var
vKey: TsgcX509SignKey;
vOptions: TsgcX509Options;
oCertDER: TBytes;
begin
vKey := sgcX509_MLDSAKey(mldsa65, oPrivateKey, oPublicKey);
vOptions.Subject.CommonName := 'My Post-Quantum CA';
vOptions.KeyUsage := [kuKeyCertSign, kuCRLSign];
oCertDER := sgcX509_CreateSelfSignedEx(vKey, vOptions);
end;
Die Regeln zur Schlüsselverwendung aus den Profilen werden durchgesetzt, bevor irgendetwas signiert wird, sodass ein post-quantenfähiger Schlüssel, dem eine Schlüsselverschlüsselung abverlangt wird, eine Exception auslöst, statt ein Zertifikat zu erzeugen, das sein eigenes Profil verletzt. Die Kettenvalidierung setzt inzwischen auch die Pfadlänge und die Namensbeschränkungen durch, die die ausstellenden Zertifikate deklarieren.
Wo es bereits eingebunden ist
An zwei Stellen in der Bibliothek wird das alles bereits für Sie erledigt, ohne dass Sie Kryptografie schreiben müssen:
- TLS. Die native TLS-1.3-Engine handelt die hybriden Schlüsselaustauschgruppen aus RFC 10024 aus,
X25519MLKEM768,SecP256r1MLKEM768undSecP384r1MLKEM1024, und die Standardliste beginnt bereits mit einer hybriden Gruppe. Siehe Delphi TLS 1.3 ohne OpenSSL-DLLs. - JWT. Tokens lassen sich mit ML-DSA nach RFC 9964 signieren und verifizieren. Siehe Ein JWT mit ML-DSA in Delphi signieren.
Woher wir wissen, dass es korrekt ist
Die Implementierung eines Standards ist nur eine Behauptung, bis etwas sie überprüft. Alle drei Algorithmen werden gegen die Known-Answer-Vektoren von NIST validiert, und diese Vektoren werden mit der Bibliothek als lauffähiges Testset ausgeliefert, nicht als Satz in einem Datenblatt. Der ML-DSA-Signierer ist die deterministische Variante, sodass derselbe Schlüssel und dieselbe Nachricht immer dieselbe Signatur ergeben, was die in den RFCs veröffentlichten Beispiele byte-für-byte reproduzierbar macht.
Was Sie verwenden sollten
Für den Schlüsselaustausch verwenden Sie ein Hybrid: X-Wing allein, oder die hybriden TLS-Gruppen, wenn der Datenverkehr TLS ist. Sie geben so gut wie nichts auf und sind abgesichert, welche Annahme sich auch als falsch erweisen sollte. Für Signaturen ist ML-DSA-65 die sinnvolle Standardwahl, mit ML-DSA-44, wenn die Größe zählt, und ML-DSA-87, wenn nicht. Greifen Sie zu SLH-DSA, wenn die Signatur viele Jahre später von etwas verifiziert wird, das Sie nicht aktualisieren können, etwa Firmware, und die Signaturgröße vertretbar ist.
Aktualisieren
All das steckt im sgcCrypto-Paket und fügt keine Abhängigkeit hinzu: kein OpenSSL, keine DLL, nichts, was auf dem Rechner installiert werden müsste, der Ihre Anwendung ausführt. Bestehender Code bleibt unangetastet, bis Sie ihn aufrufen.
Weiterlesen
- Delphi TLS 1.3 ohne OpenSSL-DLLs
- Ein JWT mit ML-DSA in Delphi signieren
- sgcWebSockets 2026.10, alles andere aus dieser Version
Ansehen
Dazu gibt es ein kurzes Video auf dem eSeGeCe Kanal.
Fragen, Feedback oder Hilfe bei der Migration? Nehmen Sie Kontakt auf — Sie erhalten eine Antwort von den Leuten, die den Code geschrieben haben.
