Bug 40826 - Private keys must be instance of RSAPrivate or have PKCS#8 encoding
Summary: Private keys must be instance of RSAPrivate or have PKCS#8 encoding
Status: REOPENED
Alias: None
Product: Security - Now in JIRA
Classification: Unclassified
Component: Signature (show other bugs)
Version: unspecified
Hardware: Other other
: P2 normal
Target Milestone: ---
Assignee: XML Security Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-10-27 04:14 UTC by Fillipe Lima
Modified: 2010-07-28 20:41 UTC (History)
2 users (show)



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Fillipe Lima 2006-10-27 04:14:56 UTC
Hello

I am having a problem. My application is an applet that generate a xml and sign
it with PrivateKey from SmartCard. 

The first time, it works fine! however when i try to sign again (second time), i
get this exception: 

java.security.InvalidKeyException: Private keys must be instance of
RSAPrivate(Crt)Key or have PKCS#8 encoding

The exception occurs when calling the method: DOMSignContext dsc = new
DOMSignContext(pk, doc.getDocumentElement()); This method is part of the
following code:

Does any body know what could i do to solve this problem ?

======= code that generates the xml signature

String providerName = System.getProperty("jsr105Provider",
"org.jcp.xml.dsig.internal.dom.XMLDSigRI");
XMLSignatureFactory fac = XMLSignatureFactory.getInstance(
"DOM",
(Provider) Class.forName(providerName).newInstance());
Reference ref = fac.newReference(
"",
fac.newDigestMethod(DigestMethod.SHA1, null),
Collections.singletonList(fac.newTransform(
Transform.ENVELOPED,
(TransformParameterSpec) null)),
null,
null);

SignedInfo si = fac.newSignedInfo(
fac.newCanonicalizationMethod(
CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS,
(C14NMethodParameterSpec) null),
fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
Collections.singletonList(ref));

KeyInfoFactory kif = fac.getKeyInfoFactory();
X509Data x509 = kif.newX509Data(Collections.singletonList(cert));
KeyInfo ki = kif.newKeyInfo(Collections.singletonList(x509));

DOMSignContext dsc = new DOMSignContext(pk, doc.getDocumentElement());

XMLSignature signature = fac.newXMLSignature(si, ki);
signature.sign(dsc);
return doc; 
}

======= code that get de PrivateKey and Certificate from Smart Card:
String configuracao = "name = SmartCard\n" +
"library = c:\\windows\\system32\\aetpkss1.dll";
byte[] configuracaoBytes = configuracao.getBytes();
ByteArrayInputStream configuracaoStream = new
ByteArrayInputStream(configuracaoBytes);
sun.security.pkcs11.SunPKCS11 provider = new
sun.security.pkcs11.SunPKCS11(configuracaoStream);
Security.addProvider(provider);
this.nomeProvider = provider.getName();
this.repositorio = KeyStore.getInstance("PKCS11", provider);
repositorio.load(null, pin.toCharArray());
this.inicializarDados(pin);

String keyEntry = null;
boolean ok = false;

