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();
}
}