如何使用<x509certificate>(不是证书文件)验证C#中XML文件的签名?</x509certificate>

时间:2014-12-17 15:06:34

标签: c# xml validation xml-signature xml-dsig

我正在为政府计费系统制作一些代码,经过几周的阅读后,我达到了死胡同。

我需要验证从服务器收到的xml文件中的至少两个签名,我已经根据公共MSDN制作了一些代码,以便在我使用cert文件或x509store进行签名时验证签名,并且可以正常工作很好,我可以毫无困难地根据他们的参考签署并验证每个签名。

但是,当我收到文件时我不知道如何验证它,因为我没有证书文件,我当然知道里面有标签,如果我得到那个值并把它放在openssl.exe上我可以验证签名者的身份,但是如何检查签名是否正确

http://puu.sh/dypRH/c45e200202.png

过去我用过

if (signedXml.CheckSignature(cert, true))

现在我试试     signedXml.CheckSignature())

每次都失败,我无法参考选择哪个签名,所以我为

做了一个
                foreach (XmlNode node1 in nodeList)
            {
                    testt = node1.OuterXml;
                     testt = testt.Replace(Environment.NewLine, string.Empty);
                    ttt.PreserveWhitespace = true;     
                    ttt.LoadXml(testt);

                    testt = testt.Replace(Environment.NewLine, string.Empty);
                   signedXml.LoadXml(ttt.DocumentElement);
                    //if (signedXml.CheckSignature(cert, true))
                    if (signedXml.CheckSignature())
                    {
                        Console.WriteLine("The XML signature is valid.");
                    }
                    else
                    {
                        Console.WriteLine("The XML signature is not valid.");
                    }


            #endregion
        }

但他们仍然失败

我还根据xml文件制作了证书

X509Certificate c = X509Certificate.CreateFromSignedFile("test.xml");
theCertificate = new X509Certificate2(c);

验证,但也失败

我真的不知道现在该做什么,我有点绝望,这里是xml文件

http://puu.sh/dyqcv/356dd289ae.xml

我需要验证签名,在此之后我必须制作一个响应文件并将其发送回服务器(它已准备就绪,但因为我无法验证签名,我不想出去)

哦,是的,我已经删除了名称空间,并在签名检查/计算之前将所有内容化为

    public static XElement RemoveAllNamespaces(XElement e)
    {
        return new XElement(e.Name.LocalName,
           (from n in e.Nodes()
            select ((n is XElement) ? RemoveAllNamespaces(n as XElement) : n)),
           (e.HasAttributes) ? (from a in e.Attributes()
                                where (!a.IsNamespaceDeclaration)
                                select new XAttribute(a.Name.LocalName, a.Value)) : null);
    }

我会非常感激各种帮助,即使是一个小指针,我应该在哪里尝试它会有所帮助。

