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
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);