Buone pratiche di sicurezza: Crittografia simmetrica con AES in Java e Android

Patrick Favre-Bulle
Gen 6, 2018 – 11 min read

In questo articolo ti aggiornerò sull’Advanced Encryption Standard (AES), le modalità di blocco comuni, perché hai bisogno di padding e vettori di inizializzazione e come proteggere i tuoi dati dalla modifica. Infine vi mostrerò come implementare facilmente tutto questo con Java evitando la maggior parte dei problemi di sicurezza.

Cosa dovrebbe sapere ogni ingegnere software su AES

AES, conosciuto anche con il suo nome originale Rijndael, è stato selezionato dal NIST nel 2000 per trovare un successore del datato Data Encryption Standard (DES). AES è un cifratore a blocchi, cioè la crittografia avviene su gruppi di bit di lunghezza fissa. Nel nostro caso l’algoritmo definisce blocchi di 128 bit. AES supporta lunghezze di chiave di 128, 192 e 256 bit.

Ogni blocco passa attraverso molti cicli di trasformazione. Ometterò i dettagli dell’algoritmo qui, ma il lettore interessato è rimandato all’articolo di Wikipedia su AES. La parte importante è che la lunghezza della chiave non influenza la dimensione del blocco, ma il numero di ripetizioni dei cicli di trasformazione (la chiave a 128 bit è 10 cicli, 256 bit è 14)

Fino a maggio 2009, gli unici attacchi pubblicati di successo contro l’AES completo erano attacchi side-channel su alcune implementazioni specifiche. (Fonte)

Vuoi criptare più di un blocco?

AES cripta solo 128 bit di dati, ma se vogliamo criptare interi messaggi dobbiamo scegliere una modalità a blocchi con cui più blocchi possono essere criptati in un unico testo cifrato. La modalità a blocchi più semplice è Electronic Codebook o ECB. Utilizza la stessa chiave inalterata su ogni blocco in questo modo:

Immagine da Wikpedia

Questo è particolarmente brutto perché blocchi di testo in chiaro identici sono criptati in blocchi di testo cifrato identici.

Immagine crittografata con la modalità BCE La modalità blocco rivela i modelli dell’originale (provate voi stessi)

Ricordatevi di non scegliere mai questa modalità a meno che non criptiate solo dati più piccoli di 128 bit. Sfortunatamente è ancora spesso usato impropriamente perché non richiede di fornire un vettore iniziale (di cui parleremo più avanti) e quindi sembra essere più facile da gestire per uno sviluppatore.

Un caso deve essere gestito con le modalità a blocchi però: cosa succede se l’ultimo blocco non è esattamente 128 bit? È qui che entra in gioco il padding, cioè il riempimento dei bit mancanti del blocco. Il più semplice dei quali riempie semplicemente i bit mancanti con degli zeri. Non c’è praticamente nessuna implicazione di sicurezza nella scelta del padding in AES.

Cipher Block Chaining (CBC)

Quindi quali alternative a ECB ci sono? Per esempio c’è la CBC che fa lo XOR del blocco di testo in chiaro corrente con il blocco di testo cifrato precedente. In questo modo, ogni blocco di testo cifrato dipende da tutti i blocchi di testo in chiaro elaborati fino a quel punto. Usando la stessa immagine di prima il risultato sarebbe un rumore non distinguibile dai dati casuali:

L’immagine crittografata con la modalità a blocchi CBC sembra casuale

E allora il primo blocco? Il modo più semplice è usare un blocco pieno di zeri, ad esempio, ma poi ogni crittografia con la stessa chiave e lo stesso testo in chiaro darebbe come risultato lo stesso testo cifrato. Inoltre, se si riutilizza la stessa chiave per diversi testi in chiaro, sarebbe più facile recuperare la chiave. Un modo migliore è usare un vettore di inizializzazione casuale (IV). Questa è solo una parola di fantasia per dati casuali che sono circa la dimensione di un blocco (128 bit). Pensatelo come il sale della crittografia, cioè, un IV può essere pubblico, dovrebbe essere casuale e usato solo una volta. Ricorda però che non conoscere l’IV ostacolerà solo la decrittazione del primo blocco poiché il CBC XORs il testo cifrato e non il testo in chiaro del precedente.

Quando si trasmettono o persistono i dati è comune aggiungere semplicemente l’IV al messaggio cifrato attuale. Se sei interessato a come usare correttamente AES-CBC controlla la parte 2 di questa serie.

Modalità contatore (CTR)

Un’altra opzione è usare la modalità CTR. Questa modalità a blocchi è interessante perché trasforma un cifratore a blocchi in un cifratore a flusso, il che significa che non è richiesto alcun padding. Nella sua forma base tutti i blocchi sono numerati da 0 a n. Ogni blocco sarà ora criptato con la chiave, il IV (qui chiamato anche nonce) e il valore del contatore.

Immagine da Wikpedia

Il vantaggio è, a differenza del CBC, la crittografia può essere fatta in parallelo e tutti i blocchi dipendono dal IV non solo il primo. Un grande avvertimento è che un IV non deve mai essere riutilizzato con la stessa chiave perché un attaccante può banalmente calcolare la chiave usata da quello.