Enumeration en = repositorio.aliases();
while(en.hasMoreElements()) {
keyEntry = (String)en.nextElement();
if(repositorio.isKeyEntry(keyEntry)){
ok = true;
break;
}
}
if(ok){
certificado = (X509Certificate) repositorio.getCertificate(keyEntry);
chavePrivada = (PrivateKey) repositorio.getKey(keyEntry, pin.toCharArray());
Comment 1 sean.mullan 2006-10-27 07:46:46 UTC
(In reply to comment #0)
> Hello
> 
> I am having a problem. My application is an applet that generate a xml and sign
> it with PrivateKey from SmartCard. 
> 
> The first time, it works fine! however when i try to sign again (second time), i
> get this exception: 
> 
> java.security.InvalidKeyException: Private keys must be instance of
> RSAPrivate(Crt)Key or have PKCS#8 encoding

This exception indicates that you are trying to use the key that is 
stored on the smart card with a software based crypto provider. It won't work. 
See http://java.sun.com/j2se/1.5.0/docs/guide/security/p11guide.html#DelayedSelect
for some more information about that.

However, we need to figure out why you are getting that exception. 

> The exception occurs when calling the method: DOMSignContext dsc = new
> DOMSignContext(pk, doc.getDocumentElement()); This method is part of the
> following code:
> 
> Does any body know what could i do to solve this problem ?

Can you attach the full exception stack trace?
Comment 2 Fillipe Lima 2006-10-27 09:20:54 UTC
(In reply to comment #1)
> (In reply to comment #0)
> > Hello
> > 
> > I am having a problem. My application is an applet that generate a xml and 
sign
> > it with PrivateKey from SmartCard. 
> > 
> > The first time, it works fine! however when i try to sign again (second 
time), i
> > get this exception: 
> > 
> > java.security.InvalidKeyException: Private keys must be instance of
> > RSAPrivate(Crt)Key or have PKCS#8 encoding
> This exception indicates that you are trying to use the key that is 
> stored on the smart card with a software based crypto provider. It won't 
work. 
> See 
http://java.sun.com/j2se/1.5.0/docs/guide/security/p11guide.html#DelayedSelect
> for some more information about that.
> However, we need to figure out why you are getting that exception. 
> > The exception occurs when calling the method: DOMSignContext dsc = new
> > DOMSignContext(pk, doc.getDocumentElement()); This method is part of the
> > following code:
> > 
> > Does any body know what could i do to solve this problem ?
> Can you attach the full exception stack trace?

I will try to do this:

"It is recommended that applications only call getProvider() after they have 
called the relevant initialization method. "

Im using xml signature... 
i) Is this my initialization method "XMLSignature signature = 
fac.newXMLSignature(si, ki)"; ?

ii) Is my getProvider() this part? "XMLSignatureFactory fac = 
XMLSignatureFactory.getInstance(
"DOM",
(Provider) Class.forName(providerName).newInstance());
Reference ref = fac.newReference(
"",
fac.newDigestMethod(DigestMethod.SHA1, null),
Collections.singletonList(fac.newTransform(
Transform.ENVELOPED,
(TransformParameterSpec) null)),
null,
null);
" ?

The complete stack trace:

AssinaturaXMLException: java.security.InvalidKeyException: Private keys must be 
instance of RSAPrivate(Crt)Key or have PKCS#8 encoding
	at AssinaturaXMLEnveloped.assinar(AssinaturaXMLEnveloped.java:86)
	at AssinadorDigital.AssinarDados(AssinadorDigital.java:133)
	at AssinadorDigital.btnAssinar_actionPerformed
(AssinadorDigital.java:189)
	at AssinadorDigital_btnAssinar_actionAdapter.actionPerformed
(AssinadorDigital.java:201)
	at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
	at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown 
Source)
	at java.awt.Component.processMouseEvent(Unknown Source)
	at javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)

Comment 3 sean.mullan 2006-10-27 10:18:28 UTC
(In reply to comment #2)

> The complete stack trace:
> 
> AssinaturaXMLException: java.security.InvalidKeyException: Private keys must be 
> instance of RSAPrivate(Crt)Key or have PKCS#8 encoding
> 	at AssinaturaXMLEnveloped.assinar(AssinaturaXMLEnveloped.java:86)

This stack trace doesn't help. The AssinaturaXMLException is swallowing the
stack trace of the cause: InvalidKeyException. I need to have that the stack
trace of the InvalidKeyException to be able to help.
Comment 4 Fillipe Lima 2006-10-27 15:15:23 UTC
(In reply to comment #3)
> (In reply to comment #2)
> > The complete stack trace:
> > 
> > AssinaturaXMLException: java.security.InvalidKeyException: Private keys 
must be 
> > instance of RSAPrivate(Crt)Key or have PKCS#8 encoding
> > 	at AssinaturaXMLEnveloped.assinar(AssinaturaXMLEnveloped.java:86)
> This stack trace doesn't help. The AssinaturaXMLException is swallowing the
> stack trace of the cause: InvalidKeyException. I need to have that the stack
> trace of the InvalidKeyException to be able to help.

Ok. I think this may help:

javax.xml.crypto.dsig.XMLSignatureException: java.security.InvalidKeyException: 
Private keys must be instance of RSAPrivate(Crt)Key or have PKCS#8 encoding
	at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign
(DOMXMLSignature.java:370)
	at AssinaturaXMLEnveloped.assinar(AssinaturaXMLEnveloped.java:80)
	at AssinadorDigital.AssinarDados(AssinadorDigital.java:134)
	at AssinadorDigital.btnAssinar_actionPerformed
(AssinadorDigital.java:190)
	at AssinadorDigital_btnAssinar_actionAdapter.actionPerformed
(AssinadorDigital.java:202)
	at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
	at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown 
Source)
	at java.awt.Component.processMouseEvent(Unknown Source)
	at javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)
Caused by: java.security.InvalidKeyException: Private keys must be instance of 
RSAPrivate(Crt)Key or have PKCS#8 encoding
	at sun.security.rsa.RSAKeyFactory.translatePrivateKey(Unknown Source)
	at sun.security.rsa.RSAKeyFactory.engineTranslateKey(Unknown Source)
	at sun.security.rsa.RSAKeyFactory.toRSAKey(Unknown Source)
	at sun.security.rsa.RSASignature.engineInitSign(Unknown Source)
	at sun.security.rsa.RSASignature.engineInitSign(Unknown Source)
	at java.security.Signature$Delegate.init(Unknown Source)
	at java.security.Signature$Delegate.chooseProvider(Unknown Source)
	at java.security.Signature$Delegate.engineInitSign(Unknown Source)
	at java.security.Signature.initSign(Unknown Source)
	at org.jcp.xml.dsig.internal.dom.DOMRSASignatureMethod.sign
(DOMRSASignatureMethod.java:134)
	at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign
(DOMXMLSignature.java:367)
	... 27 more
java.security.InvalidKeyException: Private keys must be instance of RSAPrivate
(Crt)Key or have PKCS#8 encoding
	at sun.security.rsa.RSAKeyFactory.translatePrivateKey(Unknown Source)
	at sun.security.rsa.RSAKeyFactory.engineTranslateKey(Unknown Source)
	at sun.security.rsa.RSAKeyFactory.toRSAKey(Unknown Source)
	at sun.security.rsa.RSASignature.engineInitSign(Unknown Source)
	at sun.security.rsa.RSASignature.engineInitSign(Unknown Source)
	at java.security.Signature$Delegate.init(Unknown Source)
	at java.security.Signature$Delegate.chooseProvider(Unknown Source)
	at java.security.Signature$Delegate.engineInitSign(Unknown Source)
	at java.security.Signature.initSign(Unknown Source)
	at org.jcp.xml.dsig.internal.dom.DOMRSASignatureMethod.sign
(DOMRSASignatureMethod.java:134)
	at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign
(DOMXMLSignature.java:367)
	at AssinaturaXMLEnveloped.assinar(AssinaturaXMLEnveloped.java:80)
	at AssinadorDigital.AssinarDados(AssinadorDigital.java:134)
	at AssinadorDigital.btnAssinar_actionPerformed
(AssinadorDigital.java:190)
	at AssinadorDigital_btnAssinar_actionAdapter.actionPerformed
(AssinadorDigital.java:202)
	at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
	at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown 
Source)
	at java.awt.Component.processMouseEvent(Unknown Source)
	at javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)
java.security.InvalidKeyException: Private keys must be instance of RSAPrivate
(Crt)Key or have PKCS#8 encoding
	at sun.security.rsa.RSAKeyFactory.translatePrivateKey(Unknown Source)
	at sun.security.rsa.RSAKeyFactory.engineTranslateKey(Unknown Source)
	at sun.security.rsa.RSAKeyFactory.toRSAKey(Unknown Source)
	at sun.security.rsa.RSASignature.engineInitSign(Unknown Source)
	at sun.security.rsa.RSASignature.engineInitSign(Unknown Source)
	at java.security.Signature$Delegate.init(Unknown Source)
	at java.security.Signature$Delegate.chooseProvider(Unknown Source)
	at java.security.Signature$Delegate.engineInitSign(Unknown Source)
	at java.security.Signature.initSign(Unknown Source)
	at org.jcp.xml.dsig.internal.dom.DOMRSASignatureMethod.sign
(DOMRSASignatureMethod.java:134)
	at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign
(DOMXMLSignature.java:367)
	at AssinaturaXMLEnveloped.assinar(AssinaturaXMLEnveloped.java:80)
	at AssinadorDigital.AssinarDados(AssinadorDigital.java:134)
	at AssinadorDigital.btnAssinar_actionPerformed
(AssinadorDigital.java:190)
	at AssinadorDigital_btnAssinar_actionAdapter.actionPerformed
(AssinadorDigital.java:202)
	at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
	at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown 
Source)
	at java.awt.Component.processMouseEvent(Unknown Source)
	at javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)
