Generazione di One Time Password in Java

Quando si parla di One Time Password (OTP), ovvero di password o pin utilizzabili per una unica sessione di login o transazione, gli standard di riferimento sono due:

  1. HOTP (HMAC-based One-time Password) pubblicato dalla Internet Engineering Task Force (IETF) nella RFC 4226;
  2. TOTP (Time-based One-time Password) una estensione di HOTP pubblicato dalla Internet Engineering Task Force (IETF) nella RFC 6238.

HOTP

Come specificato nel nome lo standard HOTP per la generazione di una OTP si basa sull’utilizzo dell’algoritmo HMAC.  Gli elementi in gioco quando si definiscono le specifiche per l’utilizzo di tale standard sono quindi le seguenti:

  • La funzione crittografica di hashing H utilizzato nell’HMAC che per default è lo SHA-1;
  • La chiave crittografica K di lunghezza arbitraria che deve rimanere segreta e nota esclusivamente al server e, a seconda dell’utilizzo che si fa dell’OTP, al client;
  • La lunghezza d dell’OTP che si vuole ottenere che, considerando che in genere si vuole garantita la human readability della password, può essere compresa tra 6 e 10 caratteri.

L’algoritmo è molto semplice e prevede l’utilizzo di un contatore (di eventi) che viene incrementato ad ogni generazione della password. Tale contatore viene cifrato con HMAC-SHA1 generando una sequenza di 160 bit ovvero 20 byte. La specifica prevede poi una sequenza di operazioni che riducono il numero di byte per ottenere un OTP leggibile nel seguente modo:

  1. Gli ultimi 4 bit, ovvero quelli che appartengono al byte 19° della sequenza, sono utilizzati come offset.
  2. I byte dall’offset all’offset + 4 sono estratti dalla sequenza e concatenati. Al primo di questi è rimosso il bit più significativo. Complessivamente si ottengono 31 bit.
  3. Alla sequenza risultante viene applicato l’operazione di modulo con 10d che elimina i bit più significativi ottenendo un OTP di lunghezza d.

Il codice java che esegue le operazioni appena descritte è mostrato di seguito. Per chiarezza si ricorda che una variabile di tipo long in java occupa 8 byte mentre una di tipo int ne occupa 4.

Caso Pratico

Per comprendere i diversi step dell’algoritmo facciamo un caso pratico e supponiamo che il nostro contatore sia arrivato al valore  1876876 . La sequenza di operazioni è descritta di seguito con l’ausilio della figura seguente.

Iniziamo con l’osservare che il valore 1876876 di tipo long occupa 8 byte, i quali una volta attraversato il processo crittografico HMAC-SHA1, divengono una sequenza di 20 byte. Si noti che si tratta di byte con segno, ovvero rappresentati in complemento a 2.

[54, -122, 120, 91, 76, 15, 68, 11, -64, -35, -67, 20, -87, 69, 87, -109, 32, -49, -69, -8]

Quindi si recuperano gli ultimi 4 bit della sequenza (step 1 della figura) accedendo al 20-esimo byte, ovvero -8 (11111000 in binario in complemento a due), ed eseguendo una operazione di AND bit a bit con 00001111. Il risultato è 8 quindi i byte coinvolti nei successivi step del processo sono quelli che vanno dalla posizione 9 alla 13, ovvero:

[-64, -35, -67, 20]

Complessivamente il bit sono 32 ma l’algoritmo ne richiede 31. Quindi il primo byte -64 è messo in AND con 0x7F (step 2 della figura)  mentre gli altri -35, -67 e 20 sono mesis in AND con 0xFF (step 4, 6 e 8 della figura). I risultati di tali operazioni vengono poi concatenati con operazioni di OR e opportune operazioni di SHIFT a sinistra di 8 bit, fino ad ottenere il valore decimale 1088273684.

Ultimo step del processo è l’operazione di modulo per 106 che determina la rimozione delle cifre più significative oltre la 6°. L’OTP generato sarà quindi  273684 .

TOTP

Questo algoritmo si basa HOTP con la differenza che come fattore variabile non viene utilizza un contatore di eventi, bensì il tempo. Nella pratica vengono considerati degli incrementi, chiamati intervalli, che di solito sono di 30 o 60 secondi. Allo scadere di ogni intervallo un contatore è incrementato ed utilizzato per generare una nuova OTP con HOTP. Questo vuol dire che ogni OTP è valida per la durata di tutto l’intervallo al termine del quale scade.

Il codice per la generazione dell’OTP in questo caso è molto semplice, la sola complicazione è ottenere l’intervallo utilizzato come contatore. Considerando 30 secondi come validità dell’OTP il codice sarà:

Di seguito sono mostrati alcuni esempi di TOTP generati ogni 30 secondi:

Codie Sorgente

Il codice sorgente del progetto è disponibile qui otp.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

*