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,876 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Jiale Xue - MSFT 44,841 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.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.