AssinaturaXMLException: java.security.InvalidKeyException: Private keys must be 
instance of RSAPrivate(Crt)Key or have PKCS#8 encoding
	at AssinaturaXMLEnveloped.assinar(AssinaturaXMLEnveloped.java:87)
	at AssinadorDigital.AssinarDados(AssinadorDigital.java:134)
	at AssinadorDigital.btnAssinar_actionPerformed
(AssinadorDigital.java:190)
	at AssinadorDigital_btnAssinar_actionAdapter.actionPerformed
(AssinadorDigital.java:202)
	at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
	at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown 
Source)
	at java.awt.Component.processMouseEvent(Unknown Source)
	at javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)

Comment 5 Fillipe Lima 2006-10-28 14:28:43 UTC
(In reply to comment #4)
> (In reply to comment #3)
> > (In reply to comment #2)
> > > The complete stack trace:
> > > 
> > > AssinaturaXMLException: java.security.InvalidKeyException: Private keys 
> must be 
> > > instance of RSAPrivate(Crt)Key or have PKCS#8 encoding
> > > 	at AssinaturaXMLEnveloped.assinar(AssinaturaXMLEnveloped.java:86)
> > This stack trace doesn't help. The AssinaturaXMLException is swallowing the
> > stack trace of the cause: InvalidKeyException. I need to have that the stack
> > trace of the InvalidKeyException to be able to help.
> 
> Ok. I think this may help:
> 
> javax.xml.crypto.dsig.XMLSignatureException: java.security.InvalidKeyException: 
> Private keys must be instance of RSAPrivate(Crt)Key or have PKCS#8 encoding

Hello

I solved the problem just changing the way i get the instance of the KeyStore: 
It was: "this.repositorio = KeyStore.getInstance("PKCS11", provider);"
Now is: "this.repositorio = KeyStore.getInstance("PKCS11");"
I singed the xml many times, without closing the application and it´s is working
fine now.

But i still have some doubts....

1) If i use KeyStore.getInstance("PKCS11", provider) The Exception doesnt occurs
 at the first time and the xml document is signed normally. However, i if try to
sign again, the exception occurs. why ? is it a Bug ?

2) What´s the difference between each one? When use each one ?

Tks
Comment 6 sean.mullan 2006-10-30 13:18:13 UTC
 
> But i still have some doubts....
> 
> 1) If i use KeyStore.getInstance("PKCS11", provider) The Exception doesnt occurs
>  at the first time and the xml document is signed normally. However, i if try to
> sign again, the exception occurs. why ? is it a Bug ?

I don't think so. The only thing that makes sense to me is that the first key is
software based, and then the subsequent keys are hardware based and used with
a cached Signature object that is software based. Are you reusing 
the XMLSignature objects each time you sign? Have you tried extracting the key
contents to see if it is hardware or software (ex: Key.getFormat should 
return "RAW" if it is hardware).
> 
> 2) What´s the difference between each one? When use each one ?

I don't think I understand the question.

> 
> Tks
Comment 7 Fillipe Lima 2006-10-30 16:02:15 UTC
(In reply to comment #6)
>  
> > But i still have some doubts....
> > 
> > 1) If i use KeyStore.getInstance("PKCS11", provider) The Exception doesnt 
occurs
> >  at the first time and the xml document is signed normally. However, i if 
try to
> > sign again, the exception occurs. why ? is it a Bug ?
> I don't think so. The only thing that makes sense to me is that the first key 
is
> software based, and then the subsequent keys are hardware based and used with
> a cached Signature object that is software based. Are you reusing 
> the XMLSignature objects each time you sign? Have you tried extracting the key
> contents to see if it is hardware or software (ex: Key.getFormat should 
> return "RAW" if it is hardware).
> > 
> > 2) What´s the difference between each one? When use each one ?
> I don't think I understand the question.
> > 
> > Tks

No. I am not reusing the XMLSignature objects each time i sign. 
Yes. I tried extracting the key contents: "SunPKCS11-SmartCard RSA private key, 
1024 bits (id 1, token object, not sensitive, unextractable)
"

the question 2 is: what's the difference between using KeyStore.getInstance
("PKCS11", provider) and using KeyStore.getInstance("PKCS11"). When use each 
one ?
I know that to use KeyStore.getInstance("PKCS11") i must have to call 
Security.addProvider() before. but...which use ? 
Comment 8 Frank Cornelis 2006-10-30 23:05:21 UTC
I'm experiencing the same kind of weird behavior when I try to sign twice. The
code does something like:

