2017-05-29 113 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(); 
相關問題