1

I have 2 portions of XML data which I have to canonize and create a digest:

<header authenticate="true">
        <static>
            <HostID>MMM</HostID>
            <TransactionID>98B230CF5FB220FD75FE916949378C2F</TransactionID>
        </static>
        <mutable>
            <TransactionPhase>Receipt</TransactionPhase>
        </mutable>
    </header>

and

<TransferReceipt authenticate="true">
            <ReceiptCode>0</ReceiptCode>
        </TransferReceipt>

If I just concatenate both strings and send them as byte[] to the canonnizer I get an exception:

org.xml.sax.SAXParseException; lineNumber: 9; columnNumber: 15; Markup im Dokument nach dem Root-Element muss ordnungsgemõ▀ formatiert sein.
        at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:257)
        at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:338)
        at org.apache.xml.security.c14n.Canonicalizer.canonicalize(Unknown Source)
        at de.martinm.tools.Utils.DSTools.canonize_data(DSTools.java:141)
        at de.martinm.tools.Utils.DSTools.getDigest(DSTools.java:244)
        at de.martinm.tools.EBICS.EBICSKernel.send_ack(EBICSKernel.java:1039)
        at de.martinm.tools.EBICS.EBICSKernel.process(EBICSKernel.java:1135)
        at de.martinm.tools.EBICS.EBICSKernel.main(EBICSKernel.java:1145)

How do have to concatenate the data so that it can be canonized and after sending over the internet, the receiver can validate the digest?

I know, that the data is not xml valid as it has no single root element.

I cannot find a description how the data has to be formated.

Here is the code:

public byte[] getDigest(byte[] data) {


        byte[] hash = null;
        String algorithm="SHA-256";

        try {           
            MessageDigest digest = MessageDigest.getInstance(algorithm);
            byte[] canonical_data = canonize_data(data);
            hash = digest.digest(canonical_data);
            logger.debug("hash created: {}", Hex.encodeHexString(hash));
        } catch (NoSuchAlgorithmException e) {
            logger.error(algorithm, e);
        };
        return hash;
    }

    public byte[] canonize_data(byte[] data) {

        byte[] canonical_data=null;

        try {
            Canonicalizer c14n = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS);
            canonical_data = c14n.canonicalize(data);
        } catch (InvalidCanonicalizerException | CanonicalizationException | ParserConfigurationException | IOException | SAXException e) {
            logger.error(Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS, e);
        }
        logger.debug("data canonized");
        return canonical_data;      
    }
Martin Müller
  • 122
  • 3
  • 17
  • If you just concatenate the files, you have two root elements which is not allowed in XML. You'll need to wrap another one around them or combine them somehow. – daniu Dec 20 '17 at 14:48

2 Answers2

2

A well-formed XML document has exactly one root element, which serves as the ancestor of all other elements and all text nodes. The result of simply concatenating two well-formed XML documents therefore is not itself a well-formed XML document. It has no root element (or it has two, depending on how you want to look at it).

You should be able to do what you describe by synthesizing a container element to serve as the root and hold the contents of the original two. At least, you can obtain a well-formed combined document that way.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
-1

The trick is, you have to canonize each snippet separately and then concat the received bytes to a new byte array

Martin Müller
  • 122
  • 3
  • 17
  • No, there is no *XML data without a root element,* so full stop until you fix that problem. See [**@JohnBollinger's answer**](https://stackoverflow.com/a/47908679/290085) for the correct answer. – kjhughes Dec 20 '17 at 16:54