Posso essere sicuro che nessuno ha alterato il mio messaggio?

La dura verità: la crittografia non protegge automaticamente dalla modifica dei dati. In realtà è un attacco piuttosto comune. Leggete qui per una discussione più approfondita su questo problema.

Quindi cosa possiamo fare? Aggiungiamo semplicemente il codice di autenticazione del messaggio (MAC) al messaggio crittografato. Un MAC è simile a una firma digitale, con la differenza che la chiave di verifica e quella di autenticazione sono praticamente le stesse. Ci sono diverse varianti di questo metodo, la modalità che viene raccomandata dalla maggior parte dei ricercatori si chiama Encrypt-then-Mac. Cioè, dopo la crittografia viene calcolato un MAC sul testo cifrato e aggiunto. Di solito si usa Hash-based message authentication code (HMAC) come tipo di MAC. Per l’integrità/autenticità dobbiamo scegliere un algoritmo MAC, scegliere una modalità di crittografia, calcolare il mac e aggiungerlo. Anche questo è lento poiché l’intero messaggio deve essere elaborato due volte. Il lato opposto deve fare lo stesso, ma per decifrare e verificare.

Crittografia autenticata con GCM

Non sarebbe fantastico se ci fossero modalità che gestiscono tutta la roba dell’autenticazione per te? Fortunatamente c’è una cosa chiamata crittografia autenticata che fornisce contemporaneamente garanzie di riservatezza, integrità e autenticità dei dati. Una delle modalità a blocchi più popolari che supporta questo si chiama Galois/Counter Mode o GCM in breve (è ad esempio disponibile anche come suite di cifratura in TLS v1.2)

GCM è fondamentalmente la modalità CTR che calcola anche un tag di autenticazione sequenzialmente durante la cifratura. Questo tag di autenticazione è poi solitamente aggiunto al testo cifrato. La sua dimensione è una proprietà di sicurezza importante, quindi dovrebbe essere lunga almeno 128 bit.

È anche possibile autenticare informazioni aggiuntive non incluse nel testo in chiaro. Questi dati sono chiamati dati associati. Perché è utile? Per esempio i dati crittografati hanno una meta proprietà, la data di creazione, che viene usata per controllare se il contenuto deve essere ricrittografato. Un attaccante potrebbe ora cambiare banalmente la data di creazione, ma se viene aggiunta come dato associato, GCM verificherà anche questa informazione e riconoscerà il cambiamento.

Un’accesa discussione: Quale dimensione della chiave usare?

L’intuizione dice: più grande è, meglio è – è ovvio che è più difficile forzare brutalmente un valore casuale di 256 bit che un 128 bit. Con la nostra attuale comprensione, forzare brutalmente tutti i valori di una parola lunga 128 bit richiederebbe una quantità astronomica di energia, non realistica per chiunque in tempi ragionevoli (guardandoti, NSA). Quindi la decisione è fondamentalmente tra infinito e infinito volte 2¹²⁸.

AES ha in realtà tre distinte dimensioni di chiave perché è stato scelto come algoritmo federale americano adatto ad essere usato in varie aree sotto il controllo del governo federale americano. (…) Così i bei cervelli militari hanno avuto l’idea che ci dovessero essere tre “livelli di sicurezza”, in modo che i segreti più importanti fossero criptati con i metodi pesanti che meritavano, ma i dati di minor valore tattico potevano essere criptati con algoritmi più pratici, anche se più deboli. (…) Così il NIST ha deciso di seguire formalmente i regolamenti (chiedere tre dimensioni di chiave) ma di fare anche la cosa intelligente (il livello più basso doveva essere infrangibile con la tecnologia prevedibile)(Fonte)

L’argomento segue: un messaggio criptato AES probabilmente non sarà rotto dalla forza bruta della chiave, ma da altri attacchi meno costosi (attualmente non conosciuti). Questi attacchi saranno dannosi per la modalità di chiave a 128 bit come per la modalità a 256 bit, quindi scegliere una chiave più grande non aiuta in questo caso.

Quindi fondamentalmente la chiave a 128 bit è abbastanza sicura per la maggior parte dei casi d’uso con l’eccezione della protezione del computer quantistico. Inoltre l’uso di 128 bit cripta più velocemente di 256 bit e la programmazione delle chiavi a 128 bit sembra essere meglio protetta contro gli attacchi alle chiavi correlate (tuttavia questo è irrilevante per la maggior parte degli usi nel mondo reale).

Come nota a margine: attacchi al canale laterale

Gli attacchi al canale laterale sono attacchi che mirano a sfruttare problemi specifici di certe implementazioni. Gli schemi di cifratura in sé non possono essere intrinsecamente protetti contro di essi. Semplici implementazioni di AES possono essere soggette ad attacchi di temporizzazione e caching, tra gli altri.

Per fare un esempio molto semplice: un semplice algoritmo che è soggetto ad attacchi di temporizzazione è un metodo equals() che confronta due array di byte segreti. Se il equals() ha un ritorno rapido, cioè dopo la prima coppia di byte che non corrispondono termina il ciclo, un attaccante può misurare il tempo che impiega il equals() a completare e può indovinare byte per byte fino a quando tutti corrispondono.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *