Che cosa fa una funzione hash crittografica

Una funzione hash crittografica è un algoritmo che prende un input di lunghezza qualsiasi e produce un output di lunghezza fissa, chiamato digest o impronta. L’input può essere una breve password, un documento di testo o un file di molti gigabyte: il risultato avrà sempre la stessa dimensione, determinata dall’algoritmo. SHA-256, per esempio, restituisce sempre 256 bit, indipendentemente da quanto sia grande il dato di partenza.

Questa compressione in un’impronta compatta è ciò che rende le funzioni hash così utili. Invece di confrontare o trasmettere interi file, si lavora con le loro impronte, molto più maneggevoli, sfruttando il fatto che a contenuti diversi corrispondono impronte diverse. Tutto, però, dipende da un insieme di proprietà ben precise che distinguono una funzione hash crittografica da un semplice meccanismo di compressione.

Le proprietà fondamentali

Non basta che un algoritmo produca un’impronta di lunghezza fissa per essere considerato crittografico. Servono alcune garanzie precise, ed è la loro combinazione a rendere la funzione adatta agli usi di sicurezza.

Deterministico

La funzione deve essere deterministica: lo stesso input produce sempre la stessa impronta, su qualunque macchina e in qualunque momento. Senza questa proprietà non sarebbe possibile verificare nulla, perché due calcoli sullo stesso dato potrebbero dare risultati diversi.

Veloce da calcolare

Una buona funzione hash deve essere efficiente: calcolare il digest di un dato deve richiedere poco tempo, anche per file di grandi dimensioni. Questo permette di usarla su larga scala, per esempio per verificare l’integrità di migliaia di file o per alimentare protocolli che la invocano continuamente. La velocità in avanti, però, non deve mai facilitare l’inversione della funzione, che resta deliberatamente impraticabile.

Resistenza alla preimmagine

La resistenza alla preimmagine significa che, dato un digest, deve essere praticamente impossibile trovare un input che lo produca. La funzione è a senso unico: facile da calcolare in avanti, irrealizzabile da invertire. Questa proprietà è ciò che consente di pubblicare o conservare un’impronta senza rivelare il dato originale.

Resistenza alla seconda preimmagine

La resistenza alla seconda preimmagine riguarda il caso in cui si parta da un input noto. Dato un messaggio, deve essere irrealizzabile trovarne un secondo, diverso, che produca la stessa impronta. È la garanzia che, fissato un documento, nessuno possa costruire un altro documento con lo stesso digest per sostituirlo di nascosto.

Resistenza alle collisioni

La resistenza alle collisioni è una garanzia più forte: deve essere irrealizzabile trovare due input qualsiasi, scelti liberamente, che condividano lo stesso digest. La differenza rispetto alla seconda preimmagine è sottile ma cruciale: qui l’attaccante non parte da un messaggio dato, ma può scegliere entrambi. È esattamente questa proprietà che SHA-1 ha perso quando, nel 2017, il progetto SHAttered ne dimostrò la prima collisione pratica producendo due file PDF diversi con la stessa impronta SHA-1.

Effetto valanga

L’effetto valanga descrive la sensibilità della funzione all’input. Modificare anche un solo bit del dato di partenza cambia il digest in modo radicale e imprevedibile, alterando in media circa metà dei bit in uscita. Due input quasi identici producono impronte completamente diverse, senza alcuna somiglianza riconoscibile. È questa proprietà che rende le funzioni hash strumenti efficaci per rilevare qualsiasi manomissione, anche minima.

In che cosa si differenziano dagli hash non crittografici

Esistono molte funzioni hash che non sono crittografiche, e confonderle con quelle di sicurezza è un errore frequente. Gli hash non crittografici, come i checksum usati per rilevare errori di trasmissione o le funzioni che distribuiscono le chiavi nelle tabelle hash dei programmi, sono progettati per essere veloci e per distribuire bene i valori, ma non offrono alcuna garanzia contro un avversario intelligente.

