使用sunpkcs#11和tomcat删除并插入智能卡

ihs*_*cak 5 java tomcat smartcard pkcs#11

我正在运行一个Web应用程序Tomcat.我的应用程序使用Web服务(通过智能卡)签名并发送电子邮件.Web服务本身会sunpkcs#11在第一次调用期间和发送电子邮件之前自动添加提供程序,然后如果未删除和插入智能卡,则可以登录并发送电子邮件.如果删除并插入,为了发送电子邮件,我必须重新启动tomcat服务器,否则它会产生一些错误,具体取决于我的代码:

result= api.signAndSend(to, cc, bcc, subject, content, smartCardPin); 
Run Code Online (Sandbox Code Playgroud)

删除并插入智能卡后,此代码提供以下异常消息:

令牌已被删除

这些是我的尝试:

  1. 我尝试sunpkcs#11在发送电子邮件并创建新sunpkcs#11提供程序并添加它之后删除提供程序.它给出了错误,如:

java.security.InvalidKeyException:没有安装的提供程序支持此密钥:sun.security.pkcs11.P11Key $ P11PrivateKey或java.security.InvalidKeyException:没有安装的提供程序支持此密钥:null

  1. 在每次api.signAndSend(...)调用后,我没有删除sunpkcs#11提供程序,

而是:

  result= api.signAndSend(to, cc, bcc, subject, content, smartCardPin);  
  SunPKCS11 sunPKCS11=(SunPKCS11)getLastProvider();  
  sunPKCS11.logout();  
  sunPKCS11.setCallbackHandler(new MyCallbackHandler());  
  KeyStore.CallbackHandlerProtection cpprotection = new KeyStore.CallbackHandlerProtection(  
  new MyCallbackHandler());  
  KeyStore.Builder builder = KeyStore.Builder.newInstance(  
  "PKCS11", sunPKCS11, cpprotection);  
  KeyStore ks = builder.getKeyStore();  

//finalize PKCS#11  
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(i expect this code to load pkcs#11 again but i am not sure)  
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 = (PKCS11) getInstanceMethod.invoke(null, pkcs11Path,  
  "C_GetFunctionList", ck_c_initialize_args, false);  
Run Code Online (Sandbox Code Playgroud)

这段代码给出:

java.security.ProviderException:sun.security.pkcs11.P11Signature.initialize(P11Signature.java:319)初始化失败,位于sun.security.pkcs11.P11Signature.engineInitSign(P11Signature.java:432),位于java.security.Signature $ Delegate .init(Signature.java:1127)at java.security.Signature $ Delegate.chooseProvider(Signature.java:1087)at java.security.Signature $ Delegate.engineInitSign(Signature.java:1151)at java.security.Signature. initSign(Signature.java:512)位于org.esign.bouncycastle.operator.jcajce.JcaContentSignerBuilder.build(未知来源)...引起:sun.security.pkcs11.wrapper.PKCS11Exception:CKR_KEY_HANDLE_INVALID at sun.security.pkcs11.wrapper.PKCS11.C_SignInit(Native Method)at sun.security.pkcs11.wrapper.PKCS11 $ SynchronizedPKCS11.C_SignInit(PKCS11.java:1721) )at sun.security.pkcs11.P11Signature.initialize(P11Signature.java:311)

java:1.8.0.31

编辑:我删除并添加SunPkcs#11,如下所示:

//the code below adds sunpkcss provider automatically after first call
result= api.signAndSend(to, cc, bcc, subject, content, smartCardPin);

//after each signAndSend i remove sunpkcs and add a new one
String sunpkcs11Name=getLastProvider().getName();
Security.removeProvider(sunpkcs11Name);

String cfg = MessageFormat.format(
                "name = Starcos-SunPkcs11  library = c:/windows/system32/aetpkss1.dll slot = 52481 ");
        InputStream is=new ByteArrayInputStream(cfg.getBytes());

SunPKCS11 newSunPkcs11Provider = new SunPKCS11(is);
Security.addProvider(newSunPkcs11Provider);
Run Code Online (Sandbox Code Playgroud)

在我添加一个新的SunPkcs11之后,api.signAndSend(...)它给出了:

java.security.InvalidKeyException:没有安装的提供程序支持此密钥:> sun.security.pkcs11.P11Key $ P11PrivateKey

此异常不是因为没有SunPkcs11,因为我在提供者列表中看到了我添加的SunPkcs11.

erh*_*hun 3

很难在此类问题中找到确切的解决方案,因为很难重现它,因此根据我的阅读,PKCS#11 已经涵盖了根据其文档插入和删除智能卡的场景,

这对于将 PKCS#11 令牌视为静态密钥库的应用程序来说很好。对于想要更动态地容纳 PKCS#11 令牌(例如插入和移除智能卡)的应用程序,您可以使用新的 KeyStore.Builder 类。以下是如何使用回调处理程序初始化 PKCS#11 密钥库的构建器的示例。

您已经提到删除和添加提供程序不适合您,但根据这篇文章,他们通过这种方式解决了这个问题。