初始化后如何完成SunPKCS11 Provider? [英] How to finalize SunPKCS11 Provider after it is initialized?
问题描述
我通过以下方式初始化了SunPKCS11提供程序:
I have initialized the SunPKCS11 provider by:
Provider provider = new sun.security.pkcs11.SunPKCS11("path_to_pkcs11.cfg");
Security.addProvider(provider);
然后我正在使用此提供程序来初始化KeyStore,以将密钥用于密码操作.
And then I'm using this provider to initialize a KeyStore to use a key for cipher operations.
KeyStore ks = KeyStore.getInstance("PKCS11", provider);
ks.load(null, "password".toCharArray());
一旦我完成了密码操作,我应该如何用PKCS11令牌完成会话?
Once I'm done with the cipher operations, how should I finalize the session with the PKCS11 token?
我尝试删除该提供程序,但是没有用.
I have tried removing the Provider, but it didn't work.
Security.removeProvider("sunPCKS11ProviderName");
下次我尝试与令牌通信时,会从令牌中抛出此异常 CKR_CRYPTOKI_ALREADY_INITIALIZED
The next time I try to communicate with the Token, I get this exception thrown from the token CKR_CRYPTOKI_ALREADY_INITIALIZED
更新:
我尝试过
sun.security.pkcs11.SunPKCS11.logout();
但它也不起作用.
我有一个用例,其中必须同时使用PKCS#11包装程序和提供程序.为了能够使用包装器,我必须完成提供程序的确定,否则当包装器尝试与令牌通信时,令牌会引发 CKR_CRYPTOKI_ALREADY_INITIALIZED
错误.
I have a use case where I have to use both the PKCS#11 Wrapper and Provider. To be able to use the wrapper, I have to finalize the provider, or else the token throws CKR_CRYPTOKI_ALREADY_INITIALIZED
error when the wrapper is trying to communicate with the token.
使用代码更新:
我正在使用Sun的PKCS#11提供程序和IAIK的PKCS#11包装程序.
I'm using Sun's PKCS#11 Provider and IAIK's 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<String> 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没有注销方法.
Since the Sun's provider is not logging out and closing sessions, IAIK is not able to access the token. And the Java's Keystore
api doesn't have a method to logout.
推荐答案
最后终于找到了解决方案.Sun的提供程序在下面使用包装器.因此,诀窍是使用Sun的PKCS#11包装器来获取当前实例并将其完成.显然,此会话功能的最终确定不会在提供程序中公开.但是有一种解决方法,它看起来像这样:
Finally was able to find a solution. The Sun's Provider uses the Wrapper underneath. So the trick is to use the Sun's PKCS#11 Wrapper to get the current instance, and finalize it. Obviously this finalizing of the session feature is not exposed in the Provider. But there is a workaround, and it looks like this:
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<String> 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);
}
这篇关于初始化后如何完成SunPKCS11 Provider?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!