Document document = loadDocument();

smartCard.open(...); // registers SunPKCS11 provider
PrivateKey privateKey = smartCard.getPrivateKey(); // from the keystore

xmlSign(document, privateKey, ...);

smartCard.close(); // removes SunPKCS11 provider
smartCard.open(...); // registers SunPKCS11 provider again
PrivateKey privateKey = smartCard.getPrivateKey();

xmlSign(document, privateKey, ...);

The second sign operation gives me:
Caused by: org.apache.xml.security.signature.XMLSignatureException: Private key
must be instance of RSAPrivate(Crt)Key or have PKCS#8 encoding
Original Exception was org.apache.xml.security.signature.XMLSignatureException:
Private key must be instance of RSAPrivate(Crt)Key or have PKCS#8 encoding
Original Exception was java.security.InvalidKeyException: Private key must be
instance of RSAPrivate(Crt)Key or have PKCS#8 encoding
	at org.apache.xml.security.signature.XMLSignature.sign(Unknown Source)

In my smart card code it doesn't matter whether to use
KeyStore.Builder builder = KeyStore.Builder.newInstance("PKCS11",
    this.pkcs11Provider, callbackHandlerProtection);
or
...("PKCS11", null, callbackHandlerProtection);

I always get the exception. The funny thing is that I can sign twice via a
non-XML signature, i.e., using
Signature.getInstance("SHA1withRSA");
but, when using xmlsec, it's throwing the exception.
Comment 9 sean.mullan 2006-11-01 14:21:59 UTC
Ok, I looked into this a little bit more and still need more details.

First, if you remove the SunPKCS11 provider and create a new instance, then any
PrivateKey objects from the old SunPKCS11 instance will not be usable with the
new instance (and this exception will be thrown). 
If the privateKey object is from the new provider, it should work. 

Can you let me know if you are doing this?
Comment 10 Fillipe Lima 2006-11-02 05:36:25 UTC
(In reply to comment #9)
> Ok, I looked into this a little bit more and still need more details.
> 
> First, if you remove the SunPKCS11 provider and create a new instance, then any
> PrivateKey objects from the old SunPKCS11 instance will not be usable with the
> new instance (and this exception will be thrown). 
> If the privateKey object is from the new provider, it should work. 
> 
> Can you let me know if you are doing this?

Each time i sign, i add the provider (Security.addProvider(p)) and create a new
PrivateKey object. Im not reusing nothing.. is it correct ? or i must have to
remove and add the provider each time? from what i know...when we use the
addProvider, it add the provider in the available slot, but we can add in a
specific slot, just using addProviderAt(p, 2) for instance.
Comment 11 sean.mullan 2006-11-02 07:42:41 UTC
> Each time i sign, i add the provider (Security.addProvider(p)) and create a new
> PrivateKey object. Im not reusing nothing.. is it correct ? or i must have to
> remove and add the provider each time? from what i know...when we use the
> addProvider, it add the provider in the available slot, but we can add in a
> specific slot, just using addProviderAt(p, 2) for instance.

Ahh, here's what I think is happening:

The first time you call Security.addProvider(p), your provider is added 
correctly, you create a new PrivateKey object using that same provider and
the xml signing operation works ok.

The next time you create a new provider and call Security.addProvider(p), 
I bet the provider is not added because it is already installed (from the APIs
standpoint, it is the same provider even though it is a new instance). Check 
the return value of addProvider to see if it returns -1. 

*But* (and this is a major but), you then use the new provider instance to
create a PrivateKey object. There's the problem. When you use this PrivateKey
to sign, the xml signature cannot find the provider that you used to create it
(since it is not installed, it only finds the old provider but that won't
work with the new PrivateKey) and therefore the signing operation fails because
it cannot find a provider that the key can be used with.

Workarounds:

Either, 1) explicitly remove the provider before you reinstall it each 
time, or 2) only create and install the provider once and always use 
this provider to create the PrivateKeys.  

