Error Verify Signature XML DGI UY always return false

Alexi Tomala 0 Reputation points
2024-06-28T20:06:42.6466667+00:00

I am working on validating the signature of an XML envelope in this case from Uruguay,

but due to the signature verification method it always returns false using .Net C#

The tests carried out with unsuccessful results, apply the following code that obtains the certificate and the signature within a cycle, considering that the xml has several signatures and a single certificate

using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;

public static void Main(string[] args)
        {
           string xmlFilePath = @"d:\Sob_219999830019_Ej_Mod_19072016.xml";//args[0];

           XmlDocument xmlDoc = new XmlDocument();
           xmlDoc.PreserveWhitespace = true;   /*It was validated by both true and false*/
            xmlDoc.Load(xmlFilePath);
           SignedXml signedXml = new SignedXml(xmlDoc);
           XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");
           XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
           nsmgr.AddNamespace("DGICFE", "http://cfe.dgi.gub.uy");

            XmlNode certificateNode = xmlDoc.SelectSingleNode("//DGICFE:Caratula/DGICFE:X509Certificate", nsmgr);
            if (certificateNode != null)
            {
                string certificateBase64 = certificateNode.InnerText;
                byte[] certificateData = Encoding.UTF8.GetBytes(certificateBase64);
                X509Certificate2 dcert2 = new X509Certificate2(certificateData); 

                foreach (XmlElement element in nodeList)
                {                   
                    signedXml.LoadXml(element);                   
                    signedXml.SigningKey = dcert2.GetRSAPublicKey();
                    /*in these 3 verifications it returns false*/
                    bool passes = signedXml.CheckSignature(dcert2, true);
                      passes = signedXml.CheckSignature(dcert2, false);
                    passes = signedXml.CheckSignature();
                    
                }
            }


        }


Checking the logs in the console I have this response, but it does not give any further indication that it may be failing

System.Security.Cryptography.Xml.SignedXml Information: 2 : [SignedXml#00245fb7, BeginCheckSignedInfo] Checking signature in SignedInfo with id. "(null)".
System.Security.Cryptography.Xml.SignedXml Information: 14 : [SignedXml#00245fb7, VerifySignedInfo] Checking SignedInfo using key RSACng#01475d71, 
signature description RSAPKCS1SHA1SignatureDescription,
 hash algorithm SHA1Cng and asymmetric signature deformatter RSAPKCS1SignatureDeformatter.

System.Security.Cryptography.Xml.SignedXml Verbose: 14 : [SignedXml#00245fb7, VerifySignedInfo] Actual hash value: 8247f7f76542509039de0f38150e4878250e51
System.Security.Cryptography.Xml.SignedXml Verbose: 14 : [SignedXml#00245fb7, VerifySignedInfo] Raw signature: 91ef1705f3de4f83b310ae5e9f1089ea72b7ebb7d2f51171d34ed8cbe03c340cf5f9c3c87 
System.Security.Cryptography.Xml.SignedXml Information: 12 : [SignedXml#00245fb7, VerificationFailure] Failed to verify SignedInfo.

Perform tests with different .net framework 3.0,3.5,4.0... up to 4.8 and .Net core 6 the result is the same.

I reviewed similar questions and none of the proposed solutions have worked for me.

The test xml is verified, that is, it has valid signatures... I attach a screenshot of the xml that I am verifying

Please can you help me by indicating what may be wrong in the code or what else I can verify?

The expected response is true, since a valid xml103545

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,627 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Jiale Xue - MSFT 42,816 Reputation points Microsoft Vendor
    2024-07-01T08:51:25.9466667+00:00

    Hi @Alexi Tomala , Welcome to Microsoft Q&A,

    The current way of decoding certificates is incorrect. Base64 encoded certificates should be decoded into byte arrays instead of using UTF-8 encoding.

    When loading and verifying signatures, make sure you verify the entire document, not just the signature node.

    using System;
    using System.Security.Cryptography.X509Certificates;
    using System.Security.Cryptography.Xml;
    using System.Text;
    using System.Xml;
    
    public class Program
    {
        public static void Main(string[] args)
        {
            string xmlFilePath = @"d:\Sob_219999830019_Ej_Mod_19072016.xml"; //args[0];
    
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.PreserveWhitespace = true;
            xmlDoc.Load(xmlFilePath);
    
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
            nsmgr.AddNamespace("DGICFE", "http://cfe.dgi.gub.uy");
    
            XmlNode certificateNode = xmlDoc.SelectSingleNode("//DGICFE:Caratula/DGICFE:X509Certificate", nsmgr);
            if (certificateNode != null)
            {
                string certificateBase64 = certificateNode.InnerText;
                byte[] certificateData = Convert.FromBase64String(certificateBase64);
                X509Certificate2 dcert2 = new X509Certificate2(certificateData);
    
                XmlNodeList nodeList = xmlDoc.GetElementsByTagName("Signature");
                foreach (XmlElement element in nodeList)
                {
                    SignedXml signedXml = new SignedXml(xmlDoc);
                    signedXml.LoadXml(element);
    
                    bool passes = signedXml.CheckSignature(dcert2, true);
                    if (passes)
                    {
                        Console.WriteLine("Signature verified successfully.");
                    }
                    else
                    {
                        Console.WriteLine("Failed to verify signature.");
                    }
                }
            }
            else
            {
                Console.WriteLine("Certificate node not found.");
            }
        }
    }
    
    

    Best Regards,

    Jiale


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment". 

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.