I have two applications running in the same java virtual machine, and both use different keystores and truststores.
A viable option would be use a single keystore and import all the other ones into the shared keystore (e.g. keytool -import), but it would really help my requirements if I could use separate keystores for separate applications running in the same jvm.
I could set the keystore and truststores to be used as jvm parameters or system properties as follows:
java -Djavax.net.ssl.keyStore=serverKeys
-Djavax.net.ssl.keyStorePassword=password
-Djavax.net.ssl.trustStore=serverTrust
-Djavax.net.ssl.trustStorePassword=password SSLApplication
or
System.setProperty("javax.net.ssl.keyStore","serverKeys")
But the problem with this approach is that it specifies the keystore/truststore to be used at a JVM level, thus all applications running in the same JVM gets the same keystore/truststore.
I have also tried creating a custom SSLContext and setting it as the default, but it also sets the context for all applications running in the same JVM.
SSLContext context = SSLContext.getInstance("SSL");
context.init(kms, tms, null);
SSLContext.setDefault(context);
I want to be able use different keystores/truststores without modifying individual application codes.
A solution that can dynamically register multiple key stores in addition to the default keystore/certs in jre into jvm would be great.
The solution will work in this way:
- When JVM boots, it loads all the default certs/keystores from jre/certs folder (default java behaviour when no keystores specified).
- When App 1 loads it registers its keystores,
- then when App 2 loads it registers its keystores...
Please let me know your ideas or solutions. Thanks in advance!
Raz's answer was a great start, but wasn't quite flexible enough to meet my needs. The MultiStoreKeyManager explicitly checks the custom KeyManager and then falls back to the jvm KeyManager if an operation fails. I actually want to check jvm certs first; the best solution should be able to handle either case. Additionally, the answer fails to provide a working TrustManager.
I've written a couple more flexible classes, CompositeX509KeyManager and CompositeX509TrustManager, which add support for any number of keystores in an arbitrary order.
CompositeX509KeyManager
CompositeX509TrustManager
Usage
For the standard case of one keystore + jvm keystore, you can wire it up like this. I’m using Guava again, but in a Guicey wrapper this time:
I extracted this from my blog post about this problem which has a bit more detail, motivation, etc. All the code is there though, so its standalone. :)
Check out my answer to this question,
How can I have multiple SSL certificates for a Java server
If you use the MyKeyManager, you can have multiple keystores or you can use a single keystore for multiple contexts.
After playing with the code I have received from ZZ Coder, sylvarking and Software Monkey, I have found a solution that works:
First, I wrote a X509KeyManager that works combines a custom keystore and a default keystore.
Then, you can use this keystore manager when creating an SSL Context or SocketFactory. The code needs some refactoring and tidying up but it works perfectly.
Let me know if anyone has any question or need any demonstration codes.