Please confirm if this is the case. 
Comment 12 Fillipe Lima 2006-11-02 09:44:52 UTC
(In reply to comment #11)
> > Each time i sign, i add the provider (Security.addProvider(p)) and create a new
> > PrivateKey object. Im not reusing nothing.. is it correct ? or i must have to
> > remove and add the provider each time? from what i know...when we use the
> > addProvider, it add the provider in the available slot, but we can add in a
> > specific slot, just using addProviderAt(p, 2) for instance.
> 
> Ahh, here's what I think is happening:
> 
> The first time you call Security.addProvider(p), your provider is added 
> correctly, you create a new PrivateKey object using that same provider and
> the xml signing operation works ok.
> 
> The next time you create a new provider and call Security.addProvider(p), 
> I bet the provider is not added because it is already installed (from the APIs
> standpoint, it is the same provider even though it is a new instance). Check 
> the return value of addProvider to see if it returns -1. 
> 
> *But* (and this is a major but), you then use the new provider instance to
> create a PrivateKey object. There's the problem. When you use this PrivateKey
> to sign, the xml signature cannot find the provider that you used to create it
> (since it is not installed, it only finds the old provider but that won't
> work with the new PrivateKey) and therefore the signing operation fails because
> it cannot find a provider that the key can be used with.
> 
> Workarounds:
> 
> Either, 1) explicitly remove the provider before you reinstall it each 
> time, or 2) only create and install the provider once and always use 
> this provider to create the PrivateKeys.  
> 
> Please confirm if this is the case. 


Exactly! the addProvider is returning -1 at the second time! (the first returned
a high position: 7). however i am not having problems anymore because im using
like this: 

Security.addProvider(p);
KeyStore.getInstance("PKCS11");

If i use KeyStore.getInstance("PKCS11", p), then i get the exception the second
time!

Sean Mullan, Thank you very much for your clarifications! i am doing this as a
part of my monograph project (Information Systems course). I will put your name
in the gratfulness area! :))
Comment 13 sean.mullan 2006-11-06 11:55:47 UTC
Closing this out, as it looks like my explanation is correct and the 
problem has been resolved.
Comment 14 Alon Bar-Lev 2007-08-08 13:29:14 UTC
As PKCS#11 has so great design, a separate instance must be instantiate for 
each slot of each provider.

I tried to do what you requested, registered the provider to system, and passed 
null to KeyStore.Builder as a provider and it does work.

