Scenario 10.4: TLS ibrido

Categoria: TLS/mTLS
Complessità: Molto alta
Prerequisiti: OpenSSL 3.6+, certificati PQ
Tempo stimato: 45-60 minuti


Descrizione

Questo scenario descrive il TLS ibrido - la combinazione di algoritmi classici e Post-Quantum nell'handshake TLS per la massima sicurezza nella fase di transizione.

Approcci ibridi:

Perché ibrido? Se un algoritmo viene violato (classico dai computer quantistici, PQ da nuovi attacchi), la connessione rimane sicura grazie all'altro.


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: Combinare entrambi i Shared Secrets Client->>Server: Finished Server->>Client: Finished Note over Client,Server: Connessione protetta ibrida


Esempio codice: TLS ibrido con OpenSSL 3.6

using WvdS.Security.Cryptography.X509Certificates.Extensions.PQ;
using System.Runtime.InteropServices;
 
// OpenSSL 3.6 Hybrid Groups per 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)
    {
        // Configurare Hybrid Groups (ordine di preferenza)
        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("Configurazione hybrid key exchange fallita");
        }
    }
}

Server TLS ibrido ASP.NET Core

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 =>
        {
            // Certificato ibrido (ML-DSA + ECDSA)
            httpsOptions.ServerCertificate = LoadHybridCertificate();
 
            // Forzare TLS 1.3 (prerequisito per ibrido)
            httpsOptions.SslProtocols = SslProtocols.Tls13;
 
            // Configurazione OpenSSL per Hybrid Key Exchange
            httpsOptions.OnAuthenticate = (context, sslOptions) =>
            {
                // Cipher Suites per 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();
 
    // Certificato duale con entrambi gli algoritmi
    var cert = ctx.LoadCertificateWithPrivateKey(
        "server-hybrid.crt.pem",
        "server-hybrid.key.pem",
        "Password!"
    );
 
    return cert;
}

Creare certificato ibrido

public class HybridCertificateBuilder
{
    public X509Certificate2 CreateHybridServerCertificate(
        X509Certificate2 caCert,
        AsymmetricAlgorithm caKey,
        string[] dnsNames)
    {
        using var ctx = PqCryptoContext.Initialize();
 
        // Chiave duale: 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 con entrambe le chiavi
        var csr = ctx.CreateHybridCertificateRequest(
            classicalKey: ecdsaKey,
            pqKey: mlDsaKey,
            subject: dn,
            extensions: new ExtBuilder()
                .SubjectAlternativeName(dnsNames.Select(d => $"dns:{d}").ToArray())
                .Build()
        );
 
        // Emettere certificato ibrido
        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)
                // Estensione specifica ibrida
                .AddCustomExtension(
                    oid: "1.3.6.1.4.1.99999.1.1",  // OID esempio
                    critical: false,
                    value: "hybrid:ecdsa-p384+ml-dsa-65"
                )
                .Build()
        );
 
        return cert;
    }
}

Nginx con OpenSSL 3.6 ibrido

server {
    listen 443 ssl http2;
    server_name www.example.com;
 
    # Certificato ibrido
    ssl_certificate     /etc/nginx/ssl/server-hybrid-chain.pem;
    ssl_certificate_key /etc/nginx/ssl/server-hybrid.key.pem;
 
    # Solo TLS 1.3
    ssl_protocols TLSv1.3;
 
    # Hybrid Key Exchange Groups (OpenSSL 3.6+)
    ssl_ecdh_curve x25519_mlkem768:secp384r1_mlkem768:X25519:secp384r1;
 
    # Algoritmi di firma (ibridi)
    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;
    }
}

Configurazione client ibrido

public HttpClient CreateHybridTlsClient()
{
    var handler = new SocketsHttpHandler
    {
        SslOptions = new SslClientAuthenticationOptions
        {
            EnabledSslProtocols = SslProtocols.Tls13,
 
            // Cipher Suites (TLS 1.3 default va bene)
            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($"Errore TLS: {errors}");
                    return false;
                }
 
                // Verificare firma ibrida
                if (certificate is X509Certificate2 cert2)
                {
                    var algorithm = cert2.SignatureAlgorithm.FriendlyName;
                    Console.WriteLine($"Algoritmo firma server: {algorithm}");
 
                    // Verificare se viene usato algoritmo PQ
                    if (!algorithm.Contains("ML-DSA") && !algorithm.Contains("hybrid"))
                    {
                        Console.WriteLine("AVVISO: Il server non usa certificato PQ");
                    }
                }
 
                return true;
            }
        }
    };
 
    return new HttpClient(handler);
}

Strategia di fallback

public class HybridTlsClientWithFallback
{
    public async Task<HttpResponseMessage> GetWithFallback(string url)
    {
        // Tentativo 1: TLS ibrido
        try
        {
            using var hybridClient = CreateHybridTlsClient();
            return await hybridClient.GetAsync(url);
        }
        catch (AuthenticationException ex) when (IsHybridNotSupported(ex))
        {
            Console.WriteLine("TLS ibrido non supportato, fallback a classico...");
        }
 
        // Fallback: TLS 1.3 classico
        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);
    }
}

Matrice di compatibilità

Componente Hybrid Key Exchange Hybrid Signature
OpenSSL 3.6+ Si Si
BoringSSL Si (sperimentale) No
Windows SChannel No (non ancora) No
NSS (Firefox) Si (ML-KEM) No
.NET 9+ Si (con OpenSSL) Si

Requisiti ibridi specifici per settore

Settore Timeline Requisito
BSI TR-02102 Dal 2025 Ibrido raccomandato
NIST Dal 2024 ML-KEM per Key Exchange
Finanza (PCI) 2025-2027 Roadmap migrazione PQ
Governo Dal 2025 Ibrido obbligatorio (US NSA CNSA 2.0)

Scenari correlati

Relazione Scenario Descrizione
Prerequisito 10.1 Server TLS Setup base
Prerequisito 10.3 Deployment mTLS Infrastruttura mTLS
Correlato 7.2 Key Encapsulation ML-KEM
Correlato Algoritmi Fondamenti PQ

« ← 10.3 Deployment mTLS | ↑ Panoramica TLS | → Tutti gli scenari »


Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional