Quando gestiamo gli account degli utenti è praticamente obbligatorio salvare la password di ciascun utente all'interno di un database. Queste password non andrebbero mai salvate in chiaro, ma vanno salvate mediante criptazione. Purtroppo non è sempre così: vediamo quindi perché criptare le password nel database, come farlo e quali sono i vantaggi o svantaggi delle scelte più tradizionali.

Supponiamo di avere un sito in hosting che memorizza i dati sensibili degli utenti (tra cui le password) su un database server. E' giusto che il provider del servizio di hosting abbia accesso ai nostri files e al nostro database, altrimenti non sarebbe in grado di fornirci supporto in caso di problemi tecnici. Uno dei nostri clienti/utenti ci potrebbe allora chiedere - “le persone che hanno accesso a quel computer (il server remoto) possono conoscere la mia password?”. Se abbiamo provveduto a criptare le password potremo rassicurarlo dicendo - “no, nemmeno io so che password hai inserito”.

Vediamo uno dei tanti modi di garantire questa sicurezza, considerando il caso di un sito realizzato in PHP appoggiato su un database MySql.

La prima cosa da fare, quando registriamo un nuovo utente, è inserire la sua password in modo criptato, usando ad esempio una query come questa

INSERT INTO clienti (id, login, pwd) VALUES ('1','pippo',md5('ciao'));

notiamo la funzione md5 che prende come argomento la stringa “ciao” (cioè la password). Il risultato della funzione md5 ritorna una versione criptata, che per la precisione si chiama chiave hash (o semplicemente hash) della stringa passata in ingresso. Per vedere cosa abbiamo inserito possiamo sbirciare la riga nella tabella clienti, oppure potremmo semplicemente eseguire la query

SELECT MD5('ciao') ;

che dovrebbe dare come risultato questi 32 caratteri

6e6bc4e49dd477ebc98ef4046c067b5f

la stringa qui sopra è la chiave hash associata dal valore ciao. Si può anche dire che la stringa è il risultato della funzione hash MD5 applicata sul valore ciao. Rimandiamo gli approfondimenti e vediamo subito come applicare lo stesso concetto nelle pagine PHP. Prendiamo una pagina PHP qualsiasi e aggiungiamo il codice

<?php echo 'MD5='.md5('ciao'); ?>

se non abbiamo fatto errori verrà stampata esattamente la stessa sequenza di 32 caratteri ottenuta come risultato dell'ultima query. Eccoci giunti al punto saliente della discussione:

Se nel database inseriamo la chiave hash di 32 caratteri, allora potremo verificare (lato PHP) che la password inserita dall'utente sia corretta confrontando i due valori hash, senza la necessità di conoscere il valore digitato dall'utente

il codice controllo da inserire nella pagina PHP potrebbe essere

$sql = mysql_query("SELECT pwd FROM clienti WHERE login='pippo'");

$array = mysql_fetch_row($sql) ;

$entered = md5($_POST['password']) ;

if ($array[0] == $entered) echo "OK" ;

else echo "NOT OK";

dove la variabile password potrebbe arrivare dal normale POST di una form HTML (dopo aver ovviamente verificato che tutte le variabili siano settate, ad esempio usando isset).

Questa soluzione ha qualcosa di magico e geniale al tempo stesso. La pagina PHP e il database dispongono entrambi di uno strumento (la funzione hash) che trasforma stringhe in chiaro in stringhe criptate, e questo ci permette di confrontare sempre e comunque i valori criptati, senza mai sapere “cosa” stiamo confrontando! Abbiamo precisato questo aspetto perché le prime volte che si approccia la criptazione è lecito chiedersi - “come faccio a decriptare ciò che ho precedentemente criptato?”. L'eleganza del meccanismo sta proprio nel fatto che non serve decriptare nulla, anzi: non serve nemmeno sapere come decriptare!

A questo punto la domanda dovrebbe sorgere spontanea: ma è possibile decriptare?

La risposta ufficiale è no, ma con qualche riserva. Se per decriptare intendiamo il procedimento di trovare la parola d'ordine (nel nostro caso ciao) partendo dalla chiave hash (i 32 caratteri più sopra), purtroppo la risposta diventa - “sì, è possibile decriptare”. Questo perché chi ha accesso al database può leggere il valore della chiave hash, e se proprio ha tempo da perdere, può lanciare qualche software che si metta a provare tutte le parole possibili (o quasi) fino a che il risultato della funzione hash coincide con quello atteso. Esemplificando un software di questo tipo produrrebbe un output del genere:

MD5(“aaa”) = 47bce5c74f589f4867dbd57e9ca9f808 NO

MD5(“aab”) = e62595ee98b585153dac87ce1ab69c3c NO

...

MD5(“ciao”)= 6e6bc4e49dd477ebc98ef4046c067b5f BINGO!

provando tutte le stringhe d'ingresso possibili, e non solo quelle di 3-4 lettere come nell'esempio qui sopra. Questa tecnica si chiama forza bruta, ma non deve preoccuparci per i seguenti motivi

  • Ne vale la pena? Chiediamoci cosa stiamo memorizzando nel database: istruzioni per lanciare testate nucleari? Conti correnti milionari? Se il gioco non vale la candela è alquanto improbabile che qualcuno voglia spendere ore o giorni a forzare una password
  • Chi lo può fare? Per riconoscere il valore corretto che ritorna la chiave hash desiderata occorre ovviamente conoscere la chiave hash stessa! Nel nostro caso la chiave è memorizzata nel database, e come dicevamo più sopra, solamente noi e gli amministratori di sistema abbiamo accesso a questi dati
  • Quale algortimo? Abbiamo visto un esempio a scopo didattico, usando l'algoritmo MD5, che è piuttosto vecchiotto. Se crediamo che i nostri dati siano davvero sensibili, possiamo usare algoritmi più moderni e sicuri, che rendono quasi impossibile forzare la password

Ci sentiamo più sicuri? No? Se l'MD5 non vi basta, nelle prossime puntate vedremo come usare altri sistemi di criptazione, che pur richiedondo poche righe di codice, possono rafforzare la sicurezza dei nostri dati.