java - 使用 sunpkcs#11 和 tomcat 移除和插入智能卡

标签 java tomcat smartcard pkcs#11

我有一个在 Tomcat 上运行的 Web 应用程序。我的应用程序使用 Web 服务来签名(通过智能卡)并发送电子邮件。 Web 服务本身会在第一次调用期间和发送电子邮件之前自动添加 sunpkcs#11 提供程序,如果未移除和插入智能卡,则可以登录并发送电子邮件。如果删除并插入,为了发送电子邮件,我必须重新启动 tomcat 服务器,否则它会根据我的代码给出几个错误:

result= api.signAndSend(to, cc, bcc, subject, content, smartCardPin); 

取出和插入智能卡后,此代码给出以下异常消息:

Token has been removed

这些是我的尝试:

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

java.security.InvalidKeyException: No installed provider supports this key: sun.security.pkcs11.P11Key$P11PrivateKey or java.security.InvalidKeyException: No installed provider supports this key: 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);  

这段代码给出:

java.security.ProviderException: Initialization failed at sun.security.pkcs11.P11Signature.initialize(P11Signature.java:319) at sun.security.pkcs11.P11Signature.engineInitSign(P11Signature.java:432) at 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) at org.esign.bouncycastle.operator.jcajce.JcaContentSignerBuilder.build(Unknown Source) . . . Caused by: 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);

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

java.security.InvalidKeyException: No installed provider supports this key: >sun.security.pkcs11.P11Key$P11PrivateKey

此异常不是因为缺少 SunPkcs11,因为我在提供程序列表中看到我添加的 SunPkcs11。

最佳答案

很难找到此类问题的确切解决方案,因为它很难重现,所以根据我的阅读,PKCS#11 已经涵盖了这种正在插入和移除的智能卡场景,根据它documentation ,

This is fine for an application that treats PKCS#11 tokens as static keystores. For an application that wants to accommodate PKCS#11 tokens more dynamically, such as Smartcards being inserted and removed, you can use the new KeyStore.Builder class. Here is an example of how to initialize the builder for a PKCS#11 keystore with a callback handler.

您已经提到删除和添加提供程序不适合您,但根据此 post他们通过这种方式解决它。

关于java - 使用 sunpkcs#11 和 tomcat 移除和插入智能卡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28603628/

相关文章:

java - IntelliJ IDEA : Tomcat 8. 5.13 和 9.0.0.M19 — 工件部署期间出错。有关详细信息,请参阅服务器日志

mysql - Hippo cms 重启构建的项目

tomcat - 部署在 Tomcat 6 上的 WebObjects 5.4.3 导致随机 StackOverflowError

java - 从智能卡读取证书

java - retrofit Minecraft 错误

java - 如何预先验证某个函数是否适用于任何版本的 java jre?

java - 实现复杂首选项屏幕的最佳方式?

java - 无法使用 Firefox 50 通过 SSL 连接到 Jetty 9 服务器

authentication - 什么是私钥挑战?

c - 如何从智能卡获取 universalPrincipalName 对象?