How to get KeyStore from usb token in Java

前端 未结 2 1098
悲&欢浪女
悲&欢浪女 2021-02-06 15:20

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

<
相关标签:
2条回答
  • 2021-02-06 15:31

    Try the below code to get the keystore from usb token using java

    class Test {
        public static void main(String args[]) throws IOException, GeneralSecurityException, DocumentException, CertificateVerificationException{
            
            // Create instance of SunPKCS11 provider
            String pkcs11Config = "name=eToken\nlibrary=C:\\Windows\\System32\\eps2003csp11.dll";
            java.io.ByteArrayInputStream pkcs11ConfigStream = new java.io.ByteArrayInputStream(pkcs11Config.getBytes());
            sun.security.pkcs11.SunPKCS11 providerPKCS11 = new sun.security.pkcs11.SunPKCS11(pkcs11ConfigStream);
            java.security.Security.addProvider(providerPKCS11);
    
            // Get provider KeyStore and login with PIN
            String pin = "12345678";
            java.security.KeyStore keyStore = java.security.KeyStore.getInstance("PKCS11", providerPKCS11);
            keyStore.load(null, pin.toCharArray());
    
            // Enumerate items (certificates and private keys) in th KeyStore
            java.util.Enumeration<String> aliases = keyStore.aliases();
            String alias = null;
            while (aliases.hasMoreElements()) {
                alias = aliases.nextElement();
                System.out.println(alias);
            }
        }
    }
    
    0 讨论(0)
  • 2021-02-06 15:44

    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.

    0 讨论(0)
提交回复
热议问题