In our java application we need to communicate with a list of servers on SSL using https protocol. The list of servers to communicate will change at runtime. Initially we do not have any of the server's certificate. At runtime, we will obtain a new server's certificate and add the public key certificate into a truststore; and any new https connection with the server should use the updated trust store.
We are thinking that we should use two trust stores, one cacerts(default one shipped with jre) and other containing certificates of the servers that we add/remove dynamically in a list. This will make sure that we do not modify the default TrustStore(cacerts) of java.
Please suggest how this can be achieved. Also, is there any way to use a specific trust store only for a particular thread in java, so that other(existing and new) threads should still use the default java trueststore(cacerts), and one specific thread will use the particular truststore for the server.
Thank you, Deepak
If you want to import certificate dynamically, you may need to use a custom
x509TrustManager
. This is done when configuring theSSLContext
, which is itself used to create theSSLSocketFactory
orSSLEngine
.jSSLutils is a library that lets you wrap existing trust managers and customize certain settings. You don't need it, but it may help.
This would go along these lines:
(The
(PKIX)SSLContextFactory
andX509TrustManagerWrapper
come from jSSLutils, but the rest is available with the J2SE/J2EE.)There are a few
CertificateException
s that you may want to catch (see subclasses). If you make a callback to the user, it's possible that the SSL/TLS connection will fail the first time because of a time-out on the SSL/TLS handshake (if the callback takes too long to be replied to.)You could then use this
SSLContext
as your default usingSSLContext.setSSLContext(...)
(from Java 6), but that's not necessarily a good idea. If you can, pass theSSLContext
to the library that makes the SSL/TLS connection. How this is done varies, but Apache HTTP Client 4.x, for example, has multiple options to configure its SSL settings, one of them being by passingKeyStore
s, another one being by passing anSSLContext
.You could also to something per thread instead of per object that's going to connect (library dependent), by checking the current thread within the
X509TrustManager
: this would probably make things a bit more complex in terms of synchronization and thread management/"awareness" by the trust manager.This question is so old that I have my doubts my bit will help anyone but here goes...
If you want to solve the OP's (original poster) problem without resorting to code changes you can configure your JVM (I only tested with Tomcat) to support the OP's desired config:
I used to just import my additional cert into a separate file and then reference it in my JVM startup with the parameter
-Djavax.net.ssl.trustStore=$JAVA_HOME/jre/lib/security/jssecacerts
with great success but I guess the recent (somewhat) JAVA security problems changed an automated inclusion of the cacerts file distributed with the SDK.So I found a nifty solution using intel from this post and the these pages (with some minor changes):
What I used to do:
What I do Now:
What it looks like:
Hope this is helpful to someone. I'm not 100% that you need to specify the keyStore password since you don't with the trustStore, but it works when you do.