Finalmente sono riuscito a risolvere tutti i problemi, quindi risponderò alla mia domanda. Queste sono le impostazioni / i file che ho usato per gestire i miei particolari problemi;
Il keystore del client è un file in formato PKCS # 12 contenente
- Il certificato pubblico del cliente (in questo caso firmato da una CA autofirmata)
- La chiave privata del cliente
Per generarlo ho usato il pkcs12
comando di OpenSSL , per esempio;
openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 -name "Whatever"
Suggerimento: assicurati di ottenere l'ultimo OpenSSL, non la versione 0.9.8h perché sembra che soffra di un bug che non ti consente di generare correttamente i file PKCS # 12.
Questo file PKCS # 12 verrà utilizzato dal client Java per presentare il certificato client al server quando il server ha esplicitamente richiesto al client di eseguire l'autenticazione. Vedi l' articolo di Wikipedia su TLS per una panoramica del funzionamento effettivo del protocollo per l'autenticazione del certificato client (spiega anche perché qui abbiamo bisogno della chiave privata del client).
Il truststore del client è un file in formato JKS semplice contenente i certificati CA principali o intermedi . Questi certificati CA determineranno con quali endpoint ti sarà consentito comunicare, in questo caso consentiranno al tuo client di connettersi a qualsiasi server che presenta un certificato che è stato firmato da una delle CA del truststore.
Per generarlo puoi usare il keytool Java standard, per esempio;
keytool -genkey -dname "cn=CLIENT" -alias truststorekey -keyalg RSA -keystore ./client-truststore.jks -keypass whatever -storepass whatever
keytool -import -keystore ./client-truststore.jks -file myca.crt -alias myca
Utilizzando questo truststore, il client proverà a eseguire una stretta di mano SSL completa con tutti i server che presentano un certificato firmato dalla CA identificata da myca.crt
.
I file sopra sono esclusivamente per il client. Quando si desidera impostare anche un server, il server necessita dei propri file di chiavi e truststore. In questo sito Web è disponibile una guida dettagliata per l'impostazione di un esempio pienamente funzionante sia per un client che per un server Java (utilizzando Tomcat) .
Problemi / Osservazioni / Consigli
- L'autenticazione del certificato client può essere applicata solo dal server.
- ( Importante! ) Quando il server richiede un certificato client (come parte dell'handshake TLS), fornirà anche un elenco di CA affidabili come parte della richiesta di certificato. Quando il certificato client che si desidera presentare per l'autenticazione non è firmato da una di queste autorità di certificazione , non verrà affatto presentato (a mio avviso, si tratta di un comportamento strano, ma sono sicuro che ci sia una ragione). Questa era la causa principale dei miei problemi, poiché l'altra parte non aveva configurato correttamente il proprio server per accettare il mio certificato client autofirmato e ritenevamo che il problema fosse alla mia fine per non aver fornito correttamente il certificato client nella richiesta.
- Ottieni Wireshark. Ha un'eccellente analisi dei pacchetti SSL / HTTPS e sarà di grande aiuto per il debug e la ricerca del problema. È simile
-Djavax.net.debug=ssl
ma è più strutturato e (probabilmente) più facile da interpretare se non ti senti a tuo agio con l'output di debug SSL Java.
È perfettamente possibile utilizzare la libreria httpclient di Apache. Se si desidera utilizzare httpclient, è sufficiente sostituire l'URL di destinazione con l'equivalente HTTPS e aggiungere i seguenti argomenti JVM (che sono gli stessi per qualsiasi altro client, indipendentemente dalla libreria che si desidera utilizzare per inviare / ricevere dati su HTTP / HTTPS) :
-Djavax.net.debug=ssl
-Djavax.net.ssl.keyStoreType=pkcs12
-Djavax.net.ssl.keyStore=client.p12
-Djavax.net.ssl.keyStorePassword=whatever
-Djavax.net.ssl.trustStoreType=jks
-Djavax.net.ssl.trustStore=client-truststore.jks
-Djavax.net.ssl.trustStorePassword=whatever