====== PlayGround ====== ====== WvdS.System.Security.Cryptography.Extensions ====== Post-Quantum Cryptography Extensions für .NET - Drop-In Erweiterung der Microsoft System.Security.Cryptography Klassen. ===== Übersicht ===== Diese Bibliothek ermöglicht schrittweises Refactoring bestehender .NET-Anwendungen auf Post-Quantum Kryptographie (PQC) ohne umfangreiche Code-Änderungen. Assembly: ''WvdS.System.Security.Cryptography.Extensions.dll'' ^ Namespace ^ Beschreibung ^ | ''WvdS.System.Security.Cryptography'' | Basis-Klassen, Enums, Config | | ''WvdS.System.Security.Cryptography.X509Certificates'' | X.509 Extensions | | ''WvdS.System.Security.Cryptography.Interop'' | OpenSSL 3.6 P/Invoke | ===== Architektur ===== {{ wvds-crypto-architecture.svg?720|WvdS Crypto Extensions Architektur }} ==== Architektur-Erklärung ==== - **Bestehende Applikation** ruft Extension Methods mit ''CryptoMode'' Parameter auf - **Extension Methods** entscheiden basierend auf Mode: * ''Classic'' → delegiert an Microsoft .NET * ''Hybrid'' → nutzt .NET + OpenSSL Interop * ''PostQuantum'' → nutzt nur OpenSSL Interop - **OpenSSL 3.6 Interop** (P/Invoke) kommuniziert mit externer libcrypto - **OpenSSL 3.6 (libcrypto)** führt PQ-Operationen aus (ML-DSA, ML-KEM, SLH-DSA) **Wichtig:** Es gibt keine direkte Verbindung zwischen Extension Methods und libcrypto. Alle PQ-Operationen laufen über den Interop-Layer! ===== Namespace-Struktur ===== WvdS.System.Security.Cryptography │ ├── CryptoMode.cs │ └── enum CryptoMode │ ├── Classic // Nur RSA/ECDSA via .NET │ ├── Hybrid // RSA/ECDSA + ML-DSA parallel │ └── PostQuantum // Nur ML-DSA via OpenSSL │ ├── CryptoConfig.cs │ └── static class CryptoConfig │ ├── DefaultMode { get; set; } │ └── OpenSslPath { get; set; } │ ├── Interop/ │ └── OpenSslInterop.cs │ └── internal static class OpenSslInterop │ ├── Initialize() │ ├── GenerateMlDsaKeyPair() │ ├── SignMlDsa() │ ├── VerifyMlDsa() │ └── CreatePqCertificate() │ └── X509Certificates/ │ ├── CertificateRequestExtensions.cs │ └── static class CertificateRequestExtensions │ ├── CreateSelfSigned(this, notBefore, notAfter, mode?) │ └── Create(this, issuer, notBefore, notAfter, serial, mode?) │ ├── X509Certificate2Extensions.cs │ └── static class X509Certificate2Extensions │ ├── CopyWithPrivateKey(this, key, mode?) │ ├── HasPqSignature(this) │ ├── GetCryptoMode(this) │ └── GetSignatureAlgorithmDescription(this) │ └── X509ChainExtensions.cs └── static class X509ChainExtensions ├── Build(this, cert, mode?) ├── IsFullyPqProtected(this) └── GetChainCryptoModes(this) ===== CryptoMode ===== ^ Mode ^ Beschreibung ^ Backend ^ Kompatibilität ^ | ''Classic'' | Nur klassische Algorithmen (RSA, ECDSA, SHA-2) | Microsoft .NET | Überall | | ''Hybrid'' | Klassisch + Post-Quantum parallel | .NET + OpenSSL 3.6 | Klassische Software kann Zertifikat lesen, PQ-Software nutzt zusätzlich ML-DSA | | ''PostQuantum'' | Nur Post-Quantum Algorithmen (ML-DSA, ML-KEM) | OpenSSL 3.6 | Nur PQ-fähige Software (z.B. ISAPI DLL) | namespace WvdS.System.Security.Cryptography; /// /// Kryptographie-Modus für alle Operationen /// public enum CryptoMode { /// /// Nur klassische Algorithmen (RSA, ECDSA) /// → System.Security.Cryptography /// Classic = 0, /// /// Klassisch + Post-Quantum kombiniert /// → System.Security.Cryptography + OpenSSL 3.6 /// → Zertifikat funktioniert auch ohne PQ-Support /// Hybrid = 1, /// /// Nur Post-Quantum Algorithmen (ML-DSA, ML-KEM) /// → OpenSSL 3.6 /// → Benötigt PQ-fähige Software /// PostQuantum = 2 } ===== Method Resolution (C# Verhalten) ===== **Wichtig:** Instance Methods haben IMMER Vorrang vor Extension Methods! Deshalb verwenden unsere Extensions einen **zusätzlichen Parameter** (''CryptoMode? mode''), damit die Signatur unterschiedlich ist. ^ Aufruf ^ Parameter ^ Ziel ^ | ''request.CreateSelfSigned(a, b)'' | 2 | → Original .NET (Instance Method) | | ''request.CreateSelfSigned(a, b, null)'' | 3 | → WvdS Extension (CryptoConfig.DefaultMode) | | ''request.CreateSelfSigned(a, b, CryptoMode.Hybrid)'' | 3 | → WvdS Extension (OpenSSL) | ===== Extension Methods ===== ==== CertificateRequestExtensions ==== namespace WvdS.System.Security.Cryptography.X509Certificates; public static class CertificateRequestExtensions { /// /// Erstellt ein selbstsigniertes Zertifikat (Root CA) /// /// CertificateRequest /// Gültig ab /// Gültig bis /// CryptoMode (null = CryptoConfig.DefaultMode) public static X509Certificate2 CreateSelfSigned( this CertificateRequest request, DateTimeOffset notBefore, DateTimeOffset notAfter, CryptoMode? mode) { var effectiveMode = mode ?? CryptoConfig.DefaultMode; return effectiveMode switch { CryptoMode.Classic => request.CreateSelfSigned(notBefore, notAfter), CryptoMode.Hybrid => CreateSelfSignedHybrid(request, notBefore, notAfter), CryptoMode.PostQuantum => CreateSelfSignedPostQuantum(request, notBefore, notAfter), _ => request.CreateSelfSigned(notBefore, notAfter) }; } /// /// Erstellt ein von einer CA signiertes Zertifikat /// public static X509Certificate2 Create( this CertificateRequest request, X509Certificate2 issuerCertificate, DateTimeOffset notBefore, DateTimeOffset notAfter, byte[] serialNumber, CryptoMode? mode) { var effectiveMode = mode ?? CryptoConfig.DefaultMode; return effectiveMode switch { CryptoMode.Classic => request.Create(issuerCertificate, notBefore, notAfter, serialNumber), CryptoMode.Hybrid => CreateHybrid(request, issuerCertificate, notBefore, notAfter, serialNumber), CryptoMode.PostQuantum => CreatePostQuantum(request, issuerCertificate, notBefore, notAfter, serialNumber), _ => request.Create(issuerCertificate, notBefore, notAfter, serialNumber) }; } } ==== X509Certificate2Extensions ==== namespace WvdS.System.Security.Cryptography.X509Certificates; public static class X509Certificate2Extensions { /// /// Kopiert Zertifikat mit Private Key /// public static X509Certificate2 CopyWithPrivateKey( this X509Certificate2 certificate, RSA privateKey, CryptoMode? mode) { var effectiveMode = mode ?? CryptoConfig.DefaultMode; return effectiveMode switch { CryptoMode.Classic => certificate.CopyWithPrivateKey(privateKey), CryptoMode.Hybrid => CopyWithPrivateKeyHybrid(certificate, privateKey), CryptoMode.PostQuantum => CopyWithPrivateKeyPostQuantum(certificate, privateKey), _ => certificate.CopyWithPrivateKey(privateKey) }; } /// /// Prüft ob das Zertifikat eine PQ-Signatur Extension hat /// public static bool HasPqSignature(this X509Certificate2 certificate) { return certificate.Extensions[PqSignatureOid] != null; } /// /// Ermittelt den CryptoMode des Zertifikats /// public static CryptoMode GetCryptoMode(this X509Certificate2 certificate) { if (IsPqOnlyAlgorithm(certificate.SignatureAlgorithm.Value)) return CryptoMode.PostQuantum; if (certificate.HasPqSignature()) return CryptoMode.Hybrid; return CryptoMode.Classic; } /// /// Gibt den Signatur-Algorithmus als lesbaren String zurück /// public static string GetSignatureAlgorithmDescription(this X509Certificate2 certificate) { var classic = certificate.SignatureAlgorithm.FriendlyName ?? "Unknown"; return certificate.GetCryptoMode() switch { CryptoMode.PostQuantum => "ML-DSA-65 (Post-Quantum)", CryptoMode.Hybrid => $"{classic} + ML-DSA-65 (Hybrid)", _ => classic }; } } ==== X509ChainExtensions ==== namespace WvdS.System.Security.Cryptography.X509Certificates; public static class X509ChainExtensions { /// /// Baut und validiert die Certificate Chain /// public static bool Build( this X509Chain chain, X509Certificate2 certificate, CryptoMode? mode) { var effectiveMode = mode ?? CryptoConfig.DefaultMode; return effectiveMode switch { CryptoMode.Classic => chain.Build(certificate), CryptoMode.Hybrid => BuildHybrid(chain, certificate), CryptoMode.PostQuantum => BuildPostQuantum(chain, certificate), _ => chain.Build(certificate) }; } /// /// Prüft ob die gesamte Chain PQ-geschützt ist /// public static bool IsFullyPqProtected(this X509Chain chain) { foreach (var element in chain.ChainElements) { if (element.Certificate.GetCryptoMode() == CryptoMode.Classic) return false; } return true; } /// /// Gibt die CryptoModes aller Zertifikate in der Chain zurück /// public static CryptoMode[] GetChainCryptoModes(this X509Chain chain) { var modes = new CryptoMode[chain.ChainElements.Count]; for (int i = 0; i < chain.ChainElements.Count; i++) { modes[i] = chain.ChainElements[i].Certificate.GetCryptoMode(); } return modes; } } ===== Refactoring-Strategie ===== ==== Phase 1: Vorbereitung (keine Änderung am Verhalten) ==== // Usings hinzufügen using WvdS.System.Security.Cryptography; using WvdS.System.Security.Cryptography.X509Certificates; // Bestehender Code - KEINE Änderung var cert = request.CreateSelfSigned(notBefore, notAfter); // → Original .NET ==== Phase 2: Explizite Migration (opt-in pro Aufruf) ==== // Einzelne Aufrufe auf Extension umstellen var cert = request.CreateSelfSigned(notBefore, notAfter, CryptoMode.Hybrid); // → OpenSSL // Oder mit null für Config-Default var cert = request.CreateSelfSigned(notBefore, notAfter, null); // → CryptoConfig.DefaultMode ==== Phase 3: Globale Umstellung ==== // Am Programmstart CryptoConfig.DefaultMode = CryptoMode.Hybrid; // Alle Aufrufe mit null nutzen jetzt Hybrid var cert = request.CreateSelfSigned(notBefore, notAfter, null); // → Hybrid ==== Search & Replace Pattern ==== ^ Suchen ^ Ersetzen ^ | ''.CreateSelfSigned(notBefore, notAfter)'' | ''.CreateSelfSigned(notBefore, notAfter, null)'' | | ''.Create(issuerCertificate, notBefore, notAfter, serialNumber)'' | ''.Create(issuerCertificate, notBefore, notAfter, serialNumber, null)'' | | ''.CopyWithPrivateKey(privateKey)'' | ''.CopyWithPrivateKey(privateKey, null)'' | | ''chain.Build(certificate)'' | ''chain.Build(certificate, null)'' | ===== OIDs ===== ==== PQ Signatur Extension ==== ^ OID ^ Beschreibung ^ | ''1.3.6.1.4.1.XXXXX.1.1'' | WvdS PQ-Signatur Extension (Hybrid-Zertifikate) | **TODO:** Eigene OID bei IANA registrieren! ==== ML-DSA Algorithmen (NIST FIPS 204) ==== ^ OID ^ Algorithmus ^ Security Level ^ | ''2.16.840.1.101.3.4.3.17'' | ML-DSA-44 | NIST Level 2 | | ''2.16.840.1.101.3.4.3.18'' | ML-DSA-65 | NIST Level 3 | | ''2.16.840.1.101.3.4.3.19'' | ML-DSA-87 | NIST Level 5 | ===== Voraussetzungen ===== ==== Runtime ==== * .NET 8.0+ * OpenSSL 3.6.0+ mit PQC-Support ==== OpenSSL Libraries ==== ^ Plattform ^ Library ^ | Windows x64 | ''libcrypto-3-x64.dll'' | | Windows x86 | ''libcrypto-3.dll'' | | Linux | ''libcrypto.so.3'' | | macOS | ''libcrypto.3.dylib'' | ===== Projektstruktur ===== WvdS.System.Security.Cryptography.Extensions/ │ ├── src/ │ └── WvdS.System.Security.Cryptography.Extensions/ │ ├── WvdS.System.Security.Cryptography.Extensions.csproj │ ├── CryptoMode.cs │ ├── CryptoConfig.cs │ ├── Interop/ │ │ └── OpenSslInterop.cs │ └── X509Certificates/ │ ├── CertificateRequestExtensions.cs │ ├── X509Certificate2Extensions.cs │ ├── X509ChainExtensions.cs │ └── Helpers/ │ ├── PqSignatureHelper.cs │ ├── PqKeyStore.cs │ └── TbsCertificateBuilder.cs │ ├── tests/ │ └── WvdS.System.Security.Cryptography.Extensions.Tests/ │ └── ... │ └── README.md ===== SVG-Diagramme in DokuWiki ===== ==== SVG hochladen ==== - **Media Manager** öffnen (Icon in Toolbar oder ''ALT+M'') - Namespace wählen (z.B. '':pqc:'') - SVG-Datei hochladen ==== SVG einbinden ==== // Basis-Syntax {{:namespace:dateiname.svg}} // Mit Breite {{:namespace:dateiname.svg?800}} // Mit Breite und Höhe {{:namespace:dateiname.svg?800x600}} // Mit Alternativtext {{:namespace:dateiname.svg?800|Beschreibung des Bildes}} // Ohne Link (nicht klickbar) {{:namespace:dateiname.svg?nolink}} // Direktlink zum Bild {{:namespace:dateiname.svg?direct}} // Kombiniert {{:namespace:dateiname.svg?direct&800|Alternativtext}} ==== Ausrichtung ==== {{:bild.svg}} // Links {{ :bild.svg}} // Rechts (Leerzeichen vor :) {{ :bild.svg }} // Zentriert (Leerzeichen vor und nach) ===== Siehe auch ===== * [[pqc:openssl|OpenSSL 3.6 PQC Integration]] * [[pqc:mldsa|ML-DSA (FIPS 204) Spezifikation]] * [[pqc:isapi|ISAPI DLL für IIS PQ-Support]] * [[certificates:chain|Certificate Chain Validation]] ===== Changelog ===== ^ Version ^ Datum ^ Änderungen ^ | 1.0.0 | TBD | Initial Release | ---- //EMSR DATA d.o.o. - WvdS Post-Quantum Cryptography Extensions// ~~NOTOC~~