Hello, At src/org/jcp/xml/dsig/internal/dom/DOMRSASignatureMethod.java the Signature object is used, but it is initialized without a provider. [Relevant for decryption] The problem is that if a hardware based provider is used (One which cannot extract its private key), the signature fails. The expected behavior is to use a specific provider as any other java crypto methods. I know there is an issue with the interface stabilization... But this is a required functionality, as there is no security without hardware cryptography... And security packages should be the first to support this. Thanks!
Can you please send more information, such as the exception stack trace and details of the software you are using (JDK, provider)? Enhancements to JDK 5 were made to specifically address the problems with unextractable keys that you are reporting. You should not have to specify a specific provider. For more information, see: http://java.sun.com/javase/6/docs/technotes/guides/security/p11guide.html#DelayedSelect
Hello, I am using sun JVM version 1.5 and 1.6. I am using the PKCS#11 provider. This provider provides SHA1withRSA. Its priority is lower than the default provider that also provides SHA1withRSA. So the default provider try to perform the RSA operation so it tries to translate the PrivateKey into RSAPrivateKey to extract the attribute, and it fails. And for the up-coming question... No... PKCS#11 provider cannot be the first one, as many things will go wrong... :) --- 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) 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(RSAKeyFactory.java:246) at sun.security.rsa.RSAKeyFactory.engineTranslateKey(RSAKeyFactory.java:149) at sun.security.rsa.RSAKeyFactory.toRSAKey(RSAKeyFactory.java:79) at sun.security.rsa.RSASignature.engineInitSign(RSASignature.java:90) at sun.security.rsa.RSASignature.engineInitSign(RSASignature.java:84) at java.security.Signature$Delegate.init(Signature.java:1073) at java.security.Signature$Delegate.chooseProvider(Signature.java:1033) at java.security.Signature$Delegate.engineInitSign(Signature.java:1097) at java.security.Signature.initSign(Signature.java:480) at org.jcp.xml.dsig.internal.dom.DOMRSASignatureMethod.sign(DOMRSASignatureMethod.java:162) at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(DOMXMLSignature.java:367) ... 2 more java.security.InvalidKeyException: Private keys must be instance of RSAPrivate(Crt)Key or have PKCS#8 encoding at sun.security.rsa.RSAKeyFactory.translatePrivateKey(RSAKeyFactory.java:246) at sun.security.rsa.RSAKeyFactory.engineTranslateKey(RSAKeyFactory.java:149) at sun.security.rsa.RSAKeyFactory.toRSAKey(RSAKeyFactory.java:79) at sun.security.rsa.RSASignature.engineInitSign(RSASignature.java:90) at sun.security.rsa.RSASignature.engineInitSign(RSASignature.java:84) at java.security.Signature$Delegate.init(Signature.java:1073) at java.security.Signature$Delegate.chooseProvider(Signature.java:1033) at java.security.Signature$Delegate.engineInitSign(Signature.java:1097) at java.security.Signature.initSign(Signature.java:480) at org.jcp.xml.dsig.internal.dom.DOMRSASignatureMethod.sign(DOMRSASignatureMethod.java:162) at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(DOMXMLSignature.java:367) java.security.InvalidKeyException: Private keys must be instance of RSAPrivate(Crt)Key or have PKCS#8 encoding at sun.security.rsa.RSAKeyFactory.translatePrivateKey(RSAKeyFactory.java:246) at sun.security.rsa.RSAKeyFactory.engineTranslateKey(RSAKeyFactory.java:149) at sun.security.rsa.RSAKeyFactory.toRSAKey(RSAKeyFactory.java:79) at sun.security.rsa.RSASignature.engineInitSign(RSASignature.java:90) at sun.security.rsa.RSASignature.engineInitSign(RSASignature.java:84) at java.security.Signature$Delegate.init(Signature.java:1073) at java.security.Signature$Delegate.chooseProvider(Signature.java:1033) at java.security.Signature$Delegate.engineInitSign(Signature.java:1097) at java.security.Signature.initSign(Signature.java:480) at org.jcp.xml.dsig.internal.dom.DOMRSASignatureMethod.sign(DOMRSASignatureMethod.java:162) at org.jcp.xml.dsig.internal.dom.DOMXMLSignature.sign(DOMXMLSignature.java:367)
BTW: I hacked the source in order to make it work... if (signature == null) { /* @HACK BEGIN */ /* * Use a specific provider to perform * signature */ java.security.Provider p = (java.security.Provider)System.getProperties ().get ("org.jcp.xml.dsig.internal.dom.signprovider"); try { // FIXME: do other hashes besides sha-1 if (p == null) { signature = Signature.getInstance("SHA1withRSA"); } else { signature = Signature.getInstance("SHA1withRSA", p); } } catch (NoSuchAlgorithmException nsae) { throw new InvalidKeyException("SHA1withRSA Signature not found"); } /* @HACK END */ }
Please read the bug report at http://issues.apache.org/bugzilla/show_bug.cgi?id=40826 A similar problem has come up before and it can be caused by using a PrivateKey from a PKCS#11 provider instance that is passed to the KeyStore API or by manipulating the providers using the Provider API. In particular, when you get your PrivateKey from the PKCS11 KeyStore, make sure you do not specify a specific provider, instead just do the following: KeyStore.getInstance("PKCS11");
Fixed. In order to use a specific provider, you must pass the Provider object as a property to the XMLSignContext or XMLValidateContex, ex: signContext.setProperty ("org.jcp.xml.dsig.internal.dom.SignatureProvider", new MyProvider());