背景信息可能有助于alaysis:
从Web应用程序我尝试连接到智能卡并从客户端计算机上运行的java程序读取证书以执行某些签名操作。 我使用Opensc-PKCS11.dll与java sunpkcs11提供程序类访问智能卡上的证书(FIPS PIV合规智能卡)。
我的问题是只要连接智能卡我就可以访问智能卡上的密钥库并执行加密操作,但是当我们删除智能卡并再次插入时,由于提供商的加载失败,程序无法获取插槽ID
由于我无法对我的插槽ID进行硬编码,因此我将其保留为0 / -1
Config file content
Name="Opensc"
Library="OpenSC-PKCS11.dll"
slot=-1
showinfo=true
byte[] pkcs11configBytes = configName.getBytes();
ByteArrayInputStream confStream = new ByteArrayInputStream(pkcs11configBytes);
bc = new org.bouncycastle.jce.provider.BouncyCastleProvider();
Security.addProvider(bc);
sun = new sun.security.pkcs11.SunPKCS11(confStream);
Security.addProvider(sun);
这个问题确实提供了相关的足够信息。 Java - how to detect smartcard hotplug
更新:我可以解决这个问题。在finally块中,我在提供者的工作完成后从提供者调用了C_Finalize。对于下一次在同一个java实例中的运行,我做了一些事情,比如下面清理PKCS11 map并再次初始化提供程序
Field moduleMapField = PKCS11.class.getDeclaredField("moduleMap");
moduleMapField.setAccessible(true);
Map<?, ?> moduleMap = (Map<?, ?>) moduleMapField.get(null);
moduleMap.clear(); // force re-execution of C_Initialize next time
//load PKCS#11
Method getInstanceMethod = PKCS11.class.getMethod("getInstance",
String.class, String.class, CK_C_INITIALIZE_ARGS.class,
Boolean.TYPE);
CK_C_INITIALIZE_ARGS ck_c_initialize_args = new CK_C_INITIALIZE_ARGS();
pkcs11 = (PKCS11) getInstanceMethod.invoke(null, libFile,
"C_GetFunctionList", ck_c_initialize_args, false);