XML Signature validation failing in some messages and passing on others

Viewed 1022

I have a java application that checks in with a .NET server for licensing purposes. The licensing server responds with signed xml. For some messages the Java application fails to validate the signature, but for others it works fine.

Here is a message that is able to be validated with no problem (formatted and replaced sensitive data):

<AuthorizeResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <LicenseKey>replaced actual data</LicenseKey>
    <Message i:nil="true" />
    <MessageGuid>67d5b7bd-33bd-467b-a3fc-842f0f4782e3</MessageGuid>
    <Nonce>0</Nonce>
    <Success>true</Success>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
            <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
            <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" />
                </Transforms>
                <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                <DigestValue>QQL4nxJbna/VUR/b3caorWjHb0Q=</DigestValue>
            </Reference>
        </SignedInfo>
        <SignatureValue>
            nui/m6DvMBbKjncklq1/1Bo4Bzq8C1Z+dhL0c3YMM2wDdDMhC7ob201r3XnDijFcuhz8BomNbE2Br51Y9+R1wPq2JuQ0K8037f7WmQW5M1l+5Dvz9bFrK1oKExKudg9iRNv0iYcgMxY6x0m3tyQTC6KnH/uBtALbQeNLTti+ho4=
        </SignatureValue>
    </Signature>
</AuthorizeResponse>

Here is a message where validation fails (formatted):

<AuthorizeResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <LicenseKey i:nil="true" />
    <Message>Already using license on max number of systems. Running on
        systems:127.0.0.1;192.168.1.8;host.docker.internal;1127.0.0.1;192.168.1.8;host.docker.internal;2</Message>
    <MessageGuid>7f5d0e32-6117-4204-85e1-dec5c57c053e</MessageGuid>
    <Nonce>0</Nonce>
    <Success>false</Success>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
            <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
            <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" />
                </Transforms>
                <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                <DigestValue>JJ81DxbusvrVSCZUy/3nobs71FU=</DigestValue>
            </Reference>
        </SignedInfo>
        <SignatureValue>
            aYhs9Vri70bSqsRcVyE8HpQgs0KIQQfmTgJiIv2QzP4Aa172T5ntiii0EU4CJn28N3tXSJK4wmbxZBOvZGnyYuBOv/5jWEFyeUuNAwmw/r+HdVKctBD0BRmSSq+fqQpMjlJmyT/3RL1S250KhCFB05NhvSxk0IbZUei/4RpWwcc=
        </SignatureValue>
    </Signature>
</AuthorizeResponse>

Signing code in C#:

        public static void SignXmlDocument(string privateKey, XmlDocument xmlDoc)
        {
            SignedXml signedXml = new SignedXml(xmlDoc);

            RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider();
            rsaKey.FromXmlString(privateKey);
            signedXml.SigningKey = rsaKey;

            Reference reference = new Reference {Uri = ""};
            XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
            reference.AddTransform(env);
            signedXml.AddReference(reference);
            signedXml.ComputeSignature();
            XmlElement xmlDigitalSignature = signedXml.GetXml();
            // ReSharper disable once PossibleNullReferenceException
            xmlDoc.DocumentElement.AppendChild(xmlDoc.ImportNode(xmlDigitalSignature, true));
        }

Validation code in Java (jboss is false):

    private static boolean verifyXmlFromStream(InputStream SignedXmlDocumentStream, boolean jboss)
    {
        try
        {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            Document sourceDoc = dbf.newDocumentBuilder().parse(SignedXmlDocumentStream);

            NodeList nl = sourceDoc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
            if (nl.getLength() == 0)
                throw new Exception("Cannot find Signature element");

            XMLSignatureFactory factory = getSignatureFactory(jboss);
            DOMValidateContext valContext = new DOMValidateContext(new KeyValueKeySelector(), nl.item(0));
            XMLSignature signature = factory.unmarshalXMLSignature(valContext);
            boolean coreValidity = signature.validate(valContext);

            if (!coreValidity)
                log.warn("Signature failed core validation!"); // error?
            return coreValidity;
        }
        catch (Exception e)
        {
            log.error(e);
            return false;
        }
    }

    private static XMLSignatureFactory getSignatureFactory(boolean jboss)
        throws ClassNotFoundException,
               InstantiationException,
               IllegalAccessException
    {
        if (jboss)
        {
            log.debug("Getting XML security provider using JBoss friendly method.");
            return XMLSignatureFactory.getInstance("DOM");
        }
        else
        {
            String provider = System.getProperty("jsr105Provider",
                    "org.jcp.xml.dsig.internal.dom.XMLDSigRI");
            return XMLSignatureFactory.getInstance("DOM",
                    (Provider)Class.forName(provider).newInstance());
        }
    }

Any idea why signing is working correctly for some messages and failing with others? I've tried encoding the document differently and sending the second message without the ';' character with no difference in behavior.

Edit: I've also tried building the HttpContent returned by my server in several different ways in case some white space formatting was changing when I built my StringContent.

1 Answers

Somehow white new lines were being removed from the message node after signing. I'm not quite sure why, so I'm just building the message without the new lines.

Related