In questo articolo ti farò vedere uno strumento molto utilizzato in informatica. Ammetto che può sembrare complesso, ma cercherò di farti passare il concetto, semplificando un po’.

In termini del tutto generali e per i nostri scopi, possiamo definire una funzione come un’operazione logico/matematica che, dato in ingresso uno o più valori (input), restituisce determinate uscite (output).

Cioè, detto in altri termini, la funzione prende dei valori, chiamati input, 'ci fa qualcosa' e poi restituisce un risultato. Ad esempio una funzione banale è la somma fra due numeri. Gli ingressi sono i due numeri e l'uscita è l'addizione fra i due. Un altro esempio è la funzione che calcola il quadrato di un numero intero positivo:

f(x)=x^2 con x>0

Ad esempio avremo:

se x=1 allora output=1

se x=2 allora output=4

se x=5 allora output=25

se x=10 allora output=100

ecc.

Notiamo che questa funzione è anche reversibile, cioè partendo dall’output, posso agilmente risalire in modo definito al corrispondente input, mediante la funzione inversa del quadrato, ossia la radice quadrata.


Le funzioni HASH

Esiste una tipologia di funzioni dalla caratteristiche molto particolari, le così dette funzioni di hash. Vediamo prima in cosa consistono e poi cerchiamo di capire perché sono molto interessanti in informatica.

Una funzione hash è un algoritmo che prende in input una sequenza di caratteri (si chiama stringa) di qualsiasi lunghezza e restituisce un codice univoco di lunghezza fissa (impronta). Tralasciamo per ora come viene calcolata questa impronta.

Le funzioni hash hanno due proprietà importanti:

  • l’impronta ha sempre la stessa dimensione, sia che la stringa di ingresso abbia due caratteri, sia che ne abbia centomila.
  • ripetendo la stessa funziona più volte con lo stesso ingresso, l’uscita è sempre la stessa.

Un’altra considerazione, abbiamo parlato di sequenza di caratteri, in realtà le funzioni hash lavorano ugualmente con qualsiasi tipologia di informazione, come un file multimediale o un programma. Questo poiché una sequenza di byte può essere sempre convertita in una stringa.


Quali sono le caratteristiche principali delle funzioni hash?

Abbiamo visto come la funzione matematica dell’elevamento al quadrato di un numero intero positivo sia reversibile, ossia esiste una funzione che, dato in ingresso l’uscita della funzione quadrato, mi restituisce l’input originale, il tutto in modo deterministico e in tempi accettabili.

Una funzione di hash, invece, non è mai reversibile, ossia è impossibile, partendo dall’impronta, ricostruire l’informazione originale di input. Pertanto si definisce funzione unidirezionale. Immagina di avere un frullatore (funzione di hash) e immagina di frullare un po’ di frutta (input), quello che otterrò è un succo di frutta (output). Questa è un’operazione non reversibile, dal succo di frutta non potrò mai ottenere i frutti originali! A voler essere precisi, risalire dall’impronta all’input della funzione di hash non è del tutto impossibile, ma è computazionalmente impraticabile. Vuol dire che tale operazione è fattibile, ma richiederebbe dei tempi talmente lunghi da non poter essere presi neanche in considerazione.

Come detto prima una caratteristica fondamentale è che partendo da due input grandi a piacere, ma identici fra loro, a parità di algoritmo di hash, otterremo due impronte identiche. Possiamo dire che le funzioni di hash sono deterministiche. Quello che però potrebbe succedere è che, a partire da due ingressi differenti (sia come contenuto che come grandezza), la nostra funzione di hash mi restituisca la stessa identica impronta. Si avrebbe in questo caso quella che si definisce collisione, che andrebbe opportunamente gestita. Tuttavia un buon algoritmo di hash non deve permettere collisioni, ossia non deve essere possibile che per una data impronta corrispondano più input possibili.

Vediamo ancora due caratteristiche. La prima è che il calcolo dell’impronta è un’operazione molto veloce, a volte è fatta addirittura in hardware con un chip. La seconda è che, considerato un input e la sua impronta, anche una minima variazione dell’input (perfino un solo bit) produce una nuova impronta che è completamente diversa dalla prima.


Per cosa si usano le funzioni di hash?

Ci sono delle applicazioni molto interessanti in cui intervengono queste tipi di funzioni. Ad esempio, supponiamo che io voglia fare il download da Internet di un programma, che viene offerto in un unico file compresso. Se fai attenzione in molti casi, proprio vicino al pulsante per scaricarlo, c’è ‘impronta del file, calcolata con un particolare algoritmo di hash, ad esempio l’MD5. Se ti stai chiedendo a cosa serve, la risposta è semplice. Una volta scaricato il file sul mio pc, posso anche io calcolare l’impronta con lo stesso algoritmo e verificarla con quella sul sito. Se le due impronte sono uguali allora vuol dire che il trasferimento non ha corrotto il file. Se, invece, anche un singolo bit è stato modificato o perso, l’impronta del file che ho scaricato sarà completamente diversa da quella originale presente sul sito, pertanto vorrà dire che il file scaricato sul mio pc è diverso da quello originale.

Il controllo degli errori è una delle applicazioni più comuni delle funzioni di hash. Oltre ai file trasmessi in una rete, è usata anche nelle operazioni di lettura/scrittura sui vari dispositivi di memorizzazione, come i dischi fissi. Il controllo degli errori si basa, come abbiamo visto prima, al confronto fra le impronte del dato, prima e dopo l’operazione.

Esistono inoltre tutta una serie di casi d’uso in cui è fondamentale porre un sigillo a dei documenti elettronici. Si pensi all’informatica forense, in cui è necessario assicurarsi che le varie informazioni come, foto, video, audio, impronte digitali, ecc. non vengano alterate da nessuno. Pertanto si associa immediatamente a questi documenti originali l’impronta calcolata con una funzione hash, che garantisce l’autenticità e integrità del dato, anche dopo aver copiato più volte il materiale.

Un’altra applicazione perfetta per questa tipologia di algoritmo è la memorizzazione delle password. Quando ci registriamo a un sito o servizio e scegliamo la nostra password, questa non viene memorizzata in chiaro sul server, per una questione di privacy, ma viene calcolata la sua funzione di hash e, questa sì, memorizzata sul server. Ogni volta che dovrò fare il login, la password che inserisco viene sottoposta alla funzione di hash e confrontata a quella memorizzata. Se entrambe sono uguali, allora vuol dire che la password inserita era corretta, e viene autorizzato il login, altrimenti no.

Nel momento in cui mi dimentico la password, il servizio non potrà ricordarmela, perché lui ne conosce solo l’hash. Pertanto mi chiederà di generarne una nuova. Se per qualche sfortunato motivo, il database di tutte le password andasse in mano a malintenzionati, non ci sarebbe alcun rischio, proprio perché non sono state memorizzate le password in chiaro, ma solo la loro impronta e dalla loro impronta, come detto, non si può risalire alla password originale.

Le funzioni di hash non sono algoritmi cifratura, poiché non c’è una chiave di cifratura. Inoltre nella crittografia è sempre possibile risalire dal messaggio cifrato a quello in chiaro, conoscendo ovviamente la chiave. Nella funzione di hash, come abbiamo visto, questo non è possibile.