【问题标题】:Verify SignatureValue And DigestValue Using Sha256 RSA使用 Sha256 RSA 验证 SignatureValue 和 DigestValue
【发布时间】:2021-07-25 04:11:21
【问题描述】:

我正在尝试验证我收到的用于 C# 验证的数据。

这是我拥有的 XML,

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Response xmlns="http://www.site.ae/abc">
  <Message xml:id="message">
    <Header>
      <SomeDate>SomValue</SomeDate>
    </Header>
    <Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="SomeDataType">
      <SomeStatus>Success</SomeStatus>
    </Body>
  </Message>
  <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
    <SignedInfo>
      <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
      <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
      <Reference URI="#message">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
        <DigestValue>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    </SignatureValue>
    <KeyInfo>
      <X509Data>
        <X509Certificate>
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXX
        </X509Certificate>
      </X509Data>
    </KeyInfo>
  </Signature>
</Response>

我正在使用下面的C#代码来验证上面的代码,

var signature = @"
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
                    var data = @"
        <Header>
          <SomeDate>SomValue</SomeDate>
        </Header>
        <Body xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""SomeDataType"">
          <SomeStatus>Success</SomeStatus>
        </Body>";
                    var digest = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
                    var x509Data = @"
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
          XXXXXXXXXXXXXXXXXXXX";
                    byte[] SignatureValueBytes = Convert.FromBase64String(signature);
                    byte[] x509DataBytes = Convert.FromBase64String(x509Data);
                    byte[] DigestValueBytes = Convert.FromBase64String(digest);
                    var cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(x509DataBytes);

                    using (var rsa = System.Security.Cryptography.X509Certificates.RSACertificateExtensions.GetRSAPublicKey(cert))
                    {
                        bool a = rsa.VerifyHash(DigestValueBytes, SignatureValueBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                    }

但是上面的代码验证失败。我错过了什么?这是空格问题吗?

【问题讨论】:

    标签: c# .net encryption cryptography rsa


    【解决方案1】:

    XML 签名的创建,即 XML 文档 (XMLDSig) 的签名,比普通签名的创建更复杂,因为一个相同的 XML 可以被不同的序列化,即不同的序列化是逻辑上相同。因此,必须事先对 XML 进行规范化,即转换为唯一格式 (Canonicalization)。同样,这同样适用于验证。

    .NET 在很大程度上封装了这些过程。因此,签名比验证更复杂,因为对于后者,参数(例如规范化变体)包含在签名的 XML 中。
    在问题中发布的签名 XML 中,已嵌入用于验证的密钥(即证书)。在这种情况下,验证的可能实现是:

    using System;
    using System.Xml;
    using System.Security.Cryptography.Xml;
    
    public class VerifyTest
    {
        private static String signedXml = 
    @"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""no""?>
    <Response xmlns=""http://www.site.ae/abc"">
        <Message id=""message"">
            <Header>
                <SomeDate>SomValue</SomeDate>
            </Header>
            <Body xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""SomeDataType"">
                <SomeStatus>Success</SomeStatus>
            </Body>
        </Message>
        <Signature xmlns=""http://www.w3.org/2000/09/xmldsig#"">
            <SignedInfo>
                <CanonicalizationMethod Algorithm=""http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments""/>
                <SignatureMethod Algorithm=""http://www.w3.org/2001/04/xmldsig-more#rsa-sha256""/>
                <Reference URI=""#message"">
                    <Transforms>
                        <Transform Algorithm=""http://www.w3.org/2000/09/xmldsig#enveloped-signature""/>
                    </Transforms>
                    <DigestMethod Algorithm=""http://www.w3.org/2001/04/xmlenc#sha256""/>
                    <DigestValue>hXuAfCAwKQIH1lGErMom2yO//25Pbyn1eXEmcEL1Rtk=</DigestValue>
                </Reference>
            </SignedInfo>
            <SignatureValue>izFP8eyDkG+9mDF2mAFl66174gpYbBzbcPPc/kDMjRm4TFnZdMAITLe60EPqdQAKK61A6FW8ZQrCkbbiBk/PRd8WaAxgAxjnMU8/U6gYUI6pk2LAANMquguYs7NQjURf7QFr1M1s7F1OrDDVlJiy2ZK3f0yLPoJstA+tnSbjYTQNlYP2qqzGARDkuEXZELSeCjXfA6M2gcGv7EsAv3GtgC2wR3GaVnnfLcieC+8bB9PJwkUtS3P/nmZuvezq/nBvZ/VsIgVjD/rLZX3rAxtVmhRj4d2ykGomnTBU0UJJtcIJyL3UJaQssr1U8YpSA5yWMfJ1uYUCZrGfh7OsHst/qrxeNwO0tGWAdsbD5MWYIwJzHAFcBTrNB0c6g1ehZwihBJWST2YJZvo3xV4UEO4++MhgsP0NHI8fPeBTZRx/vIN7quiJ21YxumUSwA5o8t4Rg9SSOthpnEbfyrSRntlSe8U28EdT0aNVL5gG/N5Qf3eW7XYHjJ2gxv8llMG6UcTY3ck48sW7f+ODatJ5Uk6GALFRjGgrdDlIBgImEormswDmwXSF46XoQVnEH2bR89Yd7g5GlzWQC+Fr5Q2vgVJ/ufS/85URVDr/KFYiJCzzmCEFdZWPR0zrOF/1GDbdAx0s8Zu3Sbq1ERMbdEQqxHs3N0NhdtVtYu96AXXnj5Azg3Y=</SignatureValue>
            <KeyInfo>
                <X509Data>
                    <X509Certificate>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</X509Certificate>
                </X509Data>
            </KeyInfo>
        </Signature>
    </Response>";
    
        public static void Main(String[] args)
        {
            // Print XML document
            Console.WriteLine(VerifyTest.signedXml);
    
            // Load signed XML document
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(VerifyTest.signedXml);
    
            // Verify
            SignedXml signedXml = new SignedXml(xmlDoc);
            XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");
            signedXml.LoadXml((XmlElement)nodeList[0]);
            bool verified =  signedXml.CheckSignature();
            Console.WriteLine(new string('-', 100) + "\nVerified: " + verified);
        }
    }
    

    代码中包含的签名 XML 基于您发布的示例,我使用私有测试密钥对其进行了签名。嵌入了验证所需并与私钥关联的证书。代码可以在.NET Fiddel上在线运行:https://dotnetfiddle.net/xpjAz4

    注意XmlDocument 类有一个PreserveWhitespace 属性,默认为false 并控制在加载或保存时是否保留空格。签名时,XML 文档的格式必须与此一致,同时考虑到PreserveWhitespace 标志。在贴出的代码中,使用的是默认值。

    可以在here 找到使用嵌入式密钥进行签名的更多详细信息。验证描述为here

    编辑:

    为了使用带有xml 前缀的id 属性,必须派生SignedXml 类并且必须覆盖GetIdElement() 方法。这个方案来自this post,这里需要调整前缀和命名空间。前缀xml 根据定义绑定到命名空间http://www.w3.org/XML/1998/namespace,s。 W3C Recommendation, 3 Declaring Namespaces, Namespace constraint: Reserved Prefixes and Namespace Names.

    当然,由于xml:id的修改,示例签名也发生了变化,因此也需要替换,所以上面的代码sn-p整体更改为:

    using System;
    using System.Xml;
    using System.Security.Cryptography.Xml;
    
    public class VerifyTest
    {
        private static String signedXml =
    @"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""no""?>
    <Response xmlns=""http://www.site.ae/abc"">
      <Message xml:id=""message"">
        <Header>
          <SomeDate>SomValue</SomeDate>
        </Header>
        <Body xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""SomeDataType"">
          <SomeStatus>Success</SomeStatus>
        </Body>
      </Message>
      <Signature xmlns=""http://www.w3.org/2000/09/xmldsig#"">
        <SignedInfo>
          <CanonicalizationMethod Algorithm=""http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments""/>
          <SignatureMethod Algorithm=""http://www.w3.org/2001/04/xmldsig-more#rsa-sha256""/>
          <Reference URI=""#message"">
            <Transforms>
              <Transform Algorithm=""http://www.w3.org/2000/09/xmldsig#enveloped-signature""/>
            </Transforms>
            <DigestMethod Algorithm=""http://www.w3.org/2001/04/xmlenc#sha256""/>
            <DigestValue>8anSzrELTpH8X6qq9rzTr6+T79EsRVhMLZ0ws3nYOTA=</DigestValue>
          </Reference>
        </SignedInfo>
        <SignatureValue>IAxXS6JBw/DGI4BdAKBSuUWYD7vX8zA5yWnez6/D2B7o2DhpGLuZVVA6gqIf9cr0omk+5kwyQMStKoYm9JWhFU136XtMgx19WC/ZCvGa59LBpIUsVpr3IKm0cQasp4jMIyeQCbAi0R/fYCY3fdH6GWdMcPuh47oOM63mBUYarokUv0ypuPykZsH010VvS9Af42BPRjnSpFRLoY4E9YtkWNpNoEgIMFRCCC6xsH+mLjMVFAmldAAGHiYn1v847NmHR3qmjRd+tfn8YtxEeLLJNgNgg8+lE1C2wsCpBTowXi/LKngEEwL+pckaSxCFa6qLIDC8aOJHM9BN30lrvSAYFGfaNZ0SHECga6aQ05UgZrlMpCg56d65qqNBz0+kDEgFhCzr8CqftHfGcVGXm95k27qNrDsrPac8s16/LBzzhONAhEwMJ7Rlef27/xSl87RSOQWTJWLF6unsJBqWvpKJY+CP0mmezqCcN/Q28oETOrR8q4QaW7ByLLv5FH1O8nneJyfd2QmhDJ3XDBSWeTGlJEGPYztVWzz2qcq9jpKmzpYxMFOJS24SKQlKcKWAdGeRJVillTyANeDnSt1YOS/z2lQoWPzrNY1XCkBUdEA+pe0aFtX2X1JCKEqvS3AtRui8fZzQ+frhcC/Y/hYDO1mD3NliUH9zkcEm8PdGNBJaLIY=</SignatureValue>
        <KeyInfo>
          <X509Data>
            <X509Certificate>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</X509Certificate>
          </X509Data>
        </KeyInfo>
      </Signature>
    </Response>";
    
        public static void Main(String[] args)
        {
            // Print XML document
            Console.WriteLine(VerifyTest.signedXml);
    
            // Load signed XML document
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(VerifyTest.signedXml);
    
            // Verify
            SignedXmlWithId signedXml = new SignedXmlWithId(xmlDoc);
            XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");
            signedXml.LoadXml((XmlElement)nodeList[0]);
            bool verified =  signedXml.CheckSignature();
            Console.WriteLine(new string('-', 100) + "\nVerified: " + verified);
        }
    
        class SignedXmlWithId : SignedXml
        { 
            public SignedXmlWithId(XmlDocument xml) : base(xml) { }
            public SignedXmlWithId(XmlElement xmlElement) : base(xmlElement) { }
    
            public override XmlElement GetIdElement(XmlDocument doc, string id)
            {
                XmlElement idElem = base.GetIdElement(doc, id);
                if (idElem == null)
                {
                    XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
                    nsManager.AddNamespace("xml", "http://www.w3.org/XML/1998/namespace");
                    idElem = doc.SelectSingleNode("//*[@xml:id=\"" + id + "\"]", nsManager) as XmlElement;
                }
                return idElem;
            }
        }
    }
        
    

    现在 XML 示例与您发布的示例完全匹配,包括xml:id 属性。代码 sn-p 可以成功执行,例如.NET Fiddel 在线:https://dotnetfiddle.net/nqNhu3.

    【讨论】:

    • 非常感谢。您的样本正在工作。但是我拥有的 xml(从 api 接收)失败了。尝试各种可能的方法,但没有奏效。我什至像你一样将&lt;Message xml:id=""message""&gt; 更新为&lt;Message id=""message""&gt;。 Api 团队为我提供了 3 个证书,他们称之为 ClientCertificate、IntermediateCertificate 和 RootCertificate。我也试过signedXml.CheckSignature(new X509Certificate2("Path"), true)。我还缺少什么
    • 这是我从 Api i.stack.imgur.com/9Efqr.png 收到的 xml 的一瞥
    • @user960567 - 当使用xml:id 时,我在签名时遇到了一个异常Malformed reference element。这就是为什么我想到了复制/粘贴错误。当然,您不能只更改 xml 签名中的 xml(即属性 xml:idid),因为那样签名数据将不适合(这样的更改应该通过签名来防止)。但是我现在已经深入挖掘并找到了解决此问题的帖子,请参阅我的答案中的编辑部分。希望这适用于您的签名。
    • 上面已经试过了,不行。然后我调试代码,发现需要使用idElem = (XmlElement)(doc.GetElementsByTagName("Message").Cast&lt;XmlNode&gt;().FirstOrDefault());。它解决了我的问题。很大的帮助!非常感谢。您的代码也可以正常工作
    猜你喜欢
    • 1970-01-01
    • 2017-06-22
    • 2017-05-12
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 2017-07-30
    • 2011-01-10
    相关资源
    最近更新 更多