Come funziona Signal: il Double Ratchet e la crittografia end-to-end spiegata
Signal è oggi considerata l’app di messaggistica più sicura al mondo. Ma cosa rende Signal diverso da WhatsApp o Telegram? La risposta non è nel design dell’interfaccia, ma in un algoritmo matematico elegante e potente chiamato Double Ratchet — il cuore della crittografia end-to-end di Signal. In questo articolo spieghiamo come funziona Signal, come funziona il Double Ratchet e perché questa tecnologia rappresenta lo stato dell’arte della privacy digitale.
Questo articolo è pensato per tutti: se hai 15 anni e vuoi capire come proteggere i tuoi messaggi, troverai analogie semplici e chiare. Se sei un sviluppatore o un sysadmin, troverai i dettagli tecnici sull’implementazione crittografica. Benvenuti nel motore della privacy moderna.
Perché Signal è più sicuro di WhatsApp: il problema della crittografia statica
Viviamo in un’epoca paradossale. Siamo più connessi che mai, eppure più esposti. Ogni messaggio, ogni foto, ogni “ti amo” inviato via chat lascia un’impronta digitale. Per capire perché Signal risolve questo problema meglio di qualsiasi altra app, partiamo da un’analogia semplice.
Immagina di essere in una classe rumorosa. Vuoi passare un bigliettino al tuo compagno di banco, Marco. Il problema? La professoressa — chiamiamola Evelina, come Eavesdropper (intercettatrice) — cammina tra i banchi e controlla tutto. Se scrivi il messaggio in chiaro, Evelina lo legge. Se lo chiudi in un lucchetto, Marco non ha la chiave per aprirlo.
La soluzione classica è lo scambio di chiavi: tu e Marco vi incontrate di nascosto prima della lezione e vi scambiate la stessa chiave. Funziona, ma è rischioso. Se Evelina vi vede scambiare la chiave, può farne una copia e leggere tutti i biglietti futuri. Peggio ancora: se Evelina ruba la chiave dal tuo astuccio oggi, può aprire non solo i messaggi di oggi, ma anche tutti quelli della settimana scorsa.
Questo è il problema della crittografia statica: se la tua chiave privata viene compromessa, tutta la tua storia di messaggi è a rischio.
Signal risolve questo problema con un’idea brillante: invece di usare una sola chiave per sempre, il sistema cambia chiave ad ogni messaggio. È come se il lucchetto del bigliettino si trasformasse in un nuovo lucchetto con una nuova combinazione dopo ogni singolo utilizzo. Anche se Evelina ruba la chiave attuale, non potrà aprire i messaggi di ieri né quelli di domani. Questo meccanismo si chiama Double Ratchet.
I fondamenti crittografici di Signal: cosa c’è sotto il cofano
Il protocollo Signal — implementato nel libsignal-protocol — non si basa su magia, ma su solide assunzioni matematiche. Per costruire il Double Ratchet servono tre elementi fondamentali.
Diffie-Hellman su Curve Ellittiche (X3DH): Signal usa Curve25519, basata sul problema del logaritmo discreto sulle curve ellittiche (ECDLP). Dati un punto generatore G e un punto pubblico P = k·G, è computazionalmente impossibile ricavare la chiave privata k. Questo permette ad Alice e Marco di generare un segreto condiviso senza mai scambiarsi la chiave privata direttamente. Signal non usa RSA perché è più lento e richiede chiavi molto più grandi.
Key Derivation Function (KDF): Signal usa HKDF basata su SHA-256. Una KDF prende un input ad alta entropia (il segreto DH) e ne distilla chiavi crittografiche uniformi. È unidirezionale: dalla chiave derivata non puoi risalire all’input originale. Questo garantisce la Forward Secrecy.
Cifratura Simmetrica AES-256-GCM: Per il messaggio vero e proprio viene usato AES-256 in modalità GCM (Galois/Counter Mode), che fornisce sia confidenzialità che autenticità (integrità dei dati).
Il Double Ratchet combina questi elementi in due cicli distinti che girano in parallelo: un Symmetric-key Ratchet (veloce, per ogni messaggio) e un Diffie-Hellman Ratchet (più lento, che scatta ad ogni cambio di direzione della conversazione).
Forward Secrecy e Post-Compromise Security: come Signal si auto-ripara
Torniamo in classe. Hai capito che cambiare chiave è importante. Ma come concordare la nuova chiave con Marco senza che Evelina la intercetti? Se invii un messaggio per dire “Ehi Marco, usiamo la nuova chiave X”, Evelina legge quel messaggio e scopre la chiave. È un paradosso.
Signal risolve il paradosso con l’asincronia. Immagina che tu e Marco abbiate ciascuno un ingranaggio segreto — il Ratchet. Quando invii un messaggio, giri il tuo ingranaggio di un tacca. La combinazione cambia. Marco, per leggere il messaggio, deve girare il suo ingranaggio corrispondente.
Il vero punto di forza è la Post-Compromise Security. Supponiamo che Evelina rubi il tuo telefono oggi e copi tutte le chiavi attuali. Tu te ne accorgi, compri un telefono nuovo e installi Signal. Appena invii un nuovo messaggio a Marco, il sistema effettua un “salto” crittografico: genera una nuova coppia di chiavi temporanee che Evelina non possiede. Da quel messaggio in poi, anche con le chiavi vecchie in mano, Evelina non può derivare quelle nuove. Il sistema si è sanato da solo — come se il lucchetto scassinato si fosse fuso e ricreato in una lega metallica sconosciuta al ladro.
Come funziona il Double Ratchet: la meccanica interna passo per passo
Ogni sessione Signal mantiene uno stato interno composto da tre chiavi:
- Root Key (RK): Il segreto maestro, derivato dall’handshake iniziale (X3DH). Non viene mai inviato in rete.
- Chain Key (CK): Derivata dalla RK, evolve ad ogni messaggio.
- Message Key (MK): Derivata dalla CK, usata per cifrare il singolo messaggio, poi scartata immediatamente.
Il processo avviene in due fasi per ogni messaggio in uscita:
Symmetric Ratchet (KDF Chain): Per inviare il messaggio n, si prende la Chain Key corrente (CKn) e la si passa nella KDF. L’output viene diviso in due parti: la Message Key (MKn) usata per cifrare il payload, e la Next Chain Key (CKn+1) salvata per il messaggio successivo. Poiché la KDF è unidirezionale, se un attaccante ottiene CKn+1 non può calcolare MKn (Forward Secrecy). Se ottiene MKn, non può calcolare CKn+1.
Diffie-Hellman Ratchet: Questo meccanismo scatta quando cambia la direzione del messaggio (da Alice a Marco, poi da Marco ad Alice). Alice genera una nuova coppia di chiavi effimere DH. Invia la parte pubblica a Marco. Entrambi calcolano un nuovo segreto DH condiviso, che viene miscelato nella Root Key per generare una RK completamente nuova. Da questa nuova Root Key viene derivata una nuova Chain Key, resettando l’intera catena simmetrica e garantendo la Post-Compromise Security.
Tabella: evoluzione delle chiavi durante una conversazione Signal
La tabella seguente traccia come cambiano le chiavi durante una sequenza di messaggi tra Alice (A) e Marco (B):
| Passo | Azione | Root Key | Chain Key | Message Key | Nota di Sicurezza |
|---|---|---|---|---|---|
| 0 | Handshake X3DH | RK0 (stabilito) | CKA,0 (da RK0) | — | Autenticazione iniziale |
| 1 | A invia Msg 1 | RK0 | CKA,1 | MKA,1 | Forward Secrecy attiva |
| 2 | A invia Msg 2 | RK0 | CKA,2 | MKA,2 | MK del Msg 1 già distrutta |
| 3 | B risponde (DH Ratchet) | RK1 (aggiornato) | CKB,0 (da RK1) | MKB,1 | Post-Compromise Security |
| 4 | B invia Msg 2 | RK1 | CKB,1 | MKB,2 | Nuova catena simmetrica |
| 5 | A risponde (DH Ratchet) | RK2 (aggiornato) | CKA,3 (da RK2) | MKA,3 | Rottura continuità crittografica |
Nota sul Passo 3: quando Marco risponde, introduce un nuovo input DH. La Root Key cambia da RK0 a RK1. Se un attaccante aveva compromesso lo stato di Alice al Passo 2, al Passo 3 non può prevedere RK1 perché manca la chiave privata effimera generata da Marco. La catena di compromissione si interrompe.
Simulazione Python del Double Ratchet
Per i professionisti, la teoria è nulla senza pratica. Di seguito uno script Python che simula la logica del Symmetric Ratchet e del DH Ratchet. Per brevità e portabilità vengono usati hmac e hashlib per simulare la KDF e uno scambio di chiavi semplificato, ma la logica di ratcheting è fedele al protocollo reale.
import hmac
import hashlib
import os
class DoubleRatchetSim:
def __init__(self, initial_root_key):
self.root_key = initial_root_key
self.chain_key = self._kdf(self.root_key, b"chain_init")
self.dh_ratchet_count = 0
def _kdf(self, key, data):
"""Simula HKDF-SHA256"""
return hmac.new(key, data, hashlib.sha256).digest()
def _ratchet_symmetric(self):
"""Genera Message Key e aggiorna Chain Key"""
digest = self._kdf(self.chain_key, b"msg_key_derive")
message_key = digest[:32]
self.chain_key = digest[32:]
return message_key
def _ratchet_dh(self, new_dh_secret):
"""Aggiorna Root Key e resetta Chain Key (DH Ratchet Step)"""
self.root_key = self._kdf(self.root_key, new_dh_secret)
self.chain_key = self._kdf(self.root_key, b"chain_init")
self.dh_ratchet_count += 1
def send_message(self, payload):
mk = self._ratchet_symmetric()
cipher = bytes([p ^ m for p, m in zip(payload.encode(), mk)])
return cipher, mk
def receive_message(self, cipher, mk):
payload = bytes([c ^ m for c, m in zip(cipher, mk)])
return payload.decode()
# --- ESECUZIONE SIMULAZIONE ---
shared_secret = os.urandom(32)
alice = DoubleRatchetSim(shared_secret)
marco = DoubleRatchetSim(shared_secret)
print("=== INIZIO SESSIONE ===")
# Alice invia 2 messaggi (Solo Symmetric Ratchet)
msg1 = "Ciao Marco, questo è un segreto."
cipher1, mk1 = alice.send_message(msg1)
print("[Alice] Invio Msg 1 (CK evolve)")
msg2 = "Secondo messaggio, stessa catena."
cipher2, mk2 = alice.send_message(msg2)
print("[Alice] Invio Msg 2 (CK evolve di nuovo)")
# Marco riceve
marco._ratchet_symmetric()
decrypted1 = marco.receive_message(cipher1, mk1)
marco._ratchet_symmetric()
decrypted2 = marco.receive_message(cipher2, mk2)
print(f"[Marco] Ricevuto 1: {decrypted1}")
print(f"[Marco] Ricevuto 2: {decrypted2}")
# DH Ratchet (Marco risponde, cambia direzione)
new_dh_secret = os.urandom(32)
marco._ratchet_dh(new_dh_secret)
alice._ratchet_dh(new_dh_secret)
print("\n=== DH RATCHET SCATTATO ===")
print(f"Root Key aggiornata. Conteggio Ratchet: {alice.dh_ratchet_count}")
msg3 = "Terzo messaggio, nuova catena di sicurezza."
cipher3, mk3 = marco.send_message(msg3)
alice._ratchet_symmetric()
decrypted3 = alice.receive_message(cipher3, mk3)
print(f"[Alice] Ricevuto 3: {decrypted3}")
print("\n=== ANALISI SICUREZZA ===")
print("MK1 e MK2 sono indipendenti da MK3 grazie al DH Ratchet.")
print("Se MK1 fosse compromesso, MK3 rimarrebbe sicuro.")
Questo script evidenzia la separazione tra l’evoluzione della catena (ogni messaggio) e il reset della radice (ogni cambio di turno). In un’implementazione reale, new_dh_secret deriverebbe da uno scambio X25519 reale tra le chiavi pubbliche effimere dei due partecipanti.
Signal può essere violato? Vulnerabilità reali e minacce future
Arriviamo alla domanda che tutti si pongono: Signal è davvero inviolabile?
Matematicamente, oggi sì. Con chiavi a 256 bit e curve ellittiche corrette, un attacco brute-force richiederebbe più energia di quella contenuta nell’intero universo osservabile. Le vulnerabilità algoritmiche del Double Ratchet sono, allo stato attuale, inesistenti.
Tuttavia la sicurezza informatica non è mai solo matematica. È un sistema socio-tecnico con quattro punti deboli concreti:
1. Il fattore umano: Puoi avere il Double Ratchet più robusto del mondo, ma uno screenshot della chat caricato su un cloud pubblico rende inutile qualsiasi crittografia. Il phishing, l’ingegneria sociale o la semplice negligenza nel proteggere il PIN di registrazione bypassano completamente la crittografia. Se un attaccante prende il controllo fisico del dispositivo, legge i messaggi prima che vengano cifrati o dopo la decifratura.
2. Vulnerabilità di implementazione: Bug nel codice — buffer overflow, gestione errata della memoria — possono esporre le chiavi. Gli attacchi side-channel (analisi del consumo energetico, tempi di esecuzione) potrebbero teoricamente far trapelare informazioni sulle chiavi private, sebbene sia estremamente difficile su dispositivi moderni.
3. La minaccia quantistica: I computer quantistici, una volta maturi (stimati tra 10 e 20 anni), potrebbero risolvere il problema del logaritmo discreto usando l’algoritmo di Shor, rompendo lo scambio di chiavi iniziale X3DH. Signal è già al lavoro su integrazioni di Post-Quantum Cryptography (PQC), come l’algoritmo Kyber, per ibridare le chiavi e resistere a un futuro attacco quantistico.
4. I metadati: Il Double Ratchet protegge il contenuto del messaggio, non i metadati. Signal sa chi parla con chi e quando, anche se minimizza questi dati tramite tecniche come i sealed sender. Sapere che Alice ha parlato con Marco alle 3 di notte può essere informativo quanto il messaggio stesso.
Domande frequenti su Signal e la crittografia end-to-end
Signal è davvero sicuro?
Sì. Signal utilizza il protocollo Double Ratchet con crittografia AES-256-GCM e scambio di chiavi Diffie-Hellman su curve ellittiche (Curve25519). È considerato lo standard de facto della messaggistica sicura e il suo codice è open source, verificato pubblicamente da esperti di sicurezza di tutto il mondo.
Cos’è il Double Ratchet di Signal?
Il Double Ratchet è il meccanismo crittografico che genera una nuova chiave di cifratura per ogni singolo messaggio. Combina un Symmetric Ratchet (che evolve ad ogni messaggio) con un Diffie-Hellman Ratchet (che si attiva ad ogni cambio di direzione della conversazione), garantendo che la compromissione di una chiave non esponga né i messaggi passati né quelli futuri.
Signal è meglio di WhatsApp?
Entrambe le app usano il protocollo Signal per la crittografia end-to-end dei messaggi. La differenza principale riguarda i metadati: WhatsApp (di proprietà di Meta) raccoglie informazioni su chi parla con chi, quando e da quale dispositivo. Signal raccoglie il minimo indispensabile e il suo codice è completamente open source e verificabile.
Signal può essere intercettato dalla polizia o dai governi?
Il contenuto dei messaggi no. Grazie alla crittografia end-to-end, nemmeno Signal stessa può leggere i tuoi messaggi. In risposta a richieste legali, Signal ha dimostrato di poter fornire solo dati minimi come la data di creazione dell’account e l’ultima connessione. I metadati (chi parla con chi) sono invece potenzialmente accessibili a terze parti a livello di rete.
Cosa significa “forward secrecy” in Signal?
Forward secrecy significa che anche se un attaccante ottiene le chiavi crittografiche attuali, non può decifrare i messaggi inviati in precedenza. Questo perché Signal genera e poi distrugge una chiave unica per ogni messaggio — le chiavi passate non esistono più e non possono essere ricostruite.
Signal è sicuro contro i computer quantistici?
Non ancora completamente, ma Signal sta lavorando attivamente a soluzioni di Post-Quantum Cryptography (PQC), tra cui l’integrazione dell’algoritmo Kyber. L’obiettivo è rendere il protocollo resistente agli attacchi di computer quantistici anche quando questa tecnologia sarà matura, stimata tra 10 e 20 anni.
Conclusione: la privacy come processo, non come stato
Il Double Ratchet non è solo un algoritmo — è una filosofia. Rifiuta l’idea che la sicurezza sia uno stato statico (“ho impostato una password forte, sono al sicuro”). Afferma invece che la sicurezza è un processo dinamico e continuo che si evolve costantemente per rendere obsoleto qualsiasi tentativo di compromissione passata o futura.
In un mondo dove i dati sono il nuovo petrolio, Signal e il suo Double Ratchet rappresentano oggi la migliore risposta disponibile alla domanda: come posso comunicare privatamente? La catena è forte quanto il suo anello più debole — e spesso quell’anello siamo noi. Usate Signal, studiate come funziona, ma ricordate sempre che la tecnologia protegge il messaggio: proteggere il dispositivo e le proprie abitudini digitali è ancora compito nostro.
Stay secure. Stay private.
