Перезапуск службы nFast без воздействия на приложение

Я использую класс sunPkcs11 для подключения своего приложения к NetHsm. Моя локальная служба nFast работает на порту 9004. Она используется в качестве моста для связи с NetHsm.

Мой провайдер настроен так:

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)

Я обязан перезапустить свое приложение.

Как я могу повторно инициализировать провайдера, чтобы снова связаться со службой без перезапуска приложения?


person wit    schedule 29.05.2017    source источник


Ответы (2)


Java KeyStore API не имеет удобного способа завершения сеанса с устройством PKCS#11. Когда вы создаете свой экземпляр поставщика, он инициализирует сеанс с токеном, и вы не можете завершить открытый сеанс после завершения взаимодействия с токеном с помощью KeyStore API.

Если вы завершите открытый сеанс до перезапуска службы, вы можете не столкнуться с этой проблемой. При условии, что вам нужно снова инициализировать сеанс (вам нужно снова создать экземпляр поставщика).

Вы можете обратиться к моему ответу здесь, где я был в состоянии решить аналогичную проблему, связанную с сеансом.

Поскольку API-интерфейс KeyStore не предоставляет такой метод, как finalize, вы можете использовать приведенный ниже обходной путь из упомянутого сообщения.

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

Обратите внимание на setProperty, который я сделал для экземпляра provider.

person always_a_rookie    schedule 29.05.2017
comment
У меня ошибка компиляции с PKCS11.getInstance. Я не нахожу этот метод в библиотеке IAIK. Я заменил его на PKCS11Connector.connectToPKCS11Module(String) - person wit; 31.05.2017
comment
PKCS11 из пакета sun.security.pkcs11.wrapper. - person always_a_rookie; 31.05.2017
comment
Это решение «IAIK PKCS#11 Wrapper», на которое распространяется лицензия. Я ищу официальное решение Sun, поставляемое с Java. Таким образом, ваш код не актуален. PKCS11.getInstance не компилируется. Кажется, мы должны использовать: PKCS11 pkcs11 = PKCS11Connector.connectToPKCS11Module(library); - person wit; 31.05.2017
comment
Если он не компилируется из-за ограничения доступа, вы можете использовать это исправление: stackoverflow.com/questions/5172069/ - person always_a_rookie; 31.05.2017

Точно так же, как всегда_новичок_к_обучению, я нашел окончательное решение.

Благодаря этому другому сообщению здесь

Теперь я могу несколько раз открывать провайдера, очищая сеанс и токен при каждом вызове. Настолько плохо, что 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();
person wit    schedule 01.06.2017