La differenza chiave sta proprio qui. Un checksum serve a individuare un errore accidentale, come un bit alterato da un disturbo di rete, ma non resiste a chi voglia deliberatamente costruire due input con lo stesso valore. Una funzione hash crittografica, invece, è pensata per opporsi a un attaccante che dispone di tempo e risorse e che cerca attivamente collisioni o preimmagini. Per questo gli hash non crittografici, pur utili e veloci, non vanno mai usati per password, firme o controlli di sicurezza, mentre solo funzioni come quelle della famiglia SHA-2 offrono le garanzie necessarie.

Un modo pratico di cogliere la differenza è chiedersi contro che cosa l’algoritmo deve difendersi. Un hash non crittografico assume un ambiente benevolo: gli input non sono scelti da un avversario, e l’obiettivo è solo distribuire bene i valori o segnalare guasti casuali. Un hash crittografico assume invece un ambiente ostile, in cui qualcuno studia attivamente l’algoritmo per piegarlo ai propri scopi. Questa differenza di modello di minaccia, e non la semplice velocità o lunghezza dell’output, è ciò che separa le due categorie. La stessa lezione emerge dalla storia di SHA-1: l’algoritmo continuava a comportarsi benissimo come distributore di valori, ma aveva smesso di reggere contro un avversario determinato, ed è proprio per questo secondo criterio che è stato giudicato inadeguato.

Usi comuni delle funzioni hash crittografiche

Le applicazioni sono numerose e toccano gran parte dell’infrastruttura digitale quotidiana.

Conservazione delle password con salt

I sistemi ben progettati non memorizzano le password in chiaro, ma il loro digest. Al momento del login si calcola l’impronta della password inserita e la si confronta con quella salvata. Grazie alla resistenza alla preimmagine, anche chi rubasse il database non potrebbe risalire facilmente alle password originali. A questo si aggiunge il salt, un valore casuale unico per ciascun utente che viene combinato con la password prima dell’hashing: in questo modo due utenti con la stessa password ottengono impronte diverse e gli attacchi basati su tabelle precalcolate diventano inefficaci. Per le password si usano in genere funzioni deliberatamente lente, proprio per ostacolare i tentativi a tappeto.

Controlli di integrità

Pubblicare il digest di un file consente a chiunque di verificarne l’integrità dopo il download o il trasferimento. Se l’impronta calcolata coincide con quella ufficiale, il contenuto non è stato alterato; se differisce, qualcosa è cambiato. È uno degli usi più semplici e diffusi, applicato a immagini di sistemi operativi, pacchetti software e backup.

Firme digitali

Le firme digitali non vengono applicate all’intero messaggio, che potrebbe essere voluminoso, ma al suo digest. La funzione hash riduce il documento a un’impronta compatta su cui opera la firma. Questo lega in modo indissolubile la sicurezza della firma alla solidità della funzione hash: se quest’ultima ammette collisioni, una firma valida per un documento può valere anche per un altro, come ha mostrato lo scenario aperto da SHAttered.

Blockchain

Nelle blockchain ogni blocco contiene il digest del blocco precedente, formando una catena. Modificare un dato passato richiederebbe di ricalcolare tutte le impronte successive, operazione resa proibitiva dal costo computazionale. È l’hashing a conferire al registro la sua caratteristica di sostanziale immutabilità, e funzioni come SHA-256 sono al centro di questi sistemi.

Una primitiva piccola ma decisiva

Le funzioni hash crittografiche sono tra i mattoni più discreti della sicurezza informatica, eppure sostengono password, firme, certificati e registri distribuiti. La loro affidabilità dipende interamente dalle proprietà descritte, e la vicenda di SHA-1 dimostra che cosa accade quando una di esse, la resistenza alle collisioni, viene meno. Scegliere funzioni solide e aggiornate, come quelle della famiglia SHA-2, è la condizione per costruire sistemi degni di fiducia.