Qual è un esempio di SSL Java bidirezionale?
Secure Sockets Layer (SSL) è una tecnologia di sicurezza standard per stabilire un collegamento crittografato tra un server e un client. È ampiamente applicata nelle transazioni che coinvolgono informazioni sensibili o personali come numeri di carte di credito, credenziali di accesso e numeri di previdenza sociale. La crittografia può essere applicata in una sola direzione o in entrambe, a una o due vie. Nell'SSL unidirezionale, il cliente conferma l'identità del server mentre l'identità del cliente rimane anonima. Nell'SSL bidirezionale, detto anche SSL reciproco, il cliente conferma l'identità del server e il server conferma l'identità del cliente.
L'SSL bidirezionale inizia con un "hello" dal client al server. Il server risponde con un "hello" abbinato al suo certificato pubblico. Il client verifica il certificato ricevuto utilizzando i certificati memorizzati nei TrustStore del client. Se la convalida del certificato del server ha esito positivo, il client presenta i certificati memorizzati nei propri KeyStores. Il server convalida il certificato ricevuto utilizzando i TrustStores del server. Il server decifra le chiavi di sessione utilizzando la chiave privata del server per stabilire una connessione sicura.
Java utilizza Java Keystore (JKS), un database protetto da password per certificati e chiavi. Ogni voce deve essere identificata da un alias unico. Keystore fornisce le credenziali.
Java utilizza anche il Truststore che si trova in $JAVA_HOME/lb/security/cacerts. Memorizza le voci delle Autorità di certificazione (CA) e i certificati autofirmati da terze parti fidate. Truststore verifica le identità dei server.
Java fornisce anche keytool, uno strumento a riga di comando per la manutenzione del Keystore e del Truststore.
È possibile eseguire TrustStore utilizzando il seguente codice. Sostituire $CERT_ALIAS e $CERT_PASSWORD rispettivamente con l'alias e la password.
1) Se non si dispone del certificato del server, si usa openssl per recuperarlo
echo -n | openssl s_client -connect SERVERDOMAIN:PORT -servername SERVERDOMAIN
-chiave myclient.key -cert myclient.cert.pem
| sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'
| tee "server.crt"
2) Creare il Truststore dal certificato del server
keytool -import -alias $CERT_ALIAS -file server.crt -keystore truststore.jks -deststorepass $CERT_PASSWORD
Quindi, generare l'IdentityStore. Sostituire $CERT_ALIAS e $CERT_PASSWORD rispettivamente con l'alias e la password.
1) Concatenare tutti i certificati in un unico file PEM
cat intermediate.cert.pem myclient.cert.pem myclient.key > full-chain.keycert.pem
2) Generare il keystore PKCS12 con l'alias dell'url del server
openssl pkcs12 -export -in full-chain.keycert.pem
-out full-chain.keycert.p12
-password env:$CERT_PASSWORD
-nome $CERT_ALIAS
-noiter -nomaciter
3) Convertire .p12 in .jks
keytool -importkeystore -srckeystore full-chain.keycert.p12
-srcstoretype pkcs12 -srcalias $CERT_ALIAS -srcstorepass $CERT_PASSWORD
-destkeystore identity.jks -deststoretype jks
-deststorepass $CERT_PASSWORD -destalias $CERT_ALIAS
Questo codice Java carica Keystore e Truststore in un contesto SSL personalizzato, crea una SSLConnectionSocketFactory e la lega a un HttpClient.
public class SSLMutualAuthTest {
publicSSLMutualAuthTest() {
// TODO Auto-generated constructor stub
}
public static void main (String[] args) {
System.out.println("MagicDude4Eva test di autenticazione SSL a 2 vie / reciproca");
org.apache.log4j.BasicConfigurator.configure();
Logger.getRootLogger().setLevel(Level.INFO);
prova {
Stringa CERT_ALIAS = "myalias", CERT_PASSWORD = "mypassword";
KeyStore identityKeyStore = KeyStore.getInstance("jks");
FileInputStream identityKeyStoreFile = new FileInputStream(new File("identity.jks"));
identityKeyStore.load(identityKeyStoreFile, CERT_PASSWORD.toCharArray());
KeyStore trustKeyStore = KeyStore.getInstance("jks");
FileInputStream trustKeyStoreFile = new FileInputStream(new File("truststore.jks"));
trustKeyStore.load(trustKeyStoreFile, CERT_PASSWORD.toCharArray());
SSLContext sslContext = SSLContexts.custom()
// load identity keystore
.loadKeyMaterial(identityKeyStore, CERT_PASSWORD.toCharArray(), new PrivateKeyStrategy() {
@Override
public String chooseAlias(Map<String, PrivateKeyDetails> aliases, Socket socket) {
restituire CERT_ALIAS;
}
})
// load trust keystore
.loadTrustMaterial(trustKeyStore, null)
.build();
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
new String[]{"TLSv1.2", "TLSv1.1"},
nullo,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
CloseableHttpClient client = HttpClients.custom()
.setSSLSocketFactory(sslConnectionSocketFactory)
.build();
// Call a SSL-endpoint
callEndPoint (client, "https://secure.server.com/endpoint",
nuovo oggetto JSONO()
.put("param1", "valore1")
.put("param2", "valore2")
);
} catch (Exception ex) {
System.out.println("Boom, abbiamo fallito: " + ex);
ex.printStackTrace();
}
}
private static void callEndPoint (CloseableHttpClient aHTTPClient, String aEndPointURL, JSONObject aPostParams) {
prova {
System.out.println("URL di chiamata: " + aEndPointURL);
HttpPost post = new HttpPost(aEndPointURL);
post.setHeader("Accept", "application/json");
post.setHeader("Content-type", "application/json");
StringEntity entity = new StringEntity(aPostParams.toString());
post.setEntity(entità);
System.out.println("**POST** richiesta Url: " + post.getURI());
System.out.println("Parametri : " + aPostParams);
HttpResponse response = aHTTPClient.execute(post);
int responseCode = response.getStatusLine().getStatusCode();
System.out.println("Codice risposta: " + responseCode);
System.out.println("Contenuto:-n");
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent());
Stringa = "";
while ((line = rd.readLine()) != null) {
System.out.println(linea);
}
} catch (Exception ex) {
System.out.println("Boom, abbiamo fallito: " + ex);
ex.printStackTrace();
}
}
}
Naturalmente, esiste una soluzione molto più semplice per impostare l'autenticazione SSL bidirezionale. SnapLogic ha diversi snap che supportano la convalida e l'autenticazione dei certificati SSL, tra cui SOAP, Splunk e REST.