====== 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~~