Gestione delle password tarmite funzioni hash

Dal punto di vista matematico le funzioni hash sono funzioni non iniettive, ovvero non invertibili, che mappano una stringa di lunghezza arbitraria in una di lunghezza predefinita detta impronta o message digest. Esistono diversi algoritmi che realizzano funzioni hash (es. MD5 e SHA-1) con diverse proprietà e caratteristiche che ne determinano l’uso più appropriato.

La funzione di hash ideale deve avere tre proprietà fondamentali:

  1. essere estremamente semplice da calcolare a partire da un qualunque tipo di dato;
  2. essere estremamente difficile o quasi impossibile risalire al testo che ha portato ad un dato hash;
  3. essere estremamente improbabile che due messaggi differenti, anche simili, abbiano lo stesso hash.

In informatica tali funzioni sono utilizzate in diversi ambiti, ad esempio:

  • come funzioni crittografiche per la generazione dell’impronta di un documento che deve essere firmato digitalmente;
  • nelle comunicazioni tra agenti software dove l’hash del messaggio viene trasmesso insieme allo stesso, in modo che il ricevente possa ricalcolarlo e verificare l’integrità del messaggio;
  • nella programmazione per l’implementazione delle tabelle di hash o dizionari, che sono strutture dati che risultano molto efficienti nelle le operazioni di ricerca.

L’applicazione più semplice delle funzioni di hash è sicuramente la conservazione della password utente in una applicazione che richiede credenziali per l’accesso. In generale in applicazioni enterprise l’autenticazione è demandata a sistemi esterni come Active Directory, LDAP o più complessi Identity Management System. Applicazioni meno importanti, però, hanno la necessità di implementare autonomamente il proprio sistema di autenticazione e devono quindi conservare le password utente nella propria base dati. Questo può avvenire o utilizzando un base dati che supporta la crittografazione delle informazioni, oppure utilizzando funzioni di hash, ottenendo, a mio avviso, con poco effort un sistema comunque efficace, economico e soprattutto sicuro.

L’idea alla base dell’algoritmo è mostrato nella figura seguente. In fase di registrazione la password utente subisce il processo di hashing e l’impronta viene conservato nella base dati. In fase di autenticazione la password inserita subisce la medesima funzione di hashing e l’impronta generata è confrontato con quanto memorizzato in base dati. La sicurezza dell’algoritmo è garantita dal fatto che il sistema non conosce la password utente ma solamente la sua impronta che, per sua natura, non è invertibile.

Hash Autentication

La realizzazione di quanto detto è molto semplice in quanto java mette a disposizione un intero package in cui sono implementate diverse funzioni per la sicurezza, che toccano aree quali: crittografia, infrastruttura a chiave pubblica, comunicazione sicura, autenticazione e controllo degli accessi. In particolare la classe che a noi interessa è java.security.MessageDigest che fornisce una implementazione di diverse funzioni di hash. L’algoritmo di hashing che utilizzeremo è lo SHA-1 e la funzione di scramble della password e di autenticazione sono mostrati nel codice seguente.

Un main di esempio per testare quanto detto è:

Che produce un output del tipo: