XML签名验证在某些消息中失败而在其他消息上传递

问题描述 投票:2回答:1

我有一个Java应用程序,可以通过.NET服务器进行签入以获取许可。许可服务器以签名的xml响应。对于某些消息,Java应用程序无法验证签名,但是对于其他消息,它可以正常工作。

这里是一条可以毫无问题地验证的消息(格式化并替换了敏感数据):

<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>

这里是验证失败的消息(格式化):

<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>

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

Java中的验证码(jboss为假):

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

任何想法为何对某些消息都无法正常签名而对其他消息却失败?我尝试对文档进行不同的编码,并发送第二个消息而不带';角色,行为无差异。

编辑:我还尝试以几种不同的方式构建服务器返回的HttpContent,以防在构建StringContent时某些空白格式发生更改。

java c# rsa digital-signature xml-signature
1个回答
0
投票

在签名后从消息节点中删除了一些白色的新行。我不太清楚为什么,所以我只是在没有新行的情况下构建消息。

© www.soinside.com 2019 - 2024. All rights reserved.