问题
I have a web application running on Tomcat
. My application uses a web service which signs (via smartcard) and sends email. The web service itself adds the sunpkcs#11
provider automatically during the first call and before sending email, then can sign in and send emails if smartcard is not removed and inserted. If removed and inserted, in order to send email I must restart the tomcat server or it will give several errors depending on my code:
result= api.signAndSend(to, cc, bcc, subject, content, smartCardPin);
After removing and inserting smart card this code gives below exception message:
Token has been removed
These are my tryings:
- I tried removing the
sunpkcs#11
provider just after sending email and creating a newsunpkcs#11
provider and adding it.it gives and error like:
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
- I did not remove sunpkcs#11 provider after each api.signAndSend(...) call,
rather :
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);
this code gives:
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
edit: i remove and add SunPkcs#11 like this:
//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);
after i add a new SunPkcs11, while api.signAndSend(...)
it gives:
java.security.InvalidKeyException: No installed provider supports this key: >sun.security.pkcs11.P11Key$P11PrivateKey
This exception is not because of absence of SunPkcs11 because i see the SunPkcs11 that i added, in the providers list.
回答1:
It is hard to find exact solution in this kind of problem because it is hard to reproduce it so according to my reading PKCS#11 is already cover this Smartcards being inserted and removed scenario according to its 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.
You already mention that remove and add provider is not working for you but according to this post they solve it via this way.
来源:https://stackoverflow.com/questions/28603628/remove-and-insert-smartcard-using-sunpkcs11-and-tomcat