1

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>
user1974566
  • 210
  • 2
  • 14
  • Do you mean the certificate for signing or encryption? Where/how do you "loose it"? Isn't it returned in the XML? Is verifying not succeeding? I've tried to get rid of the spurious namespace declarations in the past as well. I don't know what I did in the end, but I did know that it was kinda hopeless. I'd suggest you leave them in unless you have a *very* strong need to get rid of them. – Maarten Bodewes Jun 30 '17 at 10:43
  • I added expected result in the issue. I mean certificate for signing -> But RSA encryption is made using public key that I extract from certificate. "Loose it" -> In part "Current output" I provided my current xml which I get after encryption-> as you can see there isn't any information about digital signature there. But I signing this xml before encryption -> It is shown in first example. I'm sorry for my extreme lack of knowledge in this matter... – user1974566 Jul 03 '17 at 07:16

1 Answers1

1

I manage to correctly sing and encrypt xml file. Answer for future reference.

The problem was in the adding information to KeyInfo during encryption. During signing of xml file information about certificate was correctly added. But during encryption that information was also encrypted. The solution was to add certificate data once more to the KeyInfo.

EncryptedData encryptedDataElement =
        xmlCipher.getEncryptedData();
KeyInfo keyInfo = new KeyInfo(document);
X509Data x509data = new org.apache.xml.security.keys.content.X509Data(document);
x509data.addCertificate(cert);
keyInfo.add(x509data);
keyInfo.add(encKey);

encryptedDataElement.setKeyInfo(keyInfo);

// do the actual encryption
xmlCipher.doFinal(document,
        rootElement, true);
user1974566
  • 210
  • 2
  • 14