编程语言
首页 > 编程语言> > 带有opensc pkcs#11提供程序的java keytool仅适用于启用调试选项

带有opensc pkcs#11提供程序的java keytool仅适用于启用调试选项

作者:互联网

我在ubuntu 11.10上使用OpenJDK(java版“1.6.0_22”)运行最新的opensc 0.12.2

我可以阅读我的智能卡(飞天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有关,因为它是一个内部包,所以通常不会使用它.激活调试选项可能会激活此内部包?

解决方法:

我今天遇到了同样的问题,我深入研究了java源代码,直到找到了问题的根源.我知道这个问题已经很老了,已经有了一个公认的答案,但那个问题并不是真正的答案.

基本上,SunPKCS11提供程序确实列出了所有可用的插槽,然后获取您在配置中指定的插槽,并给出错误(因为您没有指定任何插槽并使用其默认值).

在调试中,列出所有可用插槽后,它会列出插入了智能卡的所有插槽.在打印了有关插槽列表的所有这些信息之后,它会初始化其slotid变量,覆盖您在配置中写入(或忘记写入)的内容.新值是正确的,因为它是从opensc默认值中读取的.

这是来自openjdk项目的SunPKCS11.java的相关代码:

    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,以便提供者始终寻找正确的值.

标签:smartcard,pkcs11,java,keytool
来源: https://codeday.me/bug/20190926/1817982.html