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

标签 java smartcard keytool pkcs#11

我有最新的 opensc 0.12.2 在带有 OpenJDK 的 ubuntu 11.10 上运行(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 有关,通常可能不会被使用,因为它是一个内部包。激活调试选项可能会激活这个内部包?

最佳答案

我今天遇到了同样的问题,我深入研究了 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,以便提供者始终寻找正确的值。

关于带有 opensc pkcs#11 提供程序的 java keytool 仅适用于启用调试选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8247115/

相关文章:

java - 有时数据不会插入到表中

java - 如何在终端中运行java代码

google-chrome - 如何在网络浏览器上使用智能卡

java - 使用 Java Keytool 更新证书 - 重用旧的 CSR?

java - 为什么我在 ~/.android 文件夹中没有 debug.keystore(对于 mac)?

java - 有没有办法向 Sublime Text 2 添加对 Java 的自动完成支持?

Java - 右键单击​​ JTabbedPane 选项卡

java - 程序 'keytool'可以在以下包中找到

java - Android 中的智能卡验证 pin apdu 命令问题

internet-explorer - 从浏览器读取智能卡