Crittografia in Java

JCA o Java Cryptography Architecture è il framework java per la crittografia che fa parte della API di sicurezza di Java, ed è stato introdotto nei pacchetti java.securityjava.crypto. JCA fornisce le principali funzionalità di crittografia quali: firma digitale, message digest (hash), certificati e convalida dei certificati, crittografia (simmetrica/blocco asimmetrico/cifrari a flusso), generazione e gestione di chiavi, generazione di numeri casuali, e molto altro.

Nel presente articolo sono descritte le funzionalità di base per la criptazione e  decriptazione, sia simmetrica che asimmetrica.

Generazione di Chiavi Crittografiche

La chiave crittografica è una informazione che è utilizzata in un algoritmo di criptazione e decriptazione per generare un testo cifrato da uno in chiaro. Possono avere lunghezza variabile in funzione dell’algoritmo utilizzato ed in generale si parla di chiavi simmetriche o asimmetriche. JCA offre le funzionalità per la generazione di entrambe le tipologie di chiavi.

La classe KeyGenerator espone le funzionalità per la generazione di chiavi simmetriche. Per istanziarla possiamo invocare il metodo getInstance() specificando l’algoritmo che si intende utilizzare. Si noti che questa modalità di istanziazione di oggetti in JCA è molto comune perché il framework è progettato in modo da demandare l’implementazione degli algoritmi a provider esterni registrati. La stringa di input specifica l’implementazione (ovvero algoritmo) richiesta e se non presente il metodo restituisce l’eccezione NoSuchAlgorithmException.

Il codice seguente generare una chiave simmetrica.

Gli algoritmi disponibili nel JCA, con le rispettive lunghezze in bit delle chiavi, sono i seguenti:

  • AES (128)
  • DES (56)
  • DESede (168)
  • HmacSHA1
  • HmacSHA256

Per la generazione di una coppia di chiavi asimmetriche (pubblica e privata) la classe del framework da utilizzare è KeyPairGenerator, come mostrato nel codice seguente. La coppia di chiavi è restituita nel bean KeyPair caratterizzata da due sole proprietà in sola lettura: publicKey e privateKey.

Gli algoritmi supportati dal framework sono:

  • DiffieHellman (1024)
  • DSA (1024)
  • RSA (1024, 2048)

Crittografia Simmetrica

La crittografia simmetrica o crittografia a chiave privata indica un metodo di cifratura molto semplice in cui la chiave utilizzata per cifrare il testo in chiaro è la stessa utilizzata per decifrarlo. La figura seguente mostra il processo appena descritto.

crittazione simmetrica

La classe che espone i servizi per la crittazione e decrittazione è java.crypto.Cipher. Come già visto per ottenerne una istanza è necessario invocare il metodo getInstance() passando una stringa (transformation) che indica il set di operazioni che devono essere eseguite sull’input per ottenere l’output richiesto. Tale stringa ha il formato “algorithm/mode/padding” dove:

  • algorithm indica l’algoritmo di crittazione desiderato;
  • mode indica il metodo di crittazione che può essere a Blocchi di Cifre o a Flusso di Cifre;
  • padding nel caso di cifratura a blocchi indica l’algoritmo da utilizzare per “riempire” il blocco finale.

Il codice seguente mostra un esempio di cifratura simmetrica con algoritmo di cifratura a blocchi AES in modalità CBC. Il metodo CBC combina il blocco corrente con l’esito della crittazione del blocco precedente, quindi necessita di un vettore di inizializzazione per cifrare il primo blocco.

L’oggetto Cipher può essere utilizzato sia per criptare che per decriptare. La selezione della modalità operativa si effettua passando il parametro mode al metodo init(), che nel nostro esempio assume il valore ENCRYPT_MODE. A tale metodo passiamo anche la chiave da utilizzare per l’operazione ed il vettore di inizializzazione.

Per eseguire l’operazione inversa di decriptazione il codice java sarà simile al precedente ma l’operazione specificata nel metodo init() dovrà essere DECRYPT_MODE.

Si noti che con tale algoritmo la sorgente e la destinazione oltre a doversi scambiare in modo sicuro la chiave simmetrica, devono anche conoscere il vettore di inizializzazione.

Per completezza si riporta anche il codice per la generazione del vettore di inizializzazione, in cui si utilizza la classe SecureRandom che utilizza algoritmi per la generazione di numeri casuali non facilmente predicibile.

Crittografia Asimmetrica

La crittografia asimmetrica, conosciuta anche come crittografia a chiave pubblica/privata o solamente crittografia a chiave pubblica, è un metodo di criptazione in cui si utilizza una coppia di chiavi diverse, una pubblica ed una privata, in grado di funzionare solo l’una con l’altra. La chiave privata è utilizzabile solo dal legittimo possessore, mentre quella pubblica è resa nota a chiunque. In pratica, ciò che viene cifrato da una chiave può essere decifrato solo con l’altra chiave della coppia e viceversa.

Sebbene più sicura, in quanto elimina il problema della condivisione della chiave tra mittente e destinatario, risulta computazionalmente  più onerosa rispetto ad un algoritmo a chiave simmetrica. Per questo motivo è generalmente utilizzato per cifrare solamente pochi blocchi di dati, come ad esempio la una chiave simmetrica. E’ poi la chiave simmetrica(detta anche chiave di sessione) che viene utilizzata per la criptazione del testo, come mostrato nell’immagine seguente.

criptazione asimmetrica

 Il codice java per le operazione di cifratura e decifratura è mostrato di seguito.

Si noti che, oltre alla tipologia della chiave, nei due metodo non è presente il vettore di inizializzazione.

Base 64 Encoding

Tutti i metodi di cifratura e decifratura che abbiamo visto ricevono in input e restituiscono in output un array di byte. Per poter persistere o trasferire tale array attraverso un media che tratta dati testuali è necessario convertirlo in Base 64. Questo per garantire che il dato rimanga intatto durante il trasporto. Il codice per eseguire il coding e l’encoding in Base 64 è il seguente:

Trasmissione del Messaggio

In conclusione inserendo i metodi descritti sopra in una classe CryptoHelper le operazioni di criptazione e decriptazione avvengono nel modo seguente:

L’output generato sarà:

Codice Sorgente

La classe è disponibile qui CryptoHelper.java

How useful was this post?

Click on a star to rate it!

Average rating 4.5 / 5. Vote count: 17

No votes so far! Be the first to rate this post.

As you found this post useful...

Follow us on social media!