2017-05-29 117 views
1

我正在使用sunPkcs11类将我的应用程序连接到NetHsm。 我的本地服务nFast在端口9004上运行。它用作与NetHsm进行通信的桥梁。nFast服务重新启动时不会影响应用程序

我的服务提供商设置这样的:

Provider provider = new sun.security.pkcs11.SunPKCS11(pkcs11ConfigFile); // name = nCipher, library = D:\Program\nCipher\nfast\toolkits\pkcs11\cknfast-64.dll 

我破译这样的:

KeyStore ks = KeyStore.getInstance("PKCS11", provider); 
ks.load(null, password); 
Key key = ks.getKey(keyId, null); 
IvParameterSpec paramSpec = new IvParameterSpec(iv); 
AlgorithmParameters algParams = AlgorithmParameters.getInstance("AES"); 
algParams.init(paramSpec); 
Cipher ci = Cipher.getInstance("AES/CBC/NoPadding", provider); 
ci.init(Cipher.DECRYPT_MODE, key, algParams); 
ci.doFinal(dataToDecipher); 

一切都是正确的,我可以破译我的钥匙。

现在,我停止服务nFast。我得到一个例外,因为不可能破译我的密钥。通常...

java.security.ProviderException: update() failed 
Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_DEVICE_ERROR 

我重新启动该服务,我想能够再次破译我的钥匙,但我得到一个异常:

java.security.ProviderException: update() failed 
Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_GENERAL_ERROR 
at sun.security.pkcs11.wrapper.PKCS11.C_FindObjectsInit(Native Method) 
at sun.security.pkcs11.P11KeyStore.findObjects(P11KeyStore.java:2673) 
at sun.security.pkcs11.P11KeyStore.mapLabels(P11KeyStore.java:2288) 
at sun.security.pkcs11.P11KeyStore.engineLoad(P11KeyStore.java:770) 

我有义务重新启动我的应用程序。

如何重新初始化提供程序以便与服务再次通信而无需重新启动应用程序?

回答

0

Java KeyStore api没有一个简洁的方式来确定与PKCS#11设备的会话。当您创建提供程序实例时,它会使用该令牌初始化会话,并且一旦完成使用KeyStore api与令牌的交互操作,就无法完成打开的会话。

如果您在重新启动服务之前完成打开的会话,则可能不会面临此问题。如果您必须重新初始化会话(您必须再次创建提供程序实例)。

你可以参考我的回答here我可以解决与会话有关的类似问题。

由于KeyStore api没有提供类似finalize的方法,因此可以从提到的帖子中执行下面的解决方法。

PKCS11 pkcs11 = PKCS11.getInstance(((sun.security.pkcs11.SunPKCS11) provider).getProperty("pkcs11LibraryPath"), null, null, true); 
pkcs11.C_Finalize(PKCS11Constants.NULL_PTR); 

注意setProperty我做了provider实例。

+0

我有一个PKCS11.getInstance的编译错误。我在IAIK库中找不到这种方法。我用PKCS11Connector.connectToPKCS11Module替换它(字符串) – wit

+0

'PKCS11'来自'sun.security.pkcs11.wrapper'包。 –

+0

这是一个获得许可的'IAIK PKCS#11包装'解决方案。我正在寻找一个随Java提供的官方Sun解决方案。因此,您的代码不是最新的。 PKCS11.getInstance不编译。看来我们必须使用:PKCS11 pkcs11 = PKCS11Connector。connectToPKCS11Module(库); – wit

0

在给定的方式always_a_rookie_to_learn,我找到了最终的解决方案。

由于这个其他职位here

现在我能够通过清除会话提供商打开多个时间,并在每次调用令牌。非常糟糕的是,C_Finalize不能在moduleMap中完成这项工作。

import sun.security.pkcs11.wrapper.PKCS11; 
import sun.security.pkcs11.wrapper.PKCS11Constants; 

// Open provider 
Provider provider = new sun.security.pkcs11.SunPKCS11(pkcs11ConfigFile); 

// Do what you need 
... 

// Finalize the pkcs11 driver in the wrapper 
PKCS11 pkcs11 = PKCS11.getInstance(library, null, null, true); 
pkcs11.C_Finalize(PKCS11Constants.NULL_PTR);    

// Clean the pkcs11 driver in the wrapper to force C_Initialize next time 
Field moduleMapField = PKCS11.class.getDeclaredField("moduleMap"); 
moduleMapField.setAccessible(true); 
Map<?, ?> moduleMap = (Map<?, ?>) moduleMapField.get(pkcs11LibraryPath); 
moduleMap.clear(); 
相关问题