Reputation: 9044
I am establishing an SSL connection to a server which has enabled ssl.There is a cacerts file in my hardware's filesystem java keystore and I extracted the certificate from it using keytool & I am giving this certificate file to create an SSLSocketfactory to establish the ssl connection , which works fine with the code snippet below.
I wanted to know how to access the cacerts ( java keystore ) file directly , and pick the certificate and establish the ssl connection. Right now , I am packaging the extracted certicate in the classpath with my jar file , which is not a good practice as I want it to be loaded from the keystore.
Below is the working code snippet of how I create a SSLSocketFactory currently.
private SSLSocketFactory createSSLFactory() {
KeyStore keyStore = null;
TrustManagerFactory tmf = null;
SSLContext ctx = null;
try {
keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream is = null;
is = SSLConnection.class.getResourceAsStream("/" + "my-keystore");
keyStore.load(is, "changeit".toCharArray());
tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
ctx = SSLContext.getInstance("TLSv1");
ctx.init(null, tmf.getTrustManagers(), null);
SSLSocketFactory factory = ctx.getSocketFactory();
return factory;
} catch (Exception e) {
// exception handling
}
return null;
}
Upvotes: 4
Views: 11746
Reputation: 31
You need to add a trust manager :
SSLSocketFactory factory = null;
try {
SSLContext ctx;
KeyManagerFactory kmf;
TrustManagerFactory tmf;
KeyStore ks;
char[] passphrase = "passphrase".toCharArray();
ctx = SSLContext.getInstance("TLS");
kmf = KeyManagerFactory.getInstance("SunX509");
tmf = TrustManagerFactory.getInstance("SunX509");
ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("testkeys"), passphrase);
kmf.init(ks, passphrase);
tmf.init(ks);
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
factory = ctx.getSocketFactory();
} catch (Exception e) {
throw new IOException(e.getMessage());
}
SSLSocket socket = (SSLSocket)factory.createSocket(host, port);
Upvotes: 0
Reputation: 23525
You can pass the keystore (and truststore) as system properties to the JVM. See here: https://stackoverflow.com/a/882479/131929
-Djavax.net.ssl.keyStoreType=pkcs12
-Djavax.net.ssl.trustStoreType=jks
-Djavax.net.ssl.keyStore=clientcertificate.p12
-Djavax.net.ssl.trustStore=gridserver.keystore
-Djavax.net.debug=ssl # very verbose debug
-Djavax.net.ssl.keyStorePassword=$PASS
-Djavax.net.ssl.trustStorePassword=$PASS
Then you can do
URL url = new URL("https://someurl");
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
InputStream inputstream = conn.getInputStream();
Upvotes: 1
Reputation: 310840
It doesn't make any sense to embed a KeyStore into a JAR file in the case of private keys and authenticating certificates. A client certificate is supposed to uniquely identify the client. It is a property of a host, not a JAR file, which can be copied around infinitely. It doesn't make sense to allow the use of the same client certificates for multiple clients. It is a misuse of PKI.
Upvotes: 4