初始化后如何完成SunPKCS11 Provider?

我通过以下方式初始化了SunPKCS11提供商:

Provider provider = new sun.security.pkcs11.SunPKCS11("path_to_pkcs11.cfg"); Security.addProvider(provider); 

然后我使用此提供程序初始化KeyStore以使用密钥进行密码操作。

 KeyStore ks = KeyStore.getInstance("PKCS11", provider); ks.load(null, "password".toCharArray()); 

完成密码操作后, 如何使用PKCS11令牌完成会话?

我试过删除提供程序,但它没有用。

 Security.removeProvider("sunPCKS11ProviderName"); 

下次我尝试与令牌通信时,我从令牌CKR_CRYPTOKI_ALREADY_INITIALIZED抛出此exception

更新

我努力了

 sun.security.pkcs11.SunPKCS11.logout(); 

但它也没有用。

我有一个用例,我必须使用PKCS#11 Wrapper和Provider。 为了能够使用包装器,我必须完成提供程序,否则当包装器尝试与令牌通信时,令牌会抛出CKR_CRYPTOKI_ALREADY_INITIALIZED错误。

更新代码:

我正在使用Sun的PKCS#11 Provider和IAIK的PKCS#11 Wrapper。

 public static void providerAndWrapperIssue() throws Exception { final String name = "ANY_NAME"; final String library = "LOCATION OF THE TOKENS DLL/SO"; final String slot = "SLOT NUMBER"; // SUN PKCS#11 Provider ------------------------------------------- StringBuilder builder = new StringBuilder(); builder.append("name=" + name); builder.append(System.getProperty("line.separator")); builder.append("library=\"" + library + "\""); builder.append(System.getProperty("line.separator")); builder.append("slot=" + slot); ByteArrayInputStream bais = new ByteArrayInputStream(builder.toString().getBytes()); Provider provider = new sun.security.pkcs11.SunPKCS11(bais); Security.addProvider(provider); KeyStore ks = KeyStore.getInstance("PKCS11"); ks.load(null, null); Enumeration aliases = ks.aliases(); while (aliases.hasMoreElements()) System.out.println(aliases.nextElement()); // IAIK PKCS#11 Wrapper ------------------------------------------- Module pkcs11Module = Module.getInstance(library, false); pkcs11Module.initialize(null); <-- Exception here. Slot[] slots = pkcs11Module.getSlotList(true); Session session = slots[0].getToken().openSession(true, true, null, null); session.login(Session.UserType.USER, "".toCharArray()); session.logout(); session.closeSession(); slots[0].getToken().closeAllSessions(); pkcs11Module.finalize(null); } 

由于Sun的提供程序未注销和关闭会话,因此IAIK无法访问该令牌。 Java的Keystore api没有注销方法。

终于能够找到解决方案。 Sun的提供商使用下面的包装器。 因此,诀窍是使用Sun的PKCS#11 Wrapper来获取当前实例,并最终确定它。 显然,会话function的最终确定不会在提供程序中公开。 但有一个解决方法,它看起来像这样:

 public static void providerAndWrapperIssue() throws Exception { final String name = "ANY_NAME"; final String library = "LOCATION OF THE TOKENS DLL/SO"; final String slot = "SLOT NUMBER"; // SUN PKCS#11 Provider ------------------------------------------- StringBuilder builder = new StringBuilder(); builder.append("name=" + name); builder.append(System.getProperty("line.separator")); builder.append("library=\"" + library + "\""); builder.append(System.getProperty("line.separator")); builder.append("slot=" + slot); ByteArrayInputStream bais = new ByteArrayInputStream(builder.toString().getBytes()); Provider provider = new sun.security.pkcs11.SunPKCS11(bais); provider.setProperty("pkcs11LibraryPath", library); Security.addProvider(provider); KeyStore ks = KeyStore.getInstance("PKCS11"); ks.load(null, null); Enumeration aliases = ks.aliases(); while (aliases.hasMoreElements()) System.out.println(aliases.nextElement()); // ==================================== // Solved it using the SUN PKCS#11 Wrapper PKCS11 pkcs11 = PKCS11.getInstance(((sun.security.pkcs11.SunPKCS11) provider).getProperty("pkcs11LibraryPath"), null, null, true); pkcs11.C_Finalize(PKCS11Constants.NULL_PTR); // ==================================== // IAIK PKCS#11 Wrapper ------------------------------------------- Module pkcs11Module = Module.getInstance(library, false); pkcs11Module.initialize(null); Slot[] slots = pkcs11Module.getSlotList(true); Session session = slots[0].getToken().openSession(true, true, null, null); session.login(Session.UserType.USER, "".toCharArray()); session.logout(); session.closeSession(); slots[0].getToken().closeAllSessions(); pkcs11Module.finalize(null); } 

您正在获得此exception,因为一旦程序第一次执行,值将保留在java.So中的进程ID以解决此问题,使其成为jar文件并作为批处理文件运行