I'm using Java Security and Javax XML Crypto for X509 certificate signing. It's working pretty well and after using XMLSignature sign
XMLSignature signature = xmlsignaturefactory.newXMLSignature(signedinfo, keyinfo);
signature.sign(domsigncontext);
my xml file is correctly signed and have format like this:
<?xml version="1.0" encoding="UTF-8"?>
<bxd:ApplicationRequest xmlns:bxd="http://bxd.fi/xmldata/">
<bxd:CustomerId>zzz</bxd:CustomerId>
<bxd:Command>UploadFile</bxd:Command>
<bxd:Timestamp>2011-11-17T09:30:47Z</bxd:Timestamp>
<bxd:Environment>TEST</bxd:Environment>
<bxd:Encryption>true</bxd:Encryption>
<bxd:Compression>true</bxd:Compression>
<bxd:CompressionMethod>gzip</bxd:CompressionMethod>
<bxd:SoftwareId>CustomerSoftwareId</bxd:SoftwareId>
<bxd:FileType>pain.001.001.02</bxd:FileType>
<bxd:Content>testtesttest</bxd:Content>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>AdsaH3fjwrbbcYxX3Nv5few+eFyEuTww=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>valuehere</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>certificatehere</X509Certificate>
<X509IssuerSerial>
<X509IssuerName>CN=test,OU=Unknown,O=Unknown,L=Unknown,ST=Unknown,C=Unknown</X509IssuerName>
<X509SerialNumber>2312434323</X509SerialNumber>
</X509IssuerSerial>
</X509Data>
</KeyInfo>
</Signature>
</bxd:ApplicationRequest>
After that, I'm encrypting this with 3DES using generated key, and after that, I'm encrypting this key using RSA 1.5 and public key from the certificate. I'm using Apache Santuario for this. MY problem is that I'm losing certificate info after encryption. Additionally, to each tag there is
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
namespace added which I don't want besides one place here ->
<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
Type="http://www.w3.org/2001/04/xmlenc#Element">
Current output:
<?xml version="1.0" encoding="UTF-8"?>
<bxd:ApplicationRequest xmlns:bxd="http://bxd.fi/xmldata/">
<xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Content" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"/>
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"/>
<xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:CipherValue xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">ciphervalueone</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedKey>
</ds:KeyInfo>
<xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:CipherValue xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">cipherval</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</bxd:ApplicationRequest>
Code that is handling encryption:
public class Encryption
{
static
{
org.apache.xml.security.Init.init();
}
public static EncryptedKey encryptKey(Document document, SecretKey keyToBeEncrypted, PublicKey keyUsedToEncryptSecretKey) throws org.apache.xml.security.encryption.XMLEncryptionException {
XMLCipher keyCipher = null;
String pubKeyAlg = keyUsedToEncryptSecretKey.getAlgorithm();
try {
String keyWrapAlgo = XMLCipher.RSA_v1dot5;
keyCipher = XMLCipher.getInstance(keyWrapAlgo);
keyCipher.init(XMLCipher.WRAP_MODE, keyUsedToEncryptSecretKey);
//return keyCipher.encryptKey(document, keyToBeEncrypted);
} catch (Exception e) {
e.printStackTrace();
}
return keyCipher.encryptKey(document, keyToBeEncrypted);
}
private static SecretKey GenerateSymmetricKey()
throws Exception
{
String jceAlgorithmName = "DESede";
KeyGenerator keyGenerator =
KeyGenerator.getInstance(jceAlgorithmName);
return keyGenerator.generateKey();
}
public static Document EncryptDocument(Document document, String elementToEncode, KeyPair pair)
throws Exception
{
// generate symmetric key
SecretKey symmetricKey = GenerateSymmetricKey();
EncryptedKey encKey = encryptKey(document,symmetricKey, pair.getPublic());
Element rootElement = document.getDocumentElement();
Element elementToEncrypt = rootElement;
XMLCipher xmlCipher =
XMLCipher.getInstance(XMLCipher.TRIPLEDES);
xmlCipher.init(XMLCipher.ENCRYPT_MODE, symmetricKey);
// add key info to encrypted data element
EncryptedData encryptedDataElement =
xmlCipher.getEncryptedData();
KeyInfo keyInfo = new KeyInfo(document);
keyInfo.add(encKey);
encryptedDataElement.setKeyInfo(keyInfo);
// do the actual encryption
//boolean encryptContentsOnly = false;
xmlCipher.doFinal(document,
elementToEncrypt, true);
// write the results to a file
return document;
}
}
Expected result:
<xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
<dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
<xenc:EncryptedKey>
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
<dsig:KeyInfo>
<dsig:X509Data>
<dsig:X509Certificate>DigitalSignatureOfCertificateHere</dsig:X509Certificate>
</dsig:X509Data>
</dsig:KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>CipherValueofEncryptedKeyHere</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedKey>
</dsig:KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>CipherValueOfProvidedXMLHere</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>