Multiple and Dynamic Keystores

Smartcards (and other removable tokens) have additional requirements for an X509KeyManager. Different Smartcards may be present in a Smartcard reader during the lifetime of a Java™ application and they may protected using different passwords. The pre-SDK 5 APIs and the IbmX509 key manager do not accomodate these requirements well. As a result, in SDK 6, new APIs were introduced and a new X509KeyManager implementation was added to the IBMJSSE2 provider.

The java.security.KeyStore.Builder class abstracts the construction and initialization of a KeyStore object. It supports the use of CallbackHandlers for password prompting and can be subclassed to support additional features as desired by an application. For example, it is possible to implement a Builder that allows individual KeyStore entries to be protected with different passwords. The javax.net.ssl.KeyStoreBuilderParameters class then can be used to initialize a KeyManagerFactory using one or more of these Builder objects.

A new X509KeyManager implementation in the IBMJSSE2 provider called NewIbmX509 supports these parameters. If multiple certificates are available, it also makes the effort to pick a certificate with the appropriate key usage and prefers valid to expired certificates

Here is an example of how to tell JSSE to use both a IBMPKCS11ImplKS keystore (which might in turn use a Smartcard) and a PKCS#12 file-based keystore.
import javax.net.ssl.*;
import java.security.KeyStore.*;
...

// Specify keystore builder parameters for PKCSIMPLKS keystores
Builder scBuilder = Builder.newInstance("PKCS11IMPLKS", null,
 new CallbackHandlerProtection(myGuiCallbackHandler));

// Specify keystore builder parameters for a specific PKCS#12 keystore
Builder fsBuilder = Builder.newInstance("PKCS12", null,
new File(pkcsFileName), new PasswordProtection(pkcsKsPassword));

// Wrap them as key manager parameters
ManagerFactoryParameters ksParams = new KeyStoreBuilderParameters(
Arrays.asList(new Builder[] { scBuilder, fsBuilder }));

// Create KeyManagerFactory
KeyManagerFactory factory = KeyManagerFactory.getInstance("NewIbmX509");

// Pass builder parameters to factory
factory.init(ksParams);

// Use factory
SSLContext ctx = SSLContext.getInstance("SSL_TLS");
ctx.init(factory.getKeyManagers(), null, null);