Skip to main content
  1. Concetti/

TLS - Transport Layer Security - Handshake e Crittografia Ibrida

Alessio Barnini
Author
Alessio Barnini
Table of Contents

Cos'e'
#

TLS (Transport Layer Security) e' il protocollo che cifra le connessioni di rete. Risolve tre problemi fondamentali in sequenza: verificare l'identita' del server, scambiare una chiave di sessione in modo sicuro, e cifrare tutto il traffico dati con quella chiave. SSL e' il predecessore deprecato — il nome sopravvive nel linguaggio comune e nel nome openssl, ma da usare TLS 1.2 o 1.3.

cryptographic-protocols.webp

Protocollo che cifra le connessioni di rete usando un modello ibrido: crittografia asimmetrica per negoziare le chiavi (handshake), simmetrica AES per cifrare i dati.

TL;DR
#

TLS risolve tre problemi in sequenza:

  1. Identita' del server: il certificato X.509 del server e' firmato da una CA fidata. Il browser verifica la catena localmente contro il trust store del sistema operativo.
  2. Key exchange sicuro: con ECDHE entrambi i lati derivano la stessa session key senza trasmetterla sulla rete. La chiave nasce nei due sistemi separatamente — non viaggia mai.
  3. Cifratura bulk: da quel momento tutto il traffico viaggia cifrato con AES. Veloce, hardware-accelerated, a ogni pacchetto.

L'handshake e' la parte costosa (asimmetrica, pochi millisecondi, fatta una volta per sessione). I dati viaggiano con AES (simmetrico, microsecondi, ogni pacchetto). TLS 1.3 rende questo schema obbligatorio e garantisce PFS per ogni sessione senza eccezioni.


Versioni Storiche
#

La storia di SSL/TLS e' una sequenza di vulnerabilita' scoperte e versioni deprecate. Conoscere quale versione ha quale vulnerabilita' e' richiesto sia per l'esame sia per configurare correttamente un server.

SSL 1.0  → 1994, mai rilasciato
SSL 2.0  → 1995, subito bucato
SSL 3.0  → 1996, usato per anni — vulnerabile a POODLE (2015)
TLS 1.0  → 1999, vulnerabile a BEAST
TLS 1.1  → 2006, deprecated RFC 8996 (2021)
TLS 1.2  → 2008, ancora in uso — PFS opzionale (dipende dalla cipher suite)
TLS 1.3  → 2018, quello attuale — ECDHE obbligatorio, PFS sempre attivo

SSL e' morto nel 2015. Quando dici "certificato SSL" intendi TLS. Il nome e' rimasto nel linguaggio comune — e nel nome openssl.


Modello Ibrido
#

Il cuore di TLS e' l'uso combinato di crittografia asimmetrica e simmetrica. La asimmetrica risolve il problema della distribuzione delle chiavi (nessun canale sicuro necessario), ma e' troppo lenta per i dati. La simmetrica e' velocissima ma richiede una chiave condivisa in anticipo. TLS le usa in sequenza: asimmetrica per consegnare la chiave, simmetrica per i dati.

