I\'m building two java applications which have to communicate using SSL two way authentication, I used instructions from here to create client and server certificates.
then
after spending a long time to make this work, the solution is as follows:
first when setting the properties using System.put("key", "value")
I noticed after many tries it is not setting the KeyStore
value it is does not appear in the ssl log , also tried to set the properties as parameters in the tomcat configuration using -Djavax.net.ssl.keyStore=""
this also didn't work.
so I read the KeyStore
from an InputStream
like this:
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream io = new FileInputStream("path/to/jks/file.jks");
try{
keystore.load(io, "pass".toCharArray());
} finally {
io.close();
}
and use the same previous code to read the TrustStore
like :
KeyStore trustStore= KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream stream = new FileInputStream("path/to/truststore/file.jks");
try{
keystore.load(stream, "trusted".toCharArray());
} finally {
stream.close();
}
after that define the SSLContext
:
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keystore, "keyPassword".toCharArray())
.loadTrustMaterial(truststore, new TrustSelfSignedStrategy())
.build();
loadKeyMaterial
used to load the keyStore
it takes the password of your privateKey "keyPassword"
as a parameter, so you must protect the private key using a password, when I tried to use a plain private key not encrypted "protected" with a password, I get exception which says: java.security.UnrecoverableKeyException: Cannot recover key
, by default this is the same as the keystore password unless you changed it.
then create the SSLConnectionSocketFactory
and pass it as a parameter to the HttpClient
..
this worked for me :)
For anyone looking to implement 2 way mutual auth, following code worked perfectly for me.
FileInputStream keystoreInputStream = null;
FileInputStream truststoreInputStream = null;
try {
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystoreInputStream = new FileInputStream("C:\\Users\\Aman\\STSProj\\AppSecurity\\clientkeystore.p12");
keystore.load(keystoreInputStream, "client".toCharArray());
keystoreInputStream.close();
KeyStore trustore = KeyStore.getInstance(KeyStore.getDefaultType());
truststoreInputStream = new FileInputStream("C:\\Users\\Aman\\STSProj\\AppSecurity\\clienttruststore.p12");
trustore.load(truststoreInputStream, "client".toCharArray());
SSLContext sslcontext = SSLContexts.custom().useProtocol("TLS")
.loadKeyMaterial(keystore, "client".toCharArray())
.loadTrustMaterial(trustore, null).build();
HostnameVerifier hostnameverifier = null;
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslcontext,
null, null, hostnameverifier);
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslSocketFactory).build();
HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setHttpClient(httpClient);
RestTemplate restTemp = new RestTemplate(requestFactory);
String greetings = restTemp
.getForObject("https://localhost:8443/SecureAppServer/test/security/hello/aman123", String.class);
System.out.println("Received greetings from secured server ---> " + greetings);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
if (keystoreInputStream != null) {
try {
keystoreInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (truststoreInputStream != null) {
try {
truststoreInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}