1

I am trying to verify data that I received for verification in C#.

Here is XML I have,

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

I am using the below C# code to verify the above code,

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

But the above code is failing to verify. What I am missing? Is this whitespace issue?

Imran Qadir Baksh - Baloch
  • 32,612
  • 68
  • 179
  • 322

1 Answers1

1

The creation of an XML signature, i.e. the signing of an XML document (XMLDSig), is more complex than the creation of an ordinary signature, since one and the same XML can be serialized differently, i.e. the different serializations are logically identical. Therefore, the XML must be normalized beforehand, i.e. converted into a unique format (Canonicalization). Similarly, the same applies to verification.

.NET largely encapsulates these processes. Thereby, signing is more complex than verifying, since for the latter the parameters (e.g. the canonicalization variant) are contained in the signed XML.
In the signed XML posted in the question, the key (i.e. the certificate) used for verification is already embedded. In this case, a possible implementation of the verification is:

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

The signed XML included in the code is based on the example you posted, which I signed using a private test key. The certificate needed for verification and associated with the private key is embedded. The code can be run online on .NET Fiddel: https://dotnetfiddle.net/xpjAz4.

Note that the XmlDocument class has a PreserveWhitespace property, which defaults to false and controls whether whitespaces are preserved when loading or saving. When signing, the format of the XML document must be consistent with this, taking into account the PreserveWhitespace flag. In the posted code, the default value is used.

Further details for signing with an embedded key can be found here. Verification is described here.

EDIT:

In order to use the id attribute with the xml prefix, the SignedXml class must be derived and the GetIdElement() method must be overridden. This solution comes from this post, where the prefix and namespace need to be adjusted. The prefix xml is by definition bound to the namespace http://www.w3.org/XML/1998/namespace, s. W3C Recommendation, 3 Declaring Namespaces, Namespace constraint: Reserved Prefixes and Namespace Names.

Also, of course, because of the modification to xml:id the example signature changes which therefore also needs to be replaced, so the above code snippet changes overall to:

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

Now the XML example matches the example you posted exactly, including the xml:id attribute. The code snippet can be successfully executed e.g. online on .NET Fiddel: https://dotnetfiddle.net/nqNhu3.

Topaco
  • 40,594
  • 4
  • 35
  • 62
  • Thanks a lot. Your sample is working. But xml that I have (received from an api) is failing. Trying with every possible way but not working. I even updated `` to `` as you did. Api Team provided me 3 certificates they call it ClientCertificate, IntermediateCertificate and RootCertificate. I also tried `signedXml.CheckSignature(new X509Certificate2("Path"), true)`. What else I am missing – Imran Qadir Baksh - Baloch May 03 '21 at 01:41
  • Here is the glimpse of xml that I received from the Api https://i.stack.imgur.com/9Efqr.png – Imran Qadir Baksh - Baloch May 03 '21 at 01:46
  • @user960567 - When using `xml:id` I got an exception _Malformed reference element_ when signing. That's why I thought of a copy/paste error. Of course, you can't just change the xml in your xml signature (i.e. the attribute `xml:id` to `id`), because then the signature data won't fit (such a change should just be prevented by a signature). But I have now dug a little deeper and found a post that solves this issue, see the Edit section in my answer. Hope this works with your signature. – Topaco May 03 '21 at 08:27
  • Already tried above not working. Then I debug the code and found out that I need to use `idElem = (XmlElement)(doc.GetElementsByTagName("Message").Cast().FirstOrDefault());`. It fixed my issue. Great help! Thanks a lot. Your code is also working – Imran Qadir Baksh - Baloch May 03 '21 at 11:32