哦,对不起,但我真的检查了所有的网站,我希望这个问题不会重复,上次我真的被淘汰了,失去了我的所有代表:(

但我有足够的动力再次提问

https://stackoverflow.com/questions/27158035/replace-string-with-another-string-does-not-work

我忍受了这个哈哈

问候!

编辑:按照user409104的要求,这是整个文件的签名值(三分之一),它也包括了签名节点和keyinfo值

<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="#SetDoc">
<Transforms>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>pIQ3XhBvaULXo7vPOktydkK+c3g=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>
n/bgCyPOI01quzrpt0OLRUbBnUd5vzjyv44S/3Oow56fS/DEtBF+83g1I4WXsw13h81rFhiApgku
tffdWuu23ox3ubGtuAVihK1xaOYBqim8dIBoLBN84M6P3H2+NDi4x01/c+4w7wtNCGedGNrjguwQ
0b864BTj0iavTpu0urUicWipsmxCv9p6JlkyVxmUdlgEvP5pPlv43qHopWvUDrYhXP9m45ap4ubg
47Zwpa7QCadghf4vEYUQOcrGcf4oDYa7KUc71VKTY8cAgmdTool8ugYD2ipNV75R5i3Cfbe8Jsyt
q9wy8iuo2Xc3FpUShojyr3JMl7meJupnmT4qGg==
</SignatureValue>
<KeyInfo>
<KeyValue>
<RSAKeyValue>
<Modulus>
xUg5RWGM6yKTu1hctQ0J9VZtr6+7VOQ75lDq7MeqxDTJgkHxO+P49GV/hRjLv3rCXvo9JBM8AKj5
U+/uue5OE6PgeqdS+M7HBF4ieD33wVsRYWuu2TLrw+/DRd6yEs61mPVRLDrIqjxxpa41VUAfwPXV
ksCZ7RNklyfSa5D+Zm6sx3v5kGPylWVpdW+k3BFYmUCW2j1rjGb5X9zV9Egi2VGe2SGsYLNu1aJS
HHAIPc+COJIBMENga/syQSNF2l4/GNUkn84RnlW5P75rPg6Oa+y2UwfUgmgrCeMcyJJKDMy6heqm
6huvgaxOTr9DZqWkxJYW5GGWTUUiq64JB3EjOQ==
</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</KeyValue>
<X509Data>
<X509Certificate>
MIIElTCCA32gAwIBAgIBLjANBgkqhkiG9w0BAQUFADCBpTEUMBIGA1UEAxMLU0lJLUNBLTIwMTMx
GjAYBgNVBAcTEVNhbnRpYWdvIGRlIENoaWxlMR0wGwYDVQQIExRSZWdpb24gTWV0cm9wb2xpdGFu
YTELMAkGA1UEBhMCQ0wxHDAaBgkqhkiG9w0BCQEWDXNpaS1jYUBzaWkuY2wxJzAlBgNVBAoTHlNl
cnZpY2lvIGRlIEltcHVlc3RvcyBJbnRlcm5vczAeFw0xMzA0MjQxMDM0NDJaFw0xNTA0MjQxMDM0
NDJaMIIBATE6MDgGA1UECxMxRGVwdG8uIGRlIEF0ZW5jaW9uIHkgQXNpc3RlbmNpYSBkZSBDb250
cmlidXllbnRlczEnMCUGA1UEChMeU2VydmljaW8gZGUgSW1wdWVzdG9zIEludGVybm9zMQswCQYD
VQQGEwJDTDEdMBsGA1UECBMUUmVnaW9uIE1ldHJvcG9saXRhbmExGjAYBgNVBAcTEVNhbnRpYWdv
IGRlIENoaWxlMSYwJAYJKoZIhvcNAQkBFhdTSUlfZHRlX2ltcHJlc29zQHNpaS5jbDEqMCgGA1UE
AxMhQ2VydGlmaWNhY2lvbiAgQ0NNICBEZXNhcnJvbGxhZG9yMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAxUg5RWGM6yKTu1hctQ0J9VZtr6+7VOQ75lDq7MeqxDTJgkHxO+P49GV/hRjL
v3rCXvo9JBM8AKj5U+/uue5OE6PgeqdS+M7HBF4ieD33wVsRYWuu2TLrw+/DRd6yEs61mPVRLDrI
qjxxpa41VUAfwPXVksCZ7RNklyfSa5D+Zm6sx3v5kGPylWVpdW+k3BFYmUCW2j1rjGb5X9zV9Egi
2VGe2SGsYLNu1aJSHHAIPc+COJIBMENga/syQSNF2l4/GNUkn84RnlW5P75rPg6Oa+y2UwfUgmgr
CeMcyJJKDMy6heqm6huvgaxOTr9DZqWkxJYW5GGWTUUiq64JB3EjOQIDAQABo3EwbzAJBgNVHRME
AjAAMD0GA1UdEQQ2MDSgGAYIKwYBBAHBAQGgDBMKNDUwMDAwNTItM6AYBggrBgEEAcEBA6AMEwo2
MDgwMzAwMC1LMCMGA1UdEgQcMBqgGAYIKwYBBAHBAQKgDBMKNjA4MDMwMDAtSzANBgkqhkiG9w0B
AQUFAAOCAQEAWbf4jOaJgvx4676oKqHoHlO5/y/8umb2eCjddVKWxrytL4Ncx/6aJSgmMBj52Whe
gHJf3+SCarDYgo2L7AzaIL7/nM1KtlKpcpqFU+LC+AFf4MctSe8nthdg7VaKze1f5W2ZKvVBDNwI
1LFrbBEn6w3PlkcJ0AjvlJBEgPlMzQVEKSEGdPOTbsiWvSxdxj8HuFFKx3R+bH9ZkNjP5s06nTFh
SFVVIYZvCQ/qIYyUCBe4ZvH02ekYK8KeO6suiDI8cctoC+DWGfSvcLEt07AuwuVbqzAde32ACnC2
lqqstjt3FuB3nYymxbrnzhJjpPkTt9m9MbSFvJzrAgQ7joO1Dw==
</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>

我已经使这个基于xml文件创建了密钥,但是我无法选择要选择哪个,我猜它使用的是第一个找到的,(但xml中有3个)也还是不知道如何使用它来验证。

我不能用RSAKeyValue制作x509certificate / 2吗?

XmlElement XmlSignature;
XmlSignature = (XmlElement)fix2.DocumentElement.SelectSingleNode("//Signature");
RSAKeyValue key = new RSAKeyValue();
key.LoadXml(XmlSignature);

1 个答案:

答案 0 :(得分:6)

这足以让您找到解决方案。下面的代码将验证xml文档中最外层Signature元素的签名。

我认为它不会验证内部签名块的原因是它们被外部签名块包装,你需要为每个包含的元素创建单独的XmlDocument实例,并为每个元素分别执行相同的步骤那些节点。

在下面的代码中,'pass'将在第三次迭代时成立。

您希望在解决方案中执行的操作是通过xpath获取外部Signature节点并仅验证该节点,然后为文档中的每个节点创建新的XmlDocument实例,并对每个节点执行单独的证书验证。

        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.PreserveWhitespace = true;
        xmlDoc.Load("ENVIO_DTE_345508.xml");
        SignedXml signedXml = new SignedXml(xmlDoc);
        XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");
        XmlNodeList certificates = xmlDoc.GetElementsByTagName("X509Certificate");
        X509Certificate2 dcert2 = new X509Certificate2(Convert.FromBase64String(certificates[0].InnerText));
        foreach (XmlElement element in nodeList) {
            signedXml.LoadXml(element);
            bool passes = signedXml.CheckSignature(dcert2, true);
        }