graph LR
    CH["ClientHello
    cipher suites"]
    SH["ServerHello
    + certificato"]
    KE["ECDHE
    parametri pubblici"]
    SK["Session Key
    derivata localmente"]
    AES["AES-256-GCM
    bulk data"]
    VEL["Veloce
    hardware accel."]

    subgraph HANDSHAKE["HANDSHAKE — asimmetrico, una volta sola"]
        CH
        SH
        KE
        SK
    end

    subgraph DATI["DATI — simmetrico, ogni pacchetto"]
        AES
        VEL
    end

    CH --> SH
    SH --> KE
    KE --> SK
    SK -->|usa la session key| AES
    AES --- VEL

Lettura: L'handshake (sinistra) usa ECDHE asimmetrico per derivare la session key — operazione costosa, fatta una sola volta per sessione. Da quel punto tutti i dati (destra) viaggiano con AES simmetrico, velocissimo.

Dev parallel: Quando fai $client->request('GET', 'https://api.service.com') in Symfony o https.get() in Node.js, la libreria TLS sottostante esegue automaticamente l'handshake ECDHE e deriva la session key. Tu non chiami mai openssl_encrypt() esplicitamente per ogni request — TLS lo fa a livello di trasporto. Quando invece cifri dati a riposo (un file upload, un campo DB sensibile), usi AES direttamente con openssl_encrypt() in PHP o crypto.createCipheriv() in Node: e' la stessa logica della Fase 2, senza la Fase 1 perche' la chiave la gestisci tu. La distinzione data in transit (TLS) vs data at rest (AES diretto) mappa esattamente sui due livelli del modello ibrido.


Il TLS Handshake
#

Il TLS handshake e' la fase di negoziazione iniziale che avviene subito dopo il three-way handshake TCP. Browser e server si accordano su algoritmi, il server si autentica con il suo certificato, derivano insieme la session key tramite ECDHE, poi inizia la cifratura dei dati. In TLS 1.3 l'intero handshake richiede un solo round trip (1 RTT).

sequenceDiagram
    participant B as Browser
    participant S as Server

    B->>S: TCP SYN
    S->>B: TCP SYN-ACK
    B->>S: TCP ACK

    B->>S: Client Hello — versioni TLS e algoritmi supportati
    S->>B: Server Hello — algoritmo scelto + certificato
    B->>B: Verifica catena certificato fino a Root CA
    B->>S: Parametro pubblico DH (A = g^a)
    S->>B: Parametro pubblico DH (B = g^b)
    note over B,S: Entrambi derivano la stessa chiave simmetrica
    note over B,S: Nessuno ha mai mandato la chiave sulla rete
    B->>S: Dati cifrati con AES
    S->>B: Risposta cifrata con AES

Lettura: TLS handshake completo partendo dal TCP. Prima il three-way handshake TCP (SYN, SYN-ACK, ACK) per stabilire la connessione. Poi il TLS: Client Hello con algoritmi supportati, Server Hello con algoritmo scelto e certificato. Browser verifica la catena CA localmente. Scambio parametri DH: entrambi derivano la stessa chiave simmetrica senza trasmetterla. Da quel punto i dati viaggiano cifrati con AES.

La cifratura inizia sul computer del client, prima che il pacchetto esca.

Browser di Ubuntu
      │ 1. TCP handshake con il server (non cifrato)
      │ 2. TLS handshake (negoziazione algoritmi, scambio chiavi)
      │ 3. Derivazione chiave simmetrica — avviene localmente
      │ 4. Dati cifrati con AES
[pacchetto gia' cifrato] ──► Kali (MITM) ──► internet ──► server

Quello che Kali vede con il MITM ARP su traffico HTTPS:

IP 192.168.64.3 > 216.58.x.x: TCP [SYN]
IP 192.168.64.3 > 216.58.x.x: TLSv1.3 Client Hello
IP 216.58.x.x > 192.168.64.3: TLSv1.3 Server Hello, Certificate
IP 192.168.64.3 > 216.58.x.x: [dati cifrati]
IP 216.58.x.x > 192.168.64.3: [dati cifrati]

Vedi che sta avvenendo una comunicazione HTTPS, con quale server, quanto traffico, quando — ma non il contenuto. I dati sono gia' cifrati quando lasciano il browser. Questo e' esattamente perche' HTTPS esiste: proteggere dal MITM di rete.


Perfect Forward Secrecy
#

PFS (Perfect Forward Secrecy) garantisce che la compromissione della chiave privata del server oggi non permetta di decifrare il traffico registrato in passato. E' la distinzione operativa fondamentale tra TLS 1.2 con RSA key exchange e TLS 1.3 con ECDHE — e una delle ragioni piu' importanti per migrare a TLS 1.3.

La E in ECDHE sta per Ephemeral — effimero.

Sessione 1: chiavi a1, b1 → chiave simmetrica K1 → scartata
Sessione 2: chiavi a2, b2 → chiave simmetrica K2 → scartata
Sessione 3: chiavi a3, b3 → chiave simmetrica K3 → scartata

TLS 1.2 vs TLS 1.3 — la differenza chiave per PFS:

TLS 1.2 (RSA)TLS 1.2 (ECDHE)TLS 1.3
Key exchangeRSA staticoECDHE efimeroECDHE efimero (obbligatorio)
Session key trasmessa?Si (cifrata)No (derivata)No (derivata)
PFS garantito?NoSiSi (sempre)
Rischio se priv key rubataTraffico passato decifraSolo identita' compromessaSolo identita' compromessa

Come riconosci PFS nell'output di openssl:

New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
# "New" = chiavi generate ora, mai usate prima — PFS attivo

# Se vedessi:
Reused, TLSv1.3, ...
# "Reused" = chiavi riciclate — PFS non funziona

TLS 1.3 rende ECDHE obbligatorio — PFS non e' piu' una scelta, e' la default.


Post-Quantum Cryptography
#

La crittografia post-quantum protegge da attacchi futuri di computer quantistici. X25519 (Diffie-Hellman su curva ellittica, usato in TLS 1.3) e' vulnerabile all'algoritmo di Shor su un computer quantistico sufficientemente potente. Lo schema ibrido X25519MLKEM768 protegge usando due algoritmi in parallelo: se uno viene rotto, l'altro tiene.

Output reale di google.com:

Negotiated TLS1.3 group: X25519MLKEM768
X25519         → Diffie-Hellman su curva ellittica (protegge oggi)
MLKEM768       → algoritmo post-quantum su reticoli (protegge dal futuro)
X25519MLKEM768 → ibrido: se uno cede, l'altro tiene

Un computer quantistico puo' rompere X25519. MLKEM768 resiste ai computer quantistici. Usandoli insieme il blast radius di una compromissione e' limitato.


La Catena CA
#

La catena CA (Certificate Authority) e' la sequenza di firme digitali che collega il certificato di un sito a una Root CA preinstallata nel sistema operativo. Ogni livello e' firmato dal livello sopra — spezzare anche un solo anello invalida tutta la catena e blocca la connessione.

certificate-authority-trust-model.webp

Output reale di openssl s_client -connect google.com:443:

depth=2 C=US, O=Google Trust Services LLC, CN=GTS Root R1   # Root CA
depth=1 C=US, O=Google Trust Services, CN=WR2               # Intermediate CA
depth=0 CN=*.google.com                                      # Certificato del sito

Certificate chain:
  0  s: CN=*.google.com          i: WR2           # sito firmato da Intermediate
  1  s: WR2                      i: GTS Root R1   # Intermediate firmata da Root
  2  s: GTS Root R1              i: GlobalSign     # Root firmata da GlobalSign

Il pattern: l'i (issuer) di ogni livello e' l's (subject) del livello sopra. E' una catena letterale — se un anello e' rotto, la verifica fallisce.

GlobalSign Root CA  (preinstallata nel tuo OS)
  └── GTS Root R1   (Intermediate — firmata da GlobalSign)
        └── WR2     (Intermediate — firmata da Root R1)
              └── *.google.com  (firmata da WR2)

Se il certificato e' scaduto o revocato:

  • Il browser non va in HTTP — blocca la connessione
  • L'utente vede il warning rosso
  • Niente dati in chiaro — niente connessione

Wildcard vs Certificato Specifico
#

La scelta tra certificato wildcard e certificati separati e' una decisione di sicurezza prima che di comodita'. Il wildcard riduce i costi operativi ma aumenta il blast radius in caso di compromissione della chiave privata.

# Wildcard — copre tutti i sottodomini di primo livello
CN=*.google.com
  copre: mail.google.com, maps.google.com, drive.google.com
  NON copre: google.com, sub.mail.google.com

# Certificato specifico
CN=github.com
  copre: solo github.com

Perche' GitHub preferisce certificati separati:

Wildcard compromesso:
  chiave rubata → tutti i sottodomini esposti

Certificati separati:
  chiave rubata → solo quel dominio esposto
  api.github.com, gist.github.com → salvi

Stesso principio dello sviluppo: blast radius minimo.


Confronto TLS vs SSH
#

TLS e SSH risolvono lo stesso problema (identita' + canale cifrato + PFS) con implementazioni diverse. Il punto di divergenza piu' importante e' il modello di fiducia: CA gerarchica vs TOFU.

                    TLS                      SSH
Scambio chiavi      X25519MLKEM768           curve25519-sha256
Firma server        ECDSA / certificato      ed25519 / known_hosts
Fiducia             CA preinstallata nel OS  TOFU — Trust On First Use
Cifratura dati      AES-256-GCM              chacha20-poly1305
PFS                 ECDHE effimero           curve25519 effimero
Auth client         certificato client       password o challenge-response
Replay protection   —                        challenge casuale per firma

Stessa struttura concettuale, implementazione diversa. Il problema da risolvere e' identico: identita' + canale cifrato + PFS.

Certificato vs Chiavi

Certificato → risponde a: "chi sei?" Chiave simmetrica AES → risponde a: "come cifriamo?"


Scenario Reale Blue Team
#

Un certificato in scadenza non e' solo un problema di UX — e' un alert operativo. Un certificato scaduto su un servizio interno invisibile dal browser puo' indicare un servizio abbandonato, una superficie di attacco fuori dal perimetro di gestione.

# Controlla scadenza su piu' domini
for domain in google.com github.com api.internal.company.com; do
  echo -n "$domain: "
  echo | openssl s_client -connect $domain:443 2>/dev/null \
    | openssl x509 -noout -enddate
done

# Verifica cipher suite e PFS
openssl s_client -connect api.service.com:443 2>/dev/null \
  | grep -E "New|Reused|Cipher|Protocol"
# New = PFS attivo; Reused = PFS non funziona
# Protocol: TLSv1.3 = ok; TLSv1.2 = controlla cipher suite
# Cipher: TLS_AES_256_GCM_SHA384 = TLS 1.3 con AEAD, ideale
Warning

Un certificato valido non significa che il sito e' sicuro. Significa solo che la connessione e' cifrata. Un attaccante puo' avere un certificato valido (Let's Encrypt e' gratuito) per un sito di phishing — la verifica del dominio va fatta separatamente.

Tip

New vs Reused nell'output openssl e' il check rapido per verificare se PFS e' attivo su un servizio che stai ispezionando. Su TLS 1.3 sara' sempre New — il protocollo non permette altro.


Collegato a
#

  • crypto — categoria
  • cryptography — teoria crittografica di base
  • pki — infrastruttura a chiave pubblica, catena CA, CRL/OCSP, DigiNotar
  • ssh-protocol — stesso schema concettuale, implementazione diversa
  • openssl-s_client — tool per ispezionare TLS da terminale

Related