我有最新的 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/