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
Другие вопросы по тегам