Scenario 10.4: Hybrid TLS
Category: TLS/mTLS
Complexity: ⭐⭐⭐⭐⭐ (Very High)
Prerequisites: OpenSSL 3.6+, PQ certificates
Estimated Time: 45-60 Minutes
Description
This scenario describes Hybrid TLS - the combination of classical and Post-Quantum algorithms in the TLS handshake for maximum security during the transition phase.
Hybrid Approaches:
- Hybrid Key Exchange - X25519 + ML-KEM-768
- Hybrid Signature - ECDSA + ML-DSA-65
- Dual Certificates - Classical + PQ certificate
Why Hybrid? If one algorithm is broken (classical by quantum computers, PQ by new attacks), the connection remains secure through the other.
TLS 1.3 Hybrid Key Exchange
sequenceDiagram
participant Client
participant Server
Client->>Server: ClientHello + key_share(X25519 + ML-KEM-768)
Server->>Client: ServerHello + key_share(X25519 + ML-KEM-768)
Note over Client,Server: Combine both shared secrets
Client->>Server: Finished
Server->>Client: Finished
Note over Client,Server: Hybrid-secured connection
Code Example: Hybrid TLS with OpenSSL 3.6
using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ; using System.Runtime.InteropServices; // OpenSSL 3.6 Hybrid Groups for Key Exchange public static class HybridTlsConfig { // Hybrid Key Exchange Groups (OpenSSL 3.6+) public const string HYBRID_X25519_MLKEM768 = "x25519_mlkem768"; public const string HYBRID_SECP384R1_MLKEM768 = "secp384r1_mlkem768"; public const string HYBRID_SECP256R1_MLKEM512 = "secp256r1_mlkem512"; [DllImport("libssl")] private static extern int SSL_CTX_set1_groups_list(IntPtr ctx, string groups); public static void ConfigureHybridKeyExchange(IntPtr sslContext) { // Configure hybrid groups (preference order) var groups = $"{HYBRID_X25519_MLKEM768}:{HYBRID_SECP384R1_MLKEM768}:X25519:secp384r1"; int result = SSL_CTX_set1_groups_list(sslContext, groups); if (result != 1) { throw new CryptographicException("Failed to configure hybrid key exchange"); } } }
ASP.NET Core Hybrid TLS Server
using Microsoft.AspNetCore.Server.Kestrel.Core; using System.Security.Authentication; var builder = WebApplication.CreateBuilder(args); builder.WebHost.ConfigureKestrel(options => { options.ListenAnyIP(443, listenOptions => { listenOptions.UseHttps(httpsOptions => { // Hybrid certificate (ML-DSA + ECDSA) httpsOptions.ServerCertificate = LoadHybridCertificate(); // Enforce TLS 1.3 (prerequisite for hybrid) httpsOptions.SslProtocols = SslProtocols.Tls13; // OpenSSL configuration for hybrid key exchange httpsOptions.OnAuthenticate = (context, sslOptions) => { // Cipher suites for TLS 1.3 sslOptions.CipherSuitesPolicy = new CipherSuitesPolicy(new[] { TlsCipherSuite.TLS_AES_256_GCM_SHA384, TlsCipherSuite.TLS_CHACHA20_POLY1305_SHA256 }); // Application-Layer Protocol Negotiation sslOptions.ApplicationProtocols = new List<SslApplicationProtocol> { SslApplicationProtocol.Http2, SslApplicationProtocol.Http11 }; }; }); listenOptions.Protocols = HttpProtocols.Http1AndHttp2; }); }); X509Certificate2 LoadHybridCertificate() { using var ctx = PqCryptoContext.Initialize(); // Dual certificate with both algorithms var cert = ctx.LoadCertificateWithPrivateKey( "server-hybrid.crt.pem", "server-hybrid.key.pem", "Password!" ); return cert; }
Create Hybrid Certificate
public class HybridCertificateBuilder { public X509Certificate2 CreateHybridServerCertificate( X509Certificate2 caCert, AsymmetricAlgorithm caKey, string[] dnsNames) { using var ctx = PqCryptoContext.Initialize(); // Dual Key: ECDSA + ML-DSA using var ecdsaKey = ECDsa.Create(ECCurve.NamedCurves.nistP384); using var mlDsaKey = ctx.GenerateKeyPair(PqAlgorithm.MlDsa65); var dn = new DnBuilder() .AddCN(dnsNames[0]) .AddO("Example GmbH") .Build(); // CSR with both keys var csr = ctx.CreateHybridCertificateRequest( classicalKey: ecdsaKey, pqKey: mlDsaKey, subject: dn, extensions: new ExtBuilder() .SubjectAlternativeName(dnsNames.Select(d => $"dns:{d}").ToArray()) .Build() ); // Issue hybrid certificate var cert = ctx.IssueHybridCertificate( csr, issuerCert: caCert, issuerKey: caKey, validDays: 365, extensions: new ExtBuilder() .BasicConstraints(ca: false, critical: true) .KeyUsage(KeyUsageFlags.DigitalSignature | KeyUsageFlags.KeyEncipherment) .ExtendedKeyUsage(ExtKeyUsage.ServerAuth) .SubjectKeyIdentifier(mlDsaKey.PublicKey) .AuthorityKeyIdentifier(caCert) // Hybrid-specific extension .AddCustomExtension( oid: "1.3.6.1.4.1.99999.1.1", // Example OID critical: false, value: "hybrid:ecdsa-p384+ml-dsa-65" ) .Build() ); return cert; } }
Nginx with OpenSSL 3.6 Hybrid
server { listen 443 ssl http2; server_name www.example.com; # Hybrid certificate ssl_certificate /etc/nginx/ssl/server-hybrid-chain.pem; ssl_certificate_key /etc/nginx/ssl/server-hybrid.key.pem; # TLS 1.3 only ssl_protocols TLSv1.3; # Hybrid Key Exchange Groups (OpenSSL 3.6+) ssl_ecdh_curve x25519_mlkem768:secp384r1_mlkem768:X25519:secp384r1; # Signature Algorithms (Hybrid) ssl_conf_command SignatureAlgorithms ed25519:ecdsa_secp384r1_sha384:mldsa65:hybrid_mldsa65_ecdsa_p384; # OCSP Stapling ssl_stapling on; ssl_stapling_verify on; location / { proxy_pass http://backend:8080; } }
Hybrid Client Configuration
public HttpClient CreateHybridTlsClient() { var handler = new SocketsHttpHandler { SslOptions = new SslClientAuthenticationOptions { EnabledSslProtocols = SslProtocols.Tls13, // Cipher suites (TLS 1.3 default good) CipherSuitesPolicy = new CipherSuitesPolicy(new[] { TlsCipherSuite.TLS_AES_256_GCM_SHA384, TlsCipherSuite.TLS_CHACHA20_POLY1305_SHA256 }), RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => { if (errors != SslPolicyErrors.None) { Console.WriteLine($"TLS Error: {errors}"); return false; } // Verify hybrid signature if (certificate is X509Certificate2 cert2) { var algorithm = cert2.SignatureAlgorithm.FriendlyName; Console.WriteLine($"Server Signature Algorithm: {algorithm}"); // Check if PQ algorithm is used if (!algorithm.Contains("ML-DSA") && !algorithm.Contains("hybrid")) { Console.WriteLine("WARNING: Server is not using PQ certificate"); } } return true; } } }; return new HttpClient(handler); }
Fallback Strategy
public class HybridTlsClientWithFallback { public async Task<HttpResponseMessage> GetWithFallback(string url) { // Attempt 1: Hybrid TLS try { using var hybridClient = CreateHybridTlsClient(); return await hybridClient.GetAsync(url); } catch (AuthenticationException ex) when (IsHybridNotSupported(ex)) { Console.WriteLine("Hybrid TLS not supported, falling back to classic..."); } // Fallback: Classic TLS 1.3 using var classicClient = CreateClassicTlsClient(); return await classicClient.GetAsync(url); } private bool IsHybridNotSupported(Exception ex) { return ex.Message.Contains("no common signature algorithm") || ex.Message.Contains("unsupported group"); } private HttpClient CreateClassicTlsClient() { var handler = new HttpClientHandler { SslProtocols = SslProtocols.Tls13 }; return new HttpClient(handler); } }
Compatibility Matrix
| Component | Hybrid Key Exchange | Hybrid Signature |
|---|---|---|
| OpenSSL 3.6+ | ✅ | ✅ |
| BoringSSL | ✅ (experimental) | ❌ |
| Windows SChannel | ❌ (not yet) | ❌ |
| NSS (Firefox) | ✅ (ML-KEM) | ❌ |
| .NET 9+ | ✅ (with OpenSSL) | ✅ |
Industry-Specific Hybrid Requirements
| Industry | Timeline | Requirement |
|---|---|---|
| BSI TR-02102 | From 2025 | Hybrid recommended |
| NIST | From 2024 | ML-KEM for key exchange |
| Financial (PCI) | 2025-2027 | PQ migration roadmap |
| Government | From 2025 | Hybrid mandatory (US NSA CNSA 2.0) |
Related Scenarios
| Relationship | Scenario | Description |
|---|---|---|
| Prerequisite | 10.1 TLS Server | Basic setup |
| Prerequisite | 10.3 mTLS Deployment | mTLS infrastructure |
| Related | 7.2 Key Encapsulation | ML-KEM |
| Related | Algorithms | PQ fundamentals |
« ← 10.3 mTLS Deployment | ↑ TLS Overview | → All Scenarios »
Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional
Zuletzt geändert: on 2026/01/30 at 06:51 AM