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 Extensions Architektur

Architektur-Erklärung

  1. Bestehende Applikation ruft Extension Methods mit CryptoMode Parameter auf
  2. Extension Methods entscheiden basierend auf Mode:
    • Classic → delegiert an Microsoft .NET
    • Hybrid → nutzt .NET + OpenSSL Interop
    • PostQuantum → nutzt nur OpenSSL Interop
  3. OpenSSL 3.6 Interop (P/Invoke) kommuniziert mit externer libcrypto
  4. 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;
 
/// <summary>
/// Kryptographie-Modus für alle Operationen
/// </summary>
public enum CryptoMode
{
    /// <summary>
    /// Nur klassische Algorithmen (RSA, ECDSA)
    /// → System.Security.Cryptography
    /// </summary>
    Classic = 0,
 
    /// <summary>
    /// Klassisch + Post-Quantum kombiniert
    /// → System.Security.Cryptography + OpenSSL 3.6
    /// → Zertifikat funktioniert auch ohne PQ-Support
    /// </summary>
    Hybrid = 1,
 
    /// <summary>
    /// Nur Post-Quantum Algorithmen (ML-DSA, ML-KEM)
    /// → OpenSSL 3.6
    /// → Benötigt PQ-fähige Software
    /// </summary>
    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
{
    /// <summary>
    /// Erstellt ein selbstsigniertes Zertifikat (Root CA)
    /// </summary>
    /// <param name="request">CertificateRequest</param>
    /// <param name="notBefore">Gültig ab</param>
    /// <param name="notAfter">Gültig bis</param>
    /// <param name="mode">CryptoMode (null = CryptoConfig.DefaultMode)</param>
    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)
        };
    }
 
    /// <summary>
    /// Erstellt ein von einer CA signiertes Zertifikat
    /// </summary>
    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
{
    /// <summary>
    /// Kopiert Zertifikat mit Private Key
    /// </summary>
    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)
        };
    }
 
    /// <summary>
    /// Prüft ob das Zertifikat eine PQ-Signatur Extension hat
    /// </summary>
    public static bool HasPqSignature(this X509Certificate2 certificate)
    {
        return certificate.Extensions[PqSignatureOid] != null;
    }
 
    /// <summary>
    /// Ermittelt den CryptoMode des Zertifikats
    /// </summary>
    public static CryptoMode GetCryptoMode(this X509Certificate2 certificate)
    {
        if (IsPqOnlyAlgorithm(certificate.SignatureAlgorithm.Value))
            return CryptoMode.PostQuantum;
 
        if (certificate.HasPqSignature())
            return CryptoMode.Hybrid;
 
        return CryptoMode.Classic;
    }
 
    /// <summary>
    /// Gibt den Signatur-Algorithmus als lesbaren String zurück
    /// </summary>
    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
{
    /// <summary>
    /// Baut und validiert die Certificate Chain
    /// </summary>
    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)
        };
    }
 
    /// <summary>
    /// Prüft ob die gesamte Chain PQ-geschützt ist
    /// </summary>
    public static bool IsFullyPqProtected(this X509Chain chain)
    {
        foreach (var element in chain.ChainElements)
        {
            if (element.Certificate.GetCryptoMode() == CryptoMode.Classic)
                return false;
        }
        return true;
    }
 
    /// <summary>
    /// Gibt die CryptoModes aller Zertifikate in der Chain zurück
    /// </summary>
    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

  1. Media Manager öffnen (Icon in Toolbar oder ALT+M)
  2. Namespace wählen (z.B. :pqc:)
  3. 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

Changelog

Version Datum Änderungen
1.0.0 TBD Initial Release

EMSR DATA d.o.o. - WvdS Post-Quantum Cryptography Extensions

Zuletzt geändert: den 11.12.2025 um 15:28