Java Keytool с провайдером opensc pkcs#11 работает только с включенной опцией отладки
У меня последняя версия opensc 0.12.2, работающая на Ubuntu 11.10 с OpenJDK (Java-версия "1.6.0_22")
Я могу читать свою смарт-карту (Feitian ePass PKI) с
pkcs15-tool --dump
Теперь я пытаюсь использовать свою смарт-карту с keytool:
keytool
-providerClass sun.security.pkcs11.SunPKCS11 \
-providerArg /etc/opensc/opensc-java.cfg \
-keystore NONE -storetype PKCS11 -list
что приводит к ошибке:
keytool error: java.security.KeyStoreException: PKCS11 not found
java.security.KeyStoreException: PKCS11 not found
at java.security.KeyStore.getInstance(KeyStore.java:603)
at sun.security.tools.KeyTool.doCommands(KeyTool.java:621)
at sun.security.tools.KeyTool.run(KeyTool.java:194)
at sun.security.tools.KeyTool.main(KeyTool.java:188)
Caused by: java.security.NoSuchAlgorithmException: PKCS11 KeyStore not available
at sun.security.jca.GetInstance.getInstance(GetInstance.java:159)
at java.security.Security.getImpl(Security.java:696)
at java.security.KeyStore.getInstance(KeyStore.java:600)
... 3 more
Когда я запускаю ту же команду с включенными параметрами отладки, вот так:
keytool
-providerClass sun.security.pkcs11.SunPKCS11 \
-providerArg /etc/opensc/opensc-java.cfg \
-keystore NONE -storetype PKCS11 -list \
-J-Djava.security.debug=sunpkcs11
это вдруг работает:
... debug infos ...
Enter keystore password:
sunpkcs11: login succeeded
Keystore type: PKCS11
Keystore provider: SunPKCS11-OpenSC
Your keystore contains 2 entries
...
Certificate fingerprint (MD5): ...
...
Certificate fingerprint (MD5): ...
Такое же поведение при настройке статически:
$ grep opensc /usr/lib/jvm/java-6-openjdk/jre/lib/security/java.security
security.provider.7=sun.security.pkcs11.SunPKCS11 /etc/opensc/opensc-java.cfg
и мой конфиг
$ cat /etc/opensc/opensc-java.cfg
name = OpenSC
description = SunPKCS11 w/ OpenSC Smart card Framework
library = /usr/lib/opensc-pkcs11.so
Я думаю, это как-то связано с openjdk или внутренним пакетом sun.security
который обычно может не использоваться, потому что это внутренний пакет. Активация параметров отладки может активировать этот внутренний пакет?
3 ответа
Сегодня у меня возникла та же проблема, и я копался в java-источниках, пока не нашел источник проблемы. Я знаю, что этот вопрос довольно старый и уже получил приемлемый ответ, но этот ответ не является реальным.
По сути, поставщик SunPKCS11 перечисляет все доступные слоты, затем получает слот, указанный в вашей конфигурации, и выдает ошибку (поскольку вы не указали ни одного слота и не указали его значение по умолчанию).
При отладке, после перечисления всех доступных слотов, он перечисляет все слоты со вставленной смарт-картой. Распечатав всю эту информацию о списке слотов, он инициализирует свою переменную slotid, перезаписывая то, что вы написали (или забыли написать) в вашей конфигурации. Новое значение является правильным, поскольку оно считывается из значений по умолчанию opensc.
Это соответствующий код из SunPKCS11.java из проекта openjdk:
long slotID = config.getSlotID();
// ....
if ((slotID < 0) || showInfo) {
long[] slots = p11.C_GetSlotList(false);
if (showInfo) {
System.out.println("All slots: " + toString(slots));
slots = p11.C_GetSlotList(true);
System.out.println("Slots with tokens: " + toString(slots));
}
if (slotID < 0) {
if ((slotListIndex < 0) || (slotListIndex >= slots.length)) {
throw new ProviderException("slotListIndex is " + slotListIndex
+ " but token only has " + slots.length + " slots");
}
slotID = slots[slotListIndex];
}
}
this.slotID = slotID;
Таким образом, обходной путь должен всегда включать в ваш конфиг отрицательное значение, как slot = -1
, так что поставщик всегда будет искать правильный.
Добавление флага отладки в командную строку работало для меня:
keytool -providerClass sun.security.pkcs11.SunPKCS11 \
-providerArg /home/hans/Desktop/smartcards/opensc-java.cfg \
-providerName SunPKCS11-OpenSC -keystore NONE -storetype PKCS11 \
-list \
-J-Djava.security.debug=sunpkcs11
Или вручную указав слот в файле cfg:
name = OpenSC
description = SunPKCS11 w/ OpenSC Smart card Framework
library = /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so
slot = 2
Я могу подтвердить это поведение с помощью Java JDK 1.6.0_20
Даже простая Java-программа работает только с установленным параметром -Djava.security.debug=sunpkcs11.
String configName = "/etc/pkcs11_java.cfg";
Provider p = new sun.security.pkcs11.SunPKCS11(configName);
keyStore = KeyStore.getInstance("PKCS11", p);
с /etc/pkcs11_java.cfg
name=OpenSC
description = SunPKCS11 via OpenSC
library=/usr/local/lib/opensc-pkcs11.so