C# 如何验证数字签名的XML文件?

C# 如何验证数字签名的XML文件?,c#,xml,hash,digital-signature,C#,Xml,Hash,Digital Signature,您好,我对数字签名非常陌生。我正在验证数字签名的XML文件,并使用以下代码对其进行了验证。但我想知道它是如何验证XML是否正确或被篡改的。看完一些文章后,我发现 1.为XML创建哈希。(不包括签名部分) 2.使用公钥解密签名(您将获得一个哈希值) 3.比较两个哈希值。(如果两个散列都匹配,则XML不会被篡改)。 我的理解是对的 这是我的XML的签名部分 <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> <Sig

您好,我对数字签名非常陌生。我正在验证数字签名的XML文件,并使用以下代码对其进行了验证。但我想知道它是如何验证XML是否正确或被篡改的。看完一些文章后,我发现 1.为XML创建哈希。(不包括签名部分) 2.使用公钥解密签名(您将获得一个哈希值) 3.比较两个哈希值。(如果两个散列都匹配,则XML不会被篡改)。 我的理解是对的

这是我的XML的签名部分

<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>u+1NVN5c3gbaxmIrkO9SzVQDklA=</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>QtQJjevrggzsFZj7PqD3p7GaWkzJAfyacjbMgMXgszCuO+Pxe2rrkScqvgGt2DJqgVlTbC/m9gnodCu7BcXSmW459mSJtyGH+ekWwj6g9ej8I7IYWCRqbI5uus3r3+vr/8ECd5CP/khu/LcCMyPuNIxA8h2EywCeQgbXBvLiWcdexBazdKQQpFxlKw0i+oTs8Ou6jViOdX1ZmTRtdKCQXzAElvpyNimQSmO9OECEs/TytjzIG98mpldfdofoq/2JC+xQhs6IF+Ctw/zlJdkgj1U18U/00Cw4puT4oScTELNSihSS+i9gAL+YjZLlIeunACbnZ4B1CVL/uS9kLlutXQ==</SignatureValue>
    <KeyInfo>
      <KeyValue>
        <RSAKeyValue>
          <Modulus>kHORMZQYOifL5UdIhKe54SfvJKyzLL5Aaw9MgpzeQPgBMmD9KMRnkeU+5RYMiUW8GT3q4eW77UihyxSX3MTAHzuqXoc6GjkBO1Tr41isud721SG7iMspw829YZKAHAPDAl0BV5gpLZagH8KXrDp4dVU+XDOOLZZZWZnbpKSFKvLaJO34KphZ/9W3L/l1BOwEs7132svmtwGgPO2Y16C90sDRWp78ZCYYhb7fAez7683+fijZCDGuVTvS0lBKhmH0ETiNfBAiELUUwHvQ5GHOFSp5PA8+hV9F7zxno1a0/OBpRsHfLydm3THyMUS7DlPE46zPiO9rRIUe90aQ64ulYQ==</Modulus>
          <Exponent>AQAB</Exponent>
        </RSAKeyValue>
      </KeyValue>
    </KeyInfo>
  </Signature>

u+1NVN5c3gbaxmIrkO9SzVQDklA=
4.中文意思是一个GvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvqvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvLIEUNACBNZ4B1CVL/uS9kLlutXQ==
2.在未来4年,我们将在未来4年,在未来10年,在未来4年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来10年,在未来64ulyq==
AQAB
以及如何验证XML:

