I have a SafeNet 5100 eToken already with a valid certificate in it that I use to access a web application from my company that requires it (multi-factor authentication).
<
The SunMSCAPI implementation isn't perfect (for example, if you have certificates with the same "friendly name", some will be inaccessible, since it's also the unique key used for the keystore alias). I'm not sure how well it works with hardware tokens.
Since your token seems to support PKCS#11, you might as well make use of the Oracle JRE's direct support for PKCS11 keystores.
Essentially, your token driver should come with a DLL implementing the PKCS#11 interface, and you need to point Java to it (as described in the PKCS#11 guide). For more flexibility, it might be more convenient to install the provider dynamically (see the paragraph that starts with "To install the provider dynamically, [...]".
Following your comments, perhaps you could use trial and error (by catching these exceptions) to find the right slot. Instead of using a configuration file, you could load the configuration from a string.
String password = "xxxxxxxxx";
String storeType = "PKCS11";
String configuration = "name = OpenSC\n"
+ "library = /usr/lib/opensc-pkcs11.so\n";
Provider provider = new sun.security.pkcs11.SunPKCS11(
new ByteArrayInputStream(configuration.getBytes("UTF-8")));
Security.addProvider(provider);
KeyStore keyStore = KeyStore.getInstance(storeType, provider);
keyStore.load(null, password.toCharArray());
If you add "slot=...\n"
to the configuration string and use a loop to try various values until it stops throwing exceptions, it might work. You may need to remove the security providers where it failed, or change the name too. (I'm not suggesting this is a clean way to do it.)
By the way, if you don't want to hard-code your password (of course!) or load it from some configuration file, you can use a callback hander like this:
KeyStore keyStore = KeyStore.getInstance(storeType, provider);
LoadStoreParameter param = new LoadStoreParameter() {
@Override
public ProtectionParameter getProtectionParameter() {
return new KeyStore.CallbackHandlerProtection(... put your callback handler here...);
}
};
keyStore.load(param);
Your callback handler could be "new com.sun.security.auth.callback.DialogCallbackHandler()
". I wouldn't generally advise using any of the com.sun.*
or sun.*
packages since they're not part of the public Java API, but you're using sun.security.pkcs11.SunPKCS11
here, so your code will be tied to this family of JREs anyway.