Importazione Certificati SSL sul Java Keystore (JKS)

Importazione Certificati SSL sul Java Keystore (JKS)
Importazione Certificati SSL sul Java Keystore (JKS)

Il meccanismo solitamente adottato per la protezione dei dati End-To-End sulla rete internet è basato sull’utilizzo del protocollo Transport Layer Security (TLS) e il suo predecessore Secure Sockets Layer (SSL), entrambi sono dei protocolli crittografici che permettono una comunicazione sicura e una integrità dei dati su reti TCP/IP, cifrano la comunicazione dalla sorgente alla destinazione sul livello di trasporto.

Una tipica connessione TLS/SSL (per esempio via browser internet) prevede un tipo di autenticazione denominata unilaterale: solo il server è autenticato (il client conosce l’identità del server), ma non vice-versa (il client rimane anonimo e non autenticato). Il client (browser web, EmailUI, Java Client, etc…) valida il certificato del server controllando la firma digitale dei certificati del server, verificando che questa sia valida e riconosciuta da una Certificate Authority conosciuta utilizzando una cifratura a chiave pubblica.

In Figura 1 è illustrato il caso in cui il browser stabilisce una connessione verso un sito web (o applicazione web) che espone un certificato rilasciato da una Certificate Authority non riconosciuta. È lasciata all’utente l’azione da intraprendere, se continuare o abbandonare la connessione, è inoltre possibile per l’utente, istruire il browser affinché consideri trusty (fidato) il certificato.

Figura 1 - Alert del Browser per Certificate Authority non riconosciuta

Figura 1 – Alert del Browser per Certificate Authority non riconosciuta

In Figura 2 sono invece illustrati i dettagli sulla catena di certificazione (Certificate Chain). Il browser (in questo caso Safari) ha tutte la ragioni a emettere un warning, in effetti, la CA (Certificate Authority)  indicata è di pura invenzione.

 

Figura 2 - Dettagli del certificato SSL

Figura 2 – Dettagli del certificato SSL

Nel caso in cui volessimo compiere connessioni TLS/SSL attraverso un software scritto in Java (in qualità di client), è necessario accertarsi che tutta la Certificate Chain (o catena di certificazione) sia soddisfatta o comunque bisogna far in modo da considerare affidabile il certificato. Vorrei ricordare che l’operazione di rendere trusted un certificato deve essere eseguita in modo consapevole, potreste introdurre dei problemi di sicurezza.

Al contrario dell’autenticazione unilaterale, la mutua autenticazione si riferisce a due parti che si autenticano reciprocamente attraverso la verifica del certificato digitale fornito in modo che entrambe i partecipanti siano sicuri dell’identità altrui.

Per maggiori approfondimenti potreste leggere Liferay 7.2: Esempio di Two-Way SSL/TLS Mutual Authentication Client e nel video Liferay 7.2 – Gogo Shell Command for the Two-Way SSL/TLS Mutual Authentication mostro come eseguire l’esempio del progetto GitHub gogo-shell-tls-mutual-sample in semplici passaggi usando Docker e Docker Compose.

 

La piattaforma Java utilizza il sistema denominato Java Keystore per la gestione della sicurezza o meglio, per lo storage e amministrazione di tutto ciò che ruota intorno ai certificati digitali (Public/Private Key, Root CA, CSR, etc…). L’implementazione di default del Java Keystore è basata su file, quest’ultimo è in un formato proprietario denominato JKS. Per coloro che volessero approfondire l’argomento sicurezza in Java, consiglio la lettura di JDK Security-Related APIs & Developer Guides che vi mostrerà tutte le nuove funzionalità e miglioramenti introdotti con Java 8.

La piattaforma Java prevede due tipi di Java Keystore che preferisco suddividere nel seguente modo:

  • Server side: Java Keystore che contiene solitamente le coppie di chiavi pubbliche/private dei certificati utilizzati dall’applicazione server. Il nome solitamente attribuito a questo repository è keystore;
  • Client side: Java Keystore che contiene i soli certificati utilizzati dalle applicazioni che agiscono come client. Il nome solitamente attribuito a questo repository è trustStore.

La posizione predefinita di entrambi i keystore è solitamente $JAVA_HOME/lib/security/. Per ragioni di semplicità, durante il corso dell’articolo farò riferimento in modo generico al nome keystore.

Il classico errore cui si va incontro quando la Certificate Chain non è soddisfatta, è un eccezione del tipo indicato di seguito. Questo tipo di eccezione è scatena perché non è stata trovata una Certification Path valida per la richiesta di connessione TLS/SSL eseguita.