private void btnVerifySign_Click(object sender, EventArgs e)
        {
string  LModulus = node.SelectSingleNode("//Signature/KeyInfo/KeyValue/RSAKeyValue/Modulus").InnerText.ToString();
                string LExponent = node.SelectSingleNode("//Signature/KeyInfo/KeyValue/RSAKeyValue/Exponent").InnerText.ToString();
using (var rsa = new RSACryptoServiceProvider())
                {
var rsaParam = new RSAParameters()
                    {
Modulus = Convert.FromBase64String(LModulus),
                        Exponent = Convert.FromBase64String(LExponent)
                    };
rsa.ImportParameters(rsaParam);
bool result = VerifyXml(newxml1, rsa);
}

public static Boolean VerifyXml(XmlDocument Doc, RSA Key)
        {
            // Check arguments. 
            if (Doc == null)
                throw new ArgumentException("Doc");
            if (Key == null)
                throw new ArgumentException("Key");

            // Create a new SignedXml object and pass it 
            // the XML document class.
            SignedXml signedXml = new SignedXml(Doc);

            // Find the "Signature" node and create a new 
            // XmlNodeList object.
            XmlNodeList nodeList = Doc.GetElementsByTagName("Signature");

            // Throw an exception if no signature was found. 
            if (nodeList.Count <= 0)
            {
                // throw new CryptographicException("Verification failed: No Signature was found in the document.");
                MessageBox.Show("Verification failed: No Signature was found in the document.");
            }

            // This example only supports one signature for 
            // the entire XML document.  Throw an exception  
            // if more than one signature was found. 
            if (nodeList.Count > 1)
            {
                MessageBox.Show("Verification failed: More that one signature was found for the document.");
                // throw new CryptographicException("Verification failed: More that one signature was found for the document.");
            }

            // Load the first <signature> node.  
            signedXml.LoadXml((XmlElement)nodeList[0]);

            // Check the signature and return the result. 
            return signedXml.CheckSignature(Key);
        }
private void bInverifysign\u单击(对象发送方,事件参数e)
{
字符串LModulus=node.SelectSingleNode(//Signature/KeyInfo/KeyValue/RSAKeyValue/module”).InnerText.ToString();
string LExponent=node.SelectSingleNode(“//Signature/KeyInfo/KeyValue/RSAKeyValue/index”).InnerText.ToString();
使用(var rsa=new RSACryptoServiceProvider())
{
var rsaparm=新的rsaparmeters()
{
模数=从Base64字符串(LModulus)转换成,
指数=Convert.FromBase64String(lexComponent)
};
rsa.输入参数(rsaParam);
bool result=VerifyXml(newxml1,rsa);
}
公共静态布尔验证XML(XmlDocument文档,RSA密钥)
{
//检查参数。
如果(Doc==null)
抛出新的ArgumentException(“Doc”);
if(Key==null)
抛出新的ArgumentException(“键”);
//创建一个新的SignedXml对象并传递它
//XML文档类。
SignedXml SignedXml=新的SignedXml(Doc);
//找到“签名”节点并创建一个新的
//XmlNodeList对象。
XmlNodeList nodeList=Doc.GetElementsByTagName(“签名”);
//如果未找到签名,则引发异常。
如果(nodeList.Count 1)
{
Show(“验证失败:为文档找到了多个签名。”);
//抛出新的加密异常(“验证失败:为文档找到了多个签名。”);
}
//加载第一个节点。
signedXml.LoadXml((xmlement)节点列表[0]);
//检查签名并返回结果。
返回signedXml.CheckSignature(密钥);
}
在这里,如果我修改xml并通过VerifyXml方法验证它,它将返回false,如果我不修改xml,VerifyXml方法将返回true。我想知道它是如何验证xml的?我已尝试比较nodeList[0]中被篡改和未被篡改的xml的值,我得到了相同的值,但为signedXml。CheckSignature(Key)返回的是真/假。不同的xml的摘要值应该不同,对吗?这里我得到的是修改和未修改的xml的相同摘要值。基于什么确切的CheckSignature(Key)返回true/false。当为xml创建哈希值时?。谢谢。

实际上签名的是
元素,而不是数据对象。数据对象的哈希包含在
元素的
元素中。因此,数据对象也被间接签名。验证签名时,da的哈希值ta对象与
元素中已签名的数据摘要进行比较。然后使用公钥检查
元素上的签名


有关更多信息,您可以阅读。在这里您可以找到有关生成和验证签名xml的步骤的信息。

但此处元素为null。这意味着什么?未生成数据对象哈希?@Rakesh在您的示例中
元素不是null。它包含
元素ts.
包含使用
中定义的算法生成的数据对象哈希。在RFC 3275的第4.3.3节中,引用是一个可能出现一次或多次的元素。您也可以在该节中找到
元素内容的描述。