But I don't think this is a valid solution, as there is no reason why all 
providers should be added to the global scope.
Comment 15 Alon Bar-Lev 2007-08-09 12:28:51 UTC
Thought about this again...
And I don't think this solution is valid.
By convention all crypto functions throughout the SDK API accept explicit 
provider.
If you can find another exception to this rule I may understand and drop 
this...
But if xmlsec is the only exception, than it should sync up.
Comment 16 sean.mullan 2007-08-10 09:51:35 UTC
(In reply to comment #15)
> Thought about this again...
> And I don't think this solution is valid.
> By convention all crypto functions throughout the SDK API accept explicit 
> provider.
> If you can find another exception to this rule I may understand and drop 
> this...
> But if xmlsec is the only exception, than it should sync up.

xmlsec/jsr 105 are at a higher layer than the JCE APIs.
I still think there should be a workaround to your problem. 
Something is happening in your code that causes the 
PrivateKey's provider to be different than what is in the JRE's list of
Providers.  Have you tried the solution in this bug report, that is:

Security.addProvider(p);
KeyStore.getInstance("PKCS11");

Comment 17 Dario Napolitano 2008-08-07 02:17:07 UTC
I seem to be experiencing the same problem reported in this bug, but no workaround seems to be effective, apart form restarting the application altogether.

The situation I have is this: my application makes use of several different types of KeyStore. The user can use a configuration window to select which one to use, and even change some properties (e.g. the .dll module for the PKCS11 provider, or the slot number).
The application uses the selected provider to send SOAP requests using Axis/Rampart 1.3. I have written a replacement Crypto class for Rampart that gets the keys and certificates from the correct keystore/provider. While everything works fine with JKS keystores, the PKCS11 provider only works until it gets reconfigured. 

Please note that I remove the previous Provider instance entirely, discard all previously obtained keys and keystores and recreate everything anew, but only the very first instance of the PKCS11 provider works.

Code excerpt:
----------------------------------------------------
StringBuilder sb = new StringBuilder();
sb.append("name = ");
sb.append(providerName);
sb.append("\nlibrary = ");
sb.append(ConfigManager.getInstance().getConf().getDllPkcs11()); // Get the selected PKCS11 DLL
sb.append("\nslot ="); 
sb.append(ConfigManager.getInstance().getConf().getPkcs11Slot()); // Get the selected slot
sb.append("\ndisabledMechanisms = { CKM_SHA1_RSA_PKCS }\n");
		
String pkcs11config = sb.toString();
		
byte pkcs11configBytes[] = pkcs11config.getBytes();
ByteArrayInputStream configStream = new ByteArrayInputStream(pkcs11configBytes);
if (Security.getProvider(fullProvName)!=null) // Provider name + SunPKCS11 prefix
	Security.removeProvider(fullProvName);
prov = new SunPKCS11(configStream);
Security.insertProviderAt(prov, 1); // This is done to have Rampart select this provider for signature operations.
ks = KeyStore.getInstance("PKCS11");
-----------------------------------------------------

Any key obtained after the first ever Provider instance gets replaced leads to this exception:

-----------------------------------------------------
org.apache.ws.security.WSSecurityException: Signature creation failed; nested exception is: 
	org.apache.xml.security.signature.XMLSignatureException: Private key must be instance of RSAPrivate(Crt)Key or have PKCS#8 encoding
Original Exception was org.apache.xml.security.signature.XMLSignatureException: Private key must be instance of RSAPrivate(Crt)Key or have PKCS#8 encoding
Original Exception was java.security.InvalidKeyException: Private key must be instance of RSAPrivate(Crt)Key or have PKCS#8 encoding
	at org.apache.ws.security.message.WSSecSignature.computeSignature(WSSecSignature.java:663)
	at org.apache.rampart.builder.AsymmetricBindingBuilder.doSignature(AsymmetricBindingBuilder.java:611)
	at org.apache.rampart.builder.AsymmetricBindingBuilder.doSignBeforeEncrypt(AsymmetricBindingBuilder.java:385)
	at org.apache.rampart.builder.AsymmetricBindingBuilder.build(AsymmetricBindingBuilder.java:95)
	at org.apache.rampart.MessageBuilder.build(MessageBuilder.java:131)
	at org.apache.rampart.handler.RampartSender.invoke(RampartSender.java:64)
	at org.apache.axis2.engine.Phase.invoke(Phase.java:292)
	at org.apache.axis2.engine.AxisEngine.invoke(AxisEngine.java:212)
	at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:377)
	at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:374)
	at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:211)
	at org.apache.axis2.client.OperationClient.execute(OperationClient.java:163)
-----------------------------------------------------



Is there any way to replace the PKCS11 provider without having to restart the application? Note that since I have to change the configuration parameters at run-time I cannot leave the first provider instance alone...
Comment 18 sean.mullan 2008-08-07 06:09:35 UTC
Have you tried the workaround implemented in bug 43056:

In order to use a specific provider, you must pass the Provider object
as a property to the XMLSignContext or XMLValidateContext, ex:

signContext.setProperty
    ("org.jcp.xml.dsig.internal.dom.SignatureProvider", new MyProvider());
Comment 19 Dario Napolitano 2008-08-07 07:52:07 UTC
Unfortunately I do not have access to the signature contexts, as they are entirely handled by Rampart. In fact to 'encourage' Rampart to use the right provider I force it to the highest priority, by using Security.insertAt().

However from my testing it seems that Rampart does select the right provider, but the provider fails to work if it's not the first time that it has been instanced. If I don't try to remove and recreate it, it works any number of times. If I have to change any parameter (for example the slot number) I have to restart the application (and the virtual machine).
Comment 20 Giedrius Noreikis 2010-02-18 23:26:32 UTC
Hi,

I am experiencing the same problem.
My application uses org.apache.xml.security.signature.XMLSignature for signing with software and hardware based keys. Each time when signing with PKCS#11 hardware, the appropriate security provider is created, added and then removed after the signing.

The first time everyting works fine. However, if I try to sign again, the org.apache.xml.security.signature.XMLSignatureException with message "Private key must be instance of RSAPrivate(Crt)Key or have PKCS#8 encoding" is thrown:

org.apache.xml.security.signature.XMLSignatureException: Private key must be instance of RSAPrivate(Crt)Key or have PKCS#8 encoding
Original Exception was java.security.InvalidKeyException: Private key must be instance of RSAPrivate(Crt)Key or have PKCS#8 encoding
	at org.apache.xml.security.algorithms.implementations.SignatureBaseRSA.engineInitSign(SignatureBaseRSA.java:181)
	at org.apache.xml.security.algorithms.SignatureAlgorithm.initSign(SignatureAlgorithm.java:276)
	at org.apache.xml.security.signature.XMLSignature.sign(XMLSignature.java:497)
	...
java.security.InvalidKeyException: Private key must be instance of RSAPrivate(Crt)Key or have PKCS#8 encoding
	at sun.security.pkcs11.P11RSAKeyFactory.implTranslatePrivateKey(P11RSAKeyFactory.java:84)
	at sun.security.pkcs11.P11KeyFactory.engineTranslateKey(P11KeyFactory.java:115)
	at sun.security.pkcs11.P11KeyFactory.convertKey(P11KeyFactory.java:48)
	at sun.security.pkcs11.P11Signature.engineInitSign(P11Signature.java:375)
	at java.security.Signature$Delegate.engineInitSign(Unknown Source)
	at java.security.Signature.initSign(Unknown Source)
	at org.apache.xml.security.algorithms.implementations.SignatureBaseRSA.engineInitSign(SignatureBaseRSA.java:179)
	at org.apache.xml.security.algorithms.SignatureAlgorithm.initSign(SignatureAlgorithm.java:276)
	at org.apache.xml.security.signature.XMLSignature.sign(XMLSignature.java:497)
	...

The interesting thing is, if I retry the signing after catching the exception, it succeeds. I found out that this "recovery" is caused by the "cache cleanup" (XMLSignature:510):
try {
    // initialize SignatureAlgorithm for signing
    sa.initSign(signingKey);
    ...
} catch (XMLSecurityException ex) {
    sa.clearSignatureCache();
    throw ex;
}

And the problem itself is caused by the "cache" ("SignatureAlgorithm.instancesSigning" variable). This map holds instances of SignatureAlgorithmSpi descendants. SignatureBaseRSA, which extends SignatureAlgorithmSpi, has "private java.security.Signature _signatureAlgorithm" variable, which, obviously, is initialised only once, and later gets associated with the first "suitable" security provider.

During the second invocation, this provider (which is already removed BTW, but it doesn't matter - instance of java.security.Signature still holds a reference to it) is fed with a PrivateKey obtained from the newly added provider. This leads to futile attempts to "convert" the key and finally the InvalidKeyException.

There are several possible workarounds (tested and confirmed to work):
1. try-catch and then retry, letting the "recovery" magic to do the work :)
2. Manual "cache cleanup" before the signing, for example:

new SignatureAlgorithm(doc, signature.getSignedInfo().getSignatureMethodURI()).clearSignatureCache();
(actually, clearSignatureCache() should be static, if it is intended for a "public" use - creating an instance of the SignatureAlgorithm is pointless here)

Or, the "instancesSigning" can be cleared directly, using the reflection (this is for research only, of course):

Field f = SignatureAlgorithm.class.getDeclaredField("instancesSigning");
f.setAccessible(true);
ThreadLocal t = (ThreadLocal)f.get(null);
Map instancesMap = (Map)t.get();
instancesMap.clear();

3. Since the "cache" is implemented per-thread, the problem can be avoided by calling the sign() from a newly-created thread.


Thinking of the possible fixes, one solution could be implementing SignatureBaseRSA.reset() (like in IntegrityHmac), which would assing a new instance to the _signatureAlgorithm. If it's worth having such a "cache" at all.
Comment 21 Jason Marshall 2010-07-27 20:09:09 UTC
I have a coworker who is experiencing this problem.

The error doesn't happen in 1.3.0.  Something changed in the interim.  We first saw this in 1.4.1, and reproed it in 1.4.3
Comment 22 Giedrius Noreikis 2010-07-28 20:41:03 UTC
(In reply to comment #21)
> I have a coworker who is experiencing this problem.
> The error doesn't happen in 1.3.0.  Something changed in the interim.  We first
> saw this in 1.4.1, and reproed it in 1.4.3

I am not sure if the cause of the problem is the same, but regarding my case (see comment #20) the optimization with the "SignatureAlgorithm.instancesSigning" variable was introduced in r413543 on Jun 11 2006 (as "instances" variable, later split into "instancesSigning" and "instancesVerify"). Version 1.3 was released in October 2005; Version 1.4 - in January 2007. So yes, that happened in the interim.