Attenzione a non confondere trust store e key store.
Il trust store serve per la validazione del certificato del server che chiami. In generale, il certificato esibito dal server dev’essere validabile, nel senso di essere emesso da una CA nota al “sistema”. Per sistema si intende la JRE, che però, a seconda dell’ambiente di installazione, potrebbe avere un elenco di certificati propri o (come più spesso accade in Linux, ad esempio), usare quelli del sistema operativo. Ora non ricordo se SdI in test usi certificati self-signed, certificati emessi da una CA “di test”, o emessi da una CA che fa capo ad una root CA ben nota oppure no. Nell’ultimo caso (quello più facile), l’errore che ricevi potrebbe significare che stai usando una versione di Java non aggiornata o, altrimenti, che l’elenco dei certificati installati nel tuo sistema non è sufficientemente aggiornato. Ad esempio in Ubuntu dovresti aggiornare i pacchetti ca-certificates
e ca-certificates-java
(forse uno tira dentro l’altro, non ricordo). Se, invece, il certificato del server SdI usato in test non è emesso da CA nota, devi recuperarti il certificato della CA radice utilizzata (di solito SdI li fornisce in questo caso - se il certificato è self-signed, è il certificato stesso) e crearti un truststore JKS dove dentro ci metti solo quel certificato e poi lo specifichi da riga di comando come stai facendo. Se ancora non funziona, prova ad aggiungerci l’eventuale certificato CA intermedio, se c’è.
Alternativamente alla specifica mediante riga di comando come stai facendo, potresti aggiungere il certificato CA in questione all’elenco dei certificati di sistema (vedi ad esempio qui per Ubuntu), ma dipende dall’ambiente che stai usando, perché chiaramente vai a rendere come attendibile per l’intero sistema un certificato “di test”.
Tuttavia, nella comunicazione con SdI entra in gioco anche il certificato client che ti serve per comunicare con loro. In questo caso il certificato client che ti forniscono, assieme alla tua chiave privata (che hai generato quando hai inviato loro la CSR con la richiesta di emissione del certificato) vanno messi in un key store (qui di solito si usa il formato p12, ma può essere anche un jks) che va specificato a livello di socket factory che usi per creare le connessioni con cui ti connetti ai loro web service. Qui a seconda della tecnologia che usi le tecniche potrebbero essere diverse.
Una proof-of-concept per creare una SSLSocketFactory
(dove clientCertificateArchiveInputStream
è un InputStream
che punta ad un file .p12 con chiave privata e certificato client):
public static SSLSocketFactory createClientCertificateSslSocketFactory(
final InputStream clientCertificateArchiveInputStream,
final char[] clientCertificateArchivePassword,
final Provider provider) throws IOException, CertificateException,
UnrecoverableKeyException {
final KeyManagerFactory keyManagerFactory;
try {
keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
final KeyStore keyStore;
try {
keyStore = KeyStore.getInstance("PKCS12");
} catch (final KeyStoreException e) {
// no PKCS12 provider - should never happen
throw new RuntimeException(e);
}
keyStore.load(clientCertificateArchiveInputStream,
clientCertificateArchivePassword);
try {
keyManagerFactory.init(keyStore,
clientCertificateArchivePassword);
} catch (final KeyStoreException e) {
// we do not expect this to happen
throw new RuntimeException(e);
}
final SSLContext context = provider != null
? SSLContext.getInstance("TLS", provider)
: SSLContext.getInstance("TLS");
try {
context.init(keyManagerFactory.getKeyManagers(), null,
new SecureRandom());
} catch (final KeyManagementException e) {
// another unexpected failures
throw new RuntimeException(e);
}
return context.getSocketFactory();
} catch (final NoSuchAlgorithmException e) {
// missing or problematic SunX509 provider - should never happen
throw new RuntimeException(e);
}
}
dopodiché, se ad esempio usi Spring Web Service dovrai impostare un opportuno WebServiceMessageSender
, che nel metodo init()
crea una SSLSocketFactory
come sopra, e nel metodo prepareConnection(HttpURLConnection)
la imposta sulla Connection
:
protected void prepareConnection(final HttpURLConnection connection)
throws IOException {
// if the client certificate is present, make the connection use it
if (sslSocketFactory != null
&& connection instanceof HttpsURLConnection)
((HttpsURLConnection) connection)
.setSSLSocketFactory(sslSocketFactory);
super.prepareConnection(connection);
// set the timeouts
connection.setConnectTimeout(connectTimeout);
connection.setReadTimeout(readTimeout);
}
Spero di averti dato qualche input per risolvere il tuo problema.