...
- As documented in public interfaces section, we will introduce two interfaces to allow pluggable implementation to provide key/trust stores loading
- We will make changes to the SslEngineBuilder#createSSLContext() method to invoke the key/trust store loading from new ssl configurations we introduce.
- Pseudocode changes in the SslEngineBuilder#createSSLContext() looks like below
Code Block String kmfAlgorithm = this.kmfAlgorithm != null ? this.kmfAlgorithm : KeyManagerFactory.getDefaultAlgorithm(); KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfAlgorithm); KeyStore ks; ... ... if ( keystore != null ) { // load keystore 'ks' in existing way } else if ( 'ssl.keystore.loader' specified ) { // load keystore 'ks' by invoking the pluggable implementation class for the config } kmf.init(ks, ksPassword.toCharArray()); ... ... ... String tmfAlgorithm = this.tmfAlgorithm != null ? this.tmfAlgorithm : TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); KeyStore ts = null; ... if ( truststore != null ) { // load truststore 'ts' in existing way } else if ( 'ssl.truststore.loader' specified ) { // load truststore 'ts' by invoking the pluggable implementation class for the config } ... tmf.init(ts); ...
- Pseudocode changes in the SslEngineBuilder#createSSLContext() looks like below
- We will make changes to the SslEngineBuilder#shouldBeRebuilt() method appropriately
...
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
package providertest; import java.security.Provider; public class MyProvider extends Provider { private static final String name = "MyProvider"; private static double version = 1.0d; private static String info = "Maulin's SSL Provider v"+version; public MyProvider() { super(name, version, info); this.put("TrustManagerFactory.PKIX", "providertest.MyTrustManagerFactory"); } } |
Writing a Java security provider and registering it from JRE
Alternative to using ssl.provider configuration is to register the Java security provider in JRE's jre/lib/security/java.security file. This way we won't run into the limitation mentioned in the above rejected approach.
However there are following challenges,
- We have to modify the java.security file on the system which creates the similar challenge as of hosting jks on local file system - meaning maintaining per box, deployment etc
- Assuming modifying java.security file is not a challenge (See KIP-492) , we still have to write a Provider with custom algorithm for TrustManagerFactory and KeyManagerFactory
- When we write those factories implementation there is no easy way to re-use validation logic (example: OpenJDK TrustManagerImpl) done by existing Providers.
- The X509ExtendedTrustManager class is having all the methods abstract so we can't re-use any standard implementations easily
- We will end up copying the validation logic (example: OpenJDK TrustManagerImpl) which is "security domain" centric
- The validation logic deals with essentially three things as of now,
- client side cert checks
- server side cert checks
- certificate path validations
- end point identification verification
- The above validation logic we should not have to deal with it in the first place for the purpose of just loading keys/certs from a different source than the file based key/trust stores.
NOTE: You can only realize the above challenges once you try to write the Provider with Trust/Key Manager factories. We would highly encourage you to try writing (using any other open-source library's provider as an example may not give you the idea) a provider to do this before you decide to comment on this approach.
Provide a way to delegate SSLContext creation
...