有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

带有opensc pkcs#11提供程序的智能卡java密钥工具仅在启用调试选项的情况下工作

我有最新的OpenSC0.12.2运行在Ubuntu11.10和OpenJDK上(java版本“1.6.0_22”)

我可以用

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) 个答案

  1. # 1 楼答案

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

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

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

    这是来自SunPKCS11的相关代码。来自openjdk项目的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,以便提供程序始终查找正确的值

  2. # 2 楼答案

    将调试标志添加到命令行对我有效:

    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
    
  3. # 3 楼答案

    我可以使用JavaJDK1.6.0\u20确认这种行为

    即使是一个简单的java程序也只能与-Djava一起工作。安全调试=设置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