~~NOTOC~~
====== Scenario 10.4: Hybrid TLS ======
**Category:** [[.:start|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.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 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** | [[.:server_setup|10.1 TLS Server]] | Basic setup |
| **Prerequisite** | [[.:mtls_deployment|10.3 mTLS Deployment]] | mTLS infrastructure |
| **Related** | [[en:int:pqcrypt:szenarien:verschluesselung:key_encapsulation|7.2 Key Encapsulation]] | ML-KEM |
| **Related** | [[en:int:pqcrypt:konzepte:algorithmen|Algorithms]] | PQ fundamentals |
----
<< [[.:mtls_deployment|← 10.3 mTLS Deployment]] | [[.:start|↑ TLS Overview]] | [[en:int:pqcrypt:szenarien:start|→ All Scenarios]] >>
{{tag>scenario tls hybrid post-quantum ml-kem ml-dsa openssl}}
----
//Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//