Andiamo subito nel pratico e vediamo come affrontare uno scenario simile prendendo come esempio un recente articolo pubblicato sul mio blog, che mostrava come realizzare un client Java SOAP per il sistema di CRM SugarCRM. Gli esempi di connessione al servizio SOAP utilizzano il protocollo HTTP. Qualora facessimo uso del protocollo HTTPS per la connessione al servizio SOAP, andremmo incontro all’eccezione mostrata in precedenza. La soluzione al problema è molto semplice, occorre importare il certificato SSL sul proprio Java Keystore e segnarlo come affidabile. L’operazione è composta dai seguenti passi:

  1. Esportazione/Salvataggio del certificato server in formato DER (Distinguished Encoding Rules) X.509 sulla propria macchina o su quella che eseguirà la connessione SSL;
  2. Importazione del certificato server sul Java Keystore.

L’esportazione del certificato server può essere eseguita in svariati modi, forse la via più semplice è attraverso un comune browser (Firefox, Internet Explore, Safari, etc…). Riporto il post che spiega come eseguire l’operazione con Mozilla Firefox: Exporting Server Certificate to File in Firefox 3. In modo analogo è possibile procedere con l’esportazione del certificato server utilizzando i più comuni browser.

Il metodo da me preferito per esportare il certificato server in formato DER è l’utilizzo del tool openssl. È più che sufficiente una sola linea di comando, per motivi di leggibilità, riporto il comando suddiviso in 4 linee:

Una volta ottenuto il certificato server, occorre importare quest’ultimo sul Java Keystore utilizzando l’apposito tool che prende il nome di keytool (Keytool: Key and Certificate Management Tool). Ricordo che il keystore è il contenitore dei certificati digitali. Ognuno di voi potrebbe avere le configurazioni più disparate riguardo il Java Keystore, lo scenario qui proposto è quello base, keystore su file e su file custom, ovvero, creato dall’importazione del certificato server, lasciamo intatto il keystore di sistema.

Il comando sopra illustrato, creerà un nuovo keystore (protetto da password) all’interno del quale finirà il certificato server identificato con l’alias sugarcrm-fe-1. L’alias identifica in modo univoco l’item appena inserito, se volessimo fare un controllo sul buon esito dell’operazione dell’import, è sufficiente eseguire il seguente comando:

L’output del precedente comando sarà simile a quanto illustrato a seguire:

Nel caso in cui il certificato server non fosse stato importato con successo, il precedente comando avrebbe risposto con la seguente eccezione:

Se dovesse essere necessario è possibile ottenere l’intera catena di certificazione utilizzando il comando a seguire. Il comando creerà un file in formato PEM per ogni certificato che fa parte della catena di certificazione (o Certificate Chain). Questi certificati posso essere importati sempre con il comando keytool visto in precedenza.

A questo punto tutto è pronto per poter eseguire con successo la connessione al servizio SOAP over HTTPS. Poiché abbiamo utilizzato un keystore custom invece di sfruttare quello di sistema, è necessario istruire la JVM circa il keystore da utilizzare, non sarebbe neppure una cattiva idea quella d’impostare un livello di debug sul sottosistema SSL. I due argomenti che devono essere passati alla JVM sono quindi:

Dato che l’applicazione Java agisce in qualità di client, occorre specificare la locazione del keystore (che ricordo essere di tipo trustStore) attraverso la proprietà java.net.ssl.trustStore.

L’opzione di debug può aiutare a capire eventuali problemi in caso di malfunzionamento, è comunque utile per coloro che vogliono capire meglio il funzionamento del protocollo TLS/SSL. Sono tracciati tutti i messaggi scambiati tra il client ed il server per portare a termine la fase di handshake.

A seguire un estratto dell’output a fronte dell’esecuzione della classe SugarCRMSoapClient.java, che utilizza però l’endpoint in HTTPS del servizio SOAP (https://sugarcrm-fe-1.local/crm-6.1/service/v2/soap.php?wsdl).

Attraverso un esempio pratico e direi abbastanza realistico, abbiamo visto come sia semplice e immediato importare certificati digitali sul Java Keystore affinché le applicazioni TLS/SSL funzionino in maniera corretta.

Esistono svariati altri modi per gestire i certificati digitali, anche attraverso tool grafici, uno di questi che utilizzo molto spesso è KeyStore Explorer disponibile per tutte le piattaforme.

5 Condivisioni

Antonio Musarra

I began my journey into the world of computing from an Olivetti M24 PC (http://it.wikipedia.org/wiki/Olivetti_M24) bought by my father for his work. Day after day, quickly taking control until … Now doing business consulting for projects in the enterprise application development using web-oriented technologies such as J2EE, Web Services, ESB, TIBCO, PHP.

Potrebbero interessarti anche...