简体   繁体   English

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

[英]java keytool with opensc pkcs#11 provider only works with debug option enabled

I have the latest opensc 0.12.2 running on ubuntu 11.10 with OpenJDK ( java version "1.6.0_22") 我在ubuntu 11.10上使用OpenJDK(java版“1.6.0_22”)运行最新的opensc 0.12.2

I can read my smartcard (a Feitian ePass PKI) with 我可以阅读我的智能卡(飞天ePass PKI)

pkcs15-tool --dump

Now i try to use my smartcard with keytool: 现在我尝试使用带有keytool的智能卡:

keytool 
   -providerClass sun.security.pkcs11.SunPKCS11 \
   -providerArg /etc/opensc/opensc-java.cfg \
   -keystore NONE -storetype PKCS11 -list 

which results in an error: 这会导致错误:

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

When i run the same command with debug options enabled like this: 当我运行相同的命令时启用调试选项,如下所示:

keytool 
   -providerClass sun.security.pkcs11.SunPKCS11 \
   -providerArg /etc/opensc/opensc-java.cfg \
   -keystore NONE -storetype PKCS11 -list \
   -J-Djava.security.debug=sunpkcs11

it suddenly works: 它突然起作用:

... 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): ...

The same behaviour when i configure it statically: 我静态配置时的行为相同:

$ 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

and my config 和我的配置

$ cat /etc/opensc/opensc-java.cfg
name = OpenSC
description = SunPKCS11 w/ OpenSC Smart card Framework
library = /usr/lib/opensc-pkcs11.so

My guess it, it has something to do with openjdk or internal package sun.security which might usually not be used because it is an internal package. 我猜,它与openjdk或内部包sun.security ,因为它是一个内部包,所以通常不会使用它。 Activating Debug options might activate this internal package? 激活调试选项可能会激活此内部包?

I got the same problem today and I digged onto the java sources until I found the source of the problem. 我今天遇到了同样的问题,我深入研究了java源代码,直到找到了问题的根源。 I know this question is quite old and already have an accepted answer, but that one is not a real answer. 我知道这个问题已经很老了,已经有了一个公认的答案,但那个问题并不是真正的答案。

Basically, the SunPKCS11 provider does list all available slots, then, get the slot you specified in your config, and give the error (since you do not specified any slot and fot its default value). 基本上,SunPKCS11提供程序确实列出了所有可用的插槽,然后获取您在配置中指定的插槽,并给出错误(因为您没有指定任何插槽并使用其默认值)。

When in debug, after listing all available slots, it does list all slots with a smartcard inserted. 在调试中,列出所有可用插槽后,它会列出插入了智能卡的所有插槽。 After having print all these information about the slot list, it does initialise its slotid variable overwriting what you wrote (or forget to write) in your config. 在打印了有关插槽列表的所有这些信息之后, 它会初始化其slotid变量,覆盖您在配置中写入(或忘记写入)的内容。 The new value is a correct one since it is read from the opensc defaults. 新值是正确的,因为它是从opensc默认值中读取的。

This is the relevant code from SunPKCS11.java from openjdk project: 这是来自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;

So, a workaround is to always include in your config a negative value like slot = -1 , so that the provider will always look for the right one. 因此,一种解决方法是始终在您的配置中包含一个负值,如slot = -1 ,以便提供者始终寻找正确的值。

Adding the debug flag to the command line worked for me: 将调试标志添加到命令行对我有用:

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

Or manually specifying the slot in the cfg file: 或者手动指定cfg文件中的插槽:

name = OpenSC
description = SunPKCS11 w/ OpenSC Smart card Framework
library = /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so
slot = 2

I can confirm this behavior using java JDK 1.6.0_20 我可以使用java JDK 1.6.0_20来确认这种行为

Even a simple java program only works with -Djava.security.debug=sunpkcs11 set. 即使是简单的java程序也只适用于-Djava.security.debug = sunpkcs11 set。

String configName = "/etc/pkcs11_java.cfg";
Provider p = new sun.security.pkcs11.SunPKCS11(configName);
keyStore = KeyStore.getInstance("PKCS11", p);

with /etc/pkcs11_java.cfg 使用/etc/pkcs11_java.cfg

name=OpenSC
description = SunPKCS11 via OpenSC
library=/usr/local/lib/opensc-pkcs11.so

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM