You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@santuario.apache.org by Peter Hendry <pe...@capeclear.com> on 2007/01/10 21:55:38 UTC

Issue moving from JDK 1.4 to 1.5

The class attached contains test code that works Ok under JDK 1.4 but 
has never worked under 1.5. The scenario is where the secret key is to 
be included with the message and encrypted using a public key then 
decrypted by the recipient using their private key. When the key is 
decrypted an instance of SecretKeySpec is returned with its algorithm 
set to RSA (the original key is DESEde). This happens on both 1.4 and 
1.5 but it only fails to decrypt the data in 1.5.

Any help/pointers appreciated.

Pete




Re: Issue moving from JDK 1.4 to 1.5

Posted by Vishal Mahajan <vm...@amberpoint.com>.
You can use the one argument version of the decryptKey method. There you 
don't need to specify the algorithm, it's determined automatically from 
the EncryptedData element.

Vishal

Peter Hendry wrote:
> Thanks for the response. Changing to
>
>     final SecretKey unwrappedKey = 
> (SecretKey)cipher.decryptKey(encryptedKey, XMLCipher.TRIPLEDES);
> does make it work! This leads onto the issue of how the receiver knows the symmetric key algorithm? This information is not transmitted in the EncryptedKey. The code I am seeing this problem in is for WS-Security and there is no indication in the EncryptedKey sent (example below) of this algorithm. Does it have to be supplied out of band?
>
>   <xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
>     <xenc:EncryptionMethod
>         xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
>         Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
>     <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
>       <xenc:CipherValue xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">op+6IqOzXDvnnRJnibidFEre1nC5km6+1vkzM7mD4yR9r
> nVYFo3SWq6t8r3s0jJj9HR6J4y4EQHW
> ay7Qhat8gMd8q9L9YStf5lNroSC3Co1HNOWokJ7aL759a0ifN3fT5djYIEVwzwwgpZHtsJjz+j99
> Ot+s+Tk6Kfhd5oe+I9Q=</xenc:CipherValue>
>     </xenc:CipherData>
>     <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
>       <wsse:SecurityTokenReference
>           xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
>           wsu:Id="id19351067"
>           xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
>         <wsse:KeyIdentifier
>             EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
>             ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier">
> Xeg55vRyK3ZhAEhEf+YT0z986L0=</wsse:KeyIdentifier>
>       </wsse:SecurityTokenReference>
>     </ds:KeyInfo>
>     <xenc:ReferenceList>
>       <xenc:DataReference URI="#id16134229"/>
>     </xenc:ReferenceList>
>   </xenc:EncryptedKey> 
>
> Pete
>   
>
> Vishal Mahajan wrote:
>> Problem seems to be in this line:
>>
>> final SecretKey unwrappedKey = (SecretKey)cipher.decryptKey(encryptedKey, XMLCipher.RSA_v1dot5);
>>
>> The second parameter to decryptKey method needs to be the symmetric 
>> key algorithm.
>>
>> Vishal
>>
>> Peter Hendry wrote:
>>> Sorry, I forgot the error produced in JDK 1.5
>>>
>>> Original Exception was java.security.InvalidKeyException: Wrong 
>>> algorithm: DESede or TripleDES required
>>>     at 
>>> org.apache.xml.security.encryption.XMLCipher.decryptToByteArray(Unknown 
>>> Source)
>>>     at 
>>> org.apache.xml.security.encryption.XMLCipher.decryptElement(Unknown 
>>> Source)
>>>     at org.apache.xml.security.encryption.XMLCipher.doFinal(Unknown 
>>> Source)
>>>     at 
>>> com.capeclear.pgh.stuff.SecurityKeyTests.main(SecurityKeyTests.java:98)
>>>     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>>     at 
>>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>>>     at 
>>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>>>     at java.lang.reflect.Method.invoke(Method.java:585)
>>>     at 
>>> com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)
>>> java.security.InvalidKeyException: Wrong algorithm: DESede or 
>>> TripleDES required
>>>     at com.sun.crypto.provider.SunJCE_aa.a(DashoA12275)
>>>     at com.sun.crypto.provider.SunJCE_m.a(DashoA12275)
>>>     at com.sun.crypto.provider.SunJCE_h.a(DashoA12275)
>>>     at com.sun.crypto.provider.DESedeCipher.engineInit(DashoA12275)
>>>     at javax.crypto.Cipher.init(DashoA12275)
>>>     at javax.crypto.Cipher.init(DashoA12275)
>>>     at 
>>> org.apache.xml.security.encryption.XMLCipher.decryptToByteArray(Unknown 
>>> Source)
>>>     at 
>>> org.apache.xml.security.encryption.XMLCipher.decryptElement(Unknown 
>>> Source)
>>>     at org.apache.xml.security.encryption.XMLCipher.doFinal(Unknown 
>>> Source)
>>>     at 
>>> com.capeclear.pgh.stuff.SecurityKeyTests.main(SecurityKeyTests.java:98)
>>>     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>>>     at 
>>> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>>>     at 
>>> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>>>     at java.lang.reflect.Method.invoke(Method.java:585)
>>>     at 
>>> com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)
>>>
>>> Pete
>>>
>>> Peter Hendry wrote:
>>>> The class attached contains test code that works Ok under JDK 1.4 
>>>> but has never worked under 1.5. The scenario is where the secret 
>>>> key is to be included with the message and encrypted using a public 
>>>> key then decrypted by the recipient using their private key. When 
>>>> the key is decrypted an instance of SecretKeySpec is returned with 
>>>> its algorithm set to RSA (the original key is DESEde). This happens 
>>>> on both 1.4 and 1.5 but it only fails to decrypt the data in 1.5.
>>>>
>>>> Any help/pointers appreciated.
>>>>
>>>> Pete
>>>>
>>>>
>>>>
>>>> ------------------------------------------------------------------------
>>>>
>>>> package pgh;
>>>>
>>>> import java.security.KeyPair;
>>>> import java.security.KeyPairGenerator;
>>>> import java.security.Security;
>>>> import java.security.spec.KeySpec;
>>>>
>>>> import javax.crypto.SecretKey;
>>>> import javax.crypto.SecretKeyFactory;
>>>> import javax.crypto.spec.DESedeKeySpec;
>>>> import javax.crypto.spec.SecretKeySpec;
>>>> import javax.xml.parsers.DocumentBuilderFactory;
>>>> import javax.xml.transform.Transformer;
>>>> import javax.xml.transform.TransformerFactory;
>>>> import javax.xml.transform.dom.DOMSource;
>>>> import javax.xml.transform.stream.StreamResult;
>>>>
>>>> import org.apache.xml.security.encryption.EncryptedKey;
>>>> import org.apache.xml.security.encryption.XMLCipher;
>>>> import org.apache.xml.security.transforms.Transforms;
>>>> import org.bouncycastle.jce.provider.BouncyCastleProvider;
>>>> import org.w3c.dom.Document;
>>>> import org.w3c.dom.Element;
>>>> import org.w3c.dom.Node;
>>>>
>>>>
>>>> public class SecurityKeyTests {
>>>>
>>>>     static {
>>>>         Security.addProvider(new BouncyCastleProvider());
>>>>         org.apache.xml.security.Init.init();
>>>>     }
>>>>
>>>>     public static void main( String[] args )
>>>>         throws Exception {
>>>>
>>>>         // the secret key to encrypt/decrypt our data
>>>>         final byte[] keyBytes = { (byte)0xA2, (byte) 0x15,
>>>>             (byte) 0x37, (byte) 0x07, (byte) 0xCB, (byte) 0x62, (byte) 0xC1,
>>>>             (byte) 0xD3, (byte) 0xF8, (byte) 0xF1, (byte) 0x97, (byte) 0xDF,
>>>>             (byte) 0xD0, (byte) 0x13, (byte) 0x4F, (byte) 0x79, (byte) 0x01,
>>>>             (byte) 0x67, (byte) 0x7A, (byte) 0x85, (byte) 0x94, (byte) 0x16,
>>>>             (byte) 0x31, (byte) 0x92 };
>>>>
>>>>         final String dataToEncrypt = "Hello World";
>>>>
>>>>         // use DESEde as the key algorithm
>>>>         final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESEde");
>>>>         final KeySpec spec = new DESedeKeySpec(keyBytes);
>>>>         final SecretKey secretKey = keyFactory.generateSecret(spec);
>>>>
>>>>         // generate key pair for encrypting/decrypting the shared key
>>>>         final KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
>>>>         final KeyPair keyPair = generator.generateKeyPair();
>>>>
>>>>         final Document doc = newDocument();
>>>>
>>>>         // encrypt the secret key with RSA 1.5 and output the EncryptedKey
>>>>         XMLCipher cipher = XMLCipher.getInstance(XMLCipher.RSA_v1dot5);
>>>>         cipher.init(XMLCipher.WRAP_MODE, keyPair.getPublic());
>>>>         final EncryptedKey encryptedKey = cipher.encryptKey(doc, secretKey);
>>>>         final Element encKeyElement = cipher.martial(encryptedKey);
>>>>
>>>>         writeNode("EncryptedKey:", encKeyElement);
>>>>
>>>>         // encode some data with the secret key
>>>>         final Element element = doc.createElement("test");
>>>>         element.appendChild(doc.createTextNode(dataToEncrypt));
>>>>         doc.appendChild(element);
>>>>
>>>>         cipher = XMLCipher.getInstance(XMLCipher.TRIPLEDES, Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
>>>>         cipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
>>>>         cipher.doFinal(doc, element, false);
>>>>
>>>>         final Element encryptedElement = (Element)doc.getDocumentElement();
>>>>         writeNode("\nEncryptedData: ", encryptedElement);
>>>>
>>>>         // get the key back from the EncryptedKey (i.e. don't use the original key)
>>>>         cipher = XMLCipher.getInstance(XMLCipher.RSA_v1dot5);
>>>>         cipher.init(XMLCipher.UNWRAP_MODE, keyPair.getPrivate());
>>>>         final SecretKey unwrappedKey = (SecretKey)cipher.decryptKey(encryptedKey, XMLCipher.RSA_v1dot5);
>>>>
>>>>         if ( unwrappedKey instanceof SecretKeySpec ) {
>>>>             final SecretKeySpec sks = (SecretKeySpec)unwrappedKey;
>>>>             System.out.println("\nUnwrapped Key: algorithm=" + sks.getAlgorithm());
>>>>         }
>>>>         else {
>>>>             System.out.println("\nUnwrapped Key: " + unwrappedKey);
>>>>         }
>>>>
>>>>         // and use it to decrypt the element
>>>>         cipher = XMLCipher.getInstance(XMLCipher.TRIPLEDES, Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
>>>>         cipher.init(XMLCipher.DECRYPT_MODE, unwrappedKey);
>>>>
>>>>         // the error occurs here in JDK1.5 because the unwrapped key is marked as "RSA" but the
>>>>         // decryption algorithm is TripleDES?
>>>>         cipher.doFinal(doc, encryptedElement, false);
>>>>
>>>>         writeNode("\nDecrypted: ", doc);
>>>>     }
>>>>
>>>>
>>>>     private static void writeNode( String msg, Node element )
>>>>         throws Exception {
>>>>
>>>>         System.out.println(msg);
>>>>         final Transformer transformer = TransformerFactory.newInstance().newTransformer();
>>>>         transformer.transform(new DOMSource(element), new StreamResult(System.out));
>>>>     }
>>>>
>>>>
>>>>     private static Document newDocument()
>>>>         throws Exception {
>>>>
>>>>         return DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
>>>>     }
>>>> }
>>>>   
>>


Re: Issue moving from JDK 1.4 to 1.5

Posted by Vishal Mahajan <vm...@amberpoint.com>.
Problem seems to be in this line:

final SecretKey unwrappedKey = (SecretKey)cipher.decryptKey(encryptedKey, XMLCipher.RSA_v1dot5);


The second parameter to decryptKey method needs to be the symmetric key 
algorithm.

Vishal

Peter Hendry wrote:
> Sorry, I forgot the error produced in JDK 1.5
>
> Original Exception was java.security.InvalidKeyException: Wrong 
> algorithm: DESede or TripleDES required
>     at 
> org.apache.xml.security.encryption.XMLCipher.decryptToByteArray(Unknown 
> Source)
>     at 
> org.apache.xml.security.encryption.XMLCipher.decryptElement(Unknown 
> Source)
>     at org.apache.xml.security.encryption.XMLCipher.doFinal(Unknown 
> Source)
>     at 
> com.capeclear.pgh.stuff.SecurityKeyTests.main(SecurityKeyTests.java:98)
>     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>     at 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>     at 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>     at java.lang.reflect.Method.invoke(Method.java:585)
>     at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)
> java.security.InvalidKeyException: Wrong algorithm: DESede or 
> TripleDES required
>     at com.sun.crypto.provider.SunJCE_aa.a(DashoA12275)
>     at com.sun.crypto.provider.SunJCE_m.a(DashoA12275)
>     at com.sun.crypto.provider.SunJCE_h.a(DashoA12275)
>     at com.sun.crypto.provider.DESedeCipher.engineInit(DashoA12275)
>     at javax.crypto.Cipher.init(DashoA12275)
>     at javax.crypto.Cipher.init(DashoA12275)
>     at 
> org.apache.xml.security.encryption.XMLCipher.decryptToByteArray(Unknown 
> Source)
>     at 
> org.apache.xml.security.encryption.XMLCipher.decryptElement(Unknown 
> Source)
>     at org.apache.xml.security.encryption.XMLCipher.doFinal(Unknown 
> Source)
>     at 
> com.capeclear.pgh.stuff.SecurityKeyTests.main(SecurityKeyTests.java:98)
>     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>     at 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>     at 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>     at java.lang.reflect.Method.invoke(Method.java:585)
>     at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)
>
> Pete
>
> Peter Hendry wrote:
>> The class attached contains test code that works Ok under JDK 1.4 but 
>> has never worked under 1.5. The scenario is where the secret key is 
>> to be included with the message and encrypted using a public key then 
>> decrypted by the recipient using their private key. When the key is 
>> decrypted an instance of SecretKeySpec is returned with its algorithm 
>> set to RSA (the original key is DESEde). This happens on both 1.4 and 
>> 1.5 but it only fails to decrypt the data in 1.5.
>>
>> Any help/pointers appreciated.
>>
>> Pete
>>
>>
>>
>> ------------------------------------------------------------------------
>>
>> package pgh;
>>
>> import java.security.KeyPair;
>> import java.security.KeyPairGenerator;
>> import java.security.Security;
>> import java.security.spec.KeySpec;
>>
>> import javax.crypto.SecretKey;
>> import javax.crypto.SecretKeyFactory;
>> import javax.crypto.spec.DESedeKeySpec;
>> import javax.crypto.spec.SecretKeySpec;
>> import javax.xml.parsers.DocumentBuilderFactory;
>> import javax.xml.transform.Transformer;
>> import javax.xml.transform.TransformerFactory;
>> import javax.xml.transform.dom.DOMSource;
>> import javax.xml.transform.stream.StreamResult;
>>
>> import org.apache.xml.security.encryption.EncryptedKey;
>> import org.apache.xml.security.encryption.XMLCipher;
>> import org.apache.xml.security.transforms.Transforms;
>> import org.bouncycastle.jce.provider.BouncyCastleProvider;
>> import org.w3c.dom.Document;
>> import org.w3c.dom.Element;
>> import org.w3c.dom.Node;
>>
>>
>> public class SecurityKeyTests {
>>
>>     static {
>>         Security.addProvider(new BouncyCastleProvider());
>>         org.apache.xml.security.Init.init();
>>     }
>>
>>     public static void main( String[] args )
>>         throws Exception {
>>
>>         // the secret key to encrypt/decrypt our data
>>         final byte[] keyBytes = { (byte)0xA2, (byte) 0x15,
>>             (byte) 0x37, (byte) 0x07, (byte) 0xCB, (byte) 0x62, (byte) 0xC1,
>>             (byte) 0xD3, (byte) 0xF8, (byte) 0xF1, (byte) 0x97, (byte) 0xDF,
>>             (byte) 0xD0, (byte) 0x13, (byte) 0x4F, (byte) 0x79, (byte) 0x01,
>>             (byte) 0x67, (byte) 0x7A, (byte) 0x85, (byte) 0x94, (byte) 0x16,
>>             (byte) 0x31, (byte) 0x92 };
>>
>>         final String dataToEncrypt = "Hello World";
>>
>>         // use DESEde as the key algorithm
>>         final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESEde");
>>         final KeySpec spec = new DESedeKeySpec(keyBytes);
>>         final SecretKey secretKey = keyFactory.generateSecret(spec);
>>
>>         // generate key pair for encrypting/decrypting the shared key
>>         final KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
>>         final KeyPair keyPair = generator.generateKeyPair();
>>
>>         final Document doc = newDocument();
>>
>>         // encrypt the secret key with RSA 1.5 and output the EncryptedKey
>>         XMLCipher cipher = XMLCipher.getInstance(XMLCipher.RSA_v1dot5);
>>         cipher.init(XMLCipher.WRAP_MODE, keyPair.getPublic());
>>         final EncryptedKey encryptedKey = cipher.encryptKey(doc, secretKey);
>>         final Element encKeyElement = cipher.martial(encryptedKey);
>>
>>         writeNode("EncryptedKey:", encKeyElement);
>>
>>         // encode some data with the secret key
>>         final Element element = doc.createElement("test");
>>         element.appendChild(doc.createTextNode(dataToEncrypt));
>>         doc.appendChild(element);
>>
>>         cipher = XMLCipher.getInstance(XMLCipher.TRIPLEDES, Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
>>         cipher.init(XMLCipher.ENCRYPT_MODE, secretKey);
>>         cipher.doFinal(doc, element, false);
>>
>>         final Element encryptedElement = (Element)doc.getDocumentElement();
>>         writeNode("\nEncryptedData: ", encryptedElement);
>>
>>         // get the key back from the EncryptedKey (i.e. don't use the original key)
>>         cipher = XMLCipher.getInstance(XMLCipher.RSA_v1dot5);
>>         cipher.init(XMLCipher.UNWRAP_MODE, keyPair.getPrivate());
>>         final SecretKey unwrappedKey = (SecretKey)cipher.decryptKey(encryptedKey, XMLCipher.RSA_v1dot5);
>>
>>         if ( unwrappedKey instanceof SecretKeySpec ) {
>>             final SecretKeySpec sks = (SecretKeySpec)unwrappedKey;
>>             System.out.println("\nUnwrapped Key: algorithm=" + sks.getAlgorithm());
>>         }
>>         else {
>>             System.out.println("\nUnwrapped Key: " + unwrappedKey);
>>         }
>>
>>         // and use it to decrypt the element
>>         cipher = XMLCipher.getInstance(XMLCipher.TRIPLEDES, Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
>>         cipher.init(XMLCipher.DECRYPT_MODE, unwrappedKey);
>>
>>         // the error occurs here in JDK1.5 because the unwrapped key is marked as "RSA" but the
>>         // decryption algorithm is TripleDES?
>>         cipher.doFinal(doc, encryptedElement, false);
>>
>>         writeNode("\nDecrypted: ", doc);
>>     }
>>
>>
>>     private static void writeNode( String msg, Node element )
>>         throws Exception {
>>
>>         System.out.println(msg);
>>         final Transformer transformer = TransformerFactory.newInstance().newTransformer();
>>         transformer.transform(new DOMSource(element), new StreamResult(System.out));
>>     }
>>
>>
>>     private static Document newDocument()
>>         throws Exception {
>>
>>         return DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
>>     }
>> }
>>