SignedXml CheckSignature is returning false everytime

Kumar Jalli 1 Reputation point
2022-12-09T18:31:22.153+00:00

We receive a SAML response from the client and when I am trying to validate the signature value using signedXml.CheckSignature(cert,true) then this method is returning always false.

I used the example code related to CheckSignature(X509Certificate2, Boolean) from this MSDN URL. Here, it will only create the SignedExample.xml file using a sample certificate and validated the signature successfully.

Created the certificate using the below command as mentioned in the MSDN example.

makecert -r -pe -n "CN=XMLDSIG_Test" -b 01/01/2005 -e 01/01/2010 -sky signing -ss my  

If the same code runs with my original SAML response file using the same signature details of the sample certificate then CheckSignature method is returning false everytime.

using System;  
using System.Security.Cryptography;  
using System.Security.Cryptography.Xml;  
using System.Security.Cryptography.X509Certificates;  
using System.Text;  
using System.Xml;  
  
public class SignVerifyEnvelope  
{  
  
    public static void Main(String[] args)  
    {  
  
        string Certificate = "CN=XMLDSIG_Test";  
  
        try  
        {  
  
            // Create an XML file to sign.  
            CreateSomeXml("Example.xml");  
            Console.WriteLine("New XML file created.");  
  
            // Sign the XML that was just created and save it in a  
            // new file.  
            SignXmlFile("Example.xml", "SignedExample.xml", Certificate);  
            Console.WriteLine("XML file signed.");  
  
            if (VerifyXmlFile("SignedExample.xml", Certificate))  
            {  
                Console.WriteLine("The XML signature is valid.");  
            }  
            else  
            {  
                Console.WriteLine("The XML signature is not valid.");  
            }  
  
  
            //Testing My SAML response file  
            if (VerifyXmlFile("SampleSamlResponse.xml", Certificate))  
            {  
                Console.WriteLine("The XML signature is valid.");  
            }  
            else  
            {  
                Console.WriteLine("The XML signature is not valid.");  
            }  
  
  
        }  
        catch (CryptographicException e)  
        {  
            Console.WriteLine(e.Message);  
        }  
    }  
  
    // Sign an XML file and save the signature in a new file.  
    public static void SignXmlFile(string FileName, string SignedFileName, string SubjectName)  
    {  
        if (null == FileName)  
            throw new ArgumentNullException("FileName");  
        if (null == SignedFileName)  
            throw new ArgumentNullException("SignedFileName");  
        if (null == SubjectName)  
            throw new ArgumentNullException("SubjectName");  
  
        // Load the certificate from the certificate store.  
        X509Certificate2 cert = GetCertificateBySubject(SubjectName);  
  
        // Create a new XML document.  
        XmlDocument doc = new XmlDocument();  
  
        // Format the document to ignore white spaces.  
        doc.PreserveWhitespace = false;  
  
        // Load the passed XML file using it's name.  
        doc.Load(new XmlTextReader(FileName));  
  
        // Create a SignedXml object.  
        SignedXml signedXml = new SignedXml(doc);  
  
        // Add the key to the SignedXml document.  
        signedXml.SigningKey = cert.GetRSAPrivateKey();  
  
        // Create a reference to be signed.  
        Reference reference = new Reference();  
        reference.Uri = "";  
  
        // Add an enveloped transformation to the reference.  
        XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();  
        reference.AddTransform(env);  
  
        // Add the reference to the SignedXml object.  
        signedXml.AddReference(reference);  
  
        // Create a new KeyInfo object.  
        KeyInfo keyInfo = new KeyInfo();  
  
        // Load the certificate into a KeyInfoX509Data object  
        // and add it to the KeyInfo object.  
        keyInfo.AddClause(new KeyInfoX509Data(cert));  
  
        // Add the KeyInfo object to the SignedXml object.  
        signedXml.KeyInfo = keyInfo;  
  
        // Compute the signature.  
        signedXml.ComputeSignature();  
  
        // Get the XML representation of the signature and save  
        // it to an XmlElement object.  
        XmlElement xmlDigitalSignature = signedXml.GetXml();  
  
        // Append the element to the XML document.  
        doc.DocumentElement.AppendChild(doc.ImportNode(xmlDigitalSignature, true));  
  
        if (doc.FirstChild is XmlDeclaration)  
        {  
            doc.RemoveChild(doc.FirstChild);  
        }  
  
        // Save the signed XML document to a file specified  
        // using the passed string.  
        using (XmlTextWriter xmltw = new XmlTextWriter(SignedFileName, new UTF8Encoding(false)))  
        {  
            doc.WriteTo(xmltw);  
            xmltw.Close();  
        }  
    }  
  
    // Verify the signature of an XML file against an asymmetric  
    // algorithm and return the result.  
    public static Boolean VerifyXmlFile(String FileName, String CertificateSubject)  
    {  
        // Check the args.  
        if (null == FileName)  
            throw new ArgumentNullException("FileName");  
        if (null == CertificateSubject)  
            throw new ArgumentNullException("CertificateSubject");  
  
        // Load the certificate from the store.  
        X509Certificate2 cert = GetCertificateBySubject(CertificateSubject);  
  
        // Create a new XML document.  
        XmlDocument xmlDocument = new XmlDocument();  
  
        // Load the passed XML file into the document.  
        xmlDocument.Load(FileName);  
  
        // Create a new SignedXml object and pass it  
        // the XML document class.  
        SignedXml signedXml = new SignedXml(xmlDocument);  
  
        // Find the "Signature" node and create a new  
        // XmlNodeList object.  
        XmlNodeList nodeList = xmlDocument.GetElementsByTagName("Signature");  
  
        // Load the signature node.  
        signedXml.LoadXml((XmlElement)nodeList[0]);  
  
        // Check the signature and return the result.  
        return signedXml.CheckSignature(cert, true);  
    }  
  
    public static X509Certificate2 GetCertificateBySubject(string CertificateSubject)  
    {  
        // Check the args.  
        if (null == CertificateSubject)  
            throw new ArgumentNullException("CertificateSubject");  
  
        // Load the certificate from the certificate store.  
        X509Certificate2 cert = null;  
  
        X509Store store = new X509Store("My", StoreLocation.CurrentUser);  
  
        try  
        {  
            // Open the store.  
            store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);  
  
            // Get the certs from the store.  
            X509Certificate2Collection CertCol = store.Certificates;  
  
            // Find the certificate with the specified subject.  
            foreach (X509Certificate2 c in CertCol)  
            {  
                if (c.Subject == CertificateSubject)  
                {  
                    cert = c;  
                    break;  
                }  
            }  
  
            // Throw an exception of the certificate was not found.  
            if (cert == null)  
            {  
                throw new CryptographicException("The certificate could not be found.");  
            }  
        }  
        finally  
        {  
            // Close the store even if an exception was thrown.  
            store.Close();  
        }  
  
        return cert;  
    }  
  
    // Create example data to sign.  
    public static void CreateSomeXml(string FileName)  
    {  
        // Check the args.  
        if (null == FileName)  
            throw new ArgumentNullException("FileName");  
  
        // Create a new XmlDocument object.  
        XmlDocument document = new XmlDocument();  
  
        // Create a new XmlNode object.  
        XmlNode node = document.CreateNode(XmlNodeType.Element, "", "MyElement", "samples");  
  
        // Add some text to the node.  
        node.InnerText = "Example text to be signed.";  
  
        // Append the node to the document.  
        document.AppendChild(node);  
  
        // Save the XML document to the file name specified.  
        using (XmlTextWriter xmltw = new XmlTextWriter(FileName, new UTF8Encoding(false)))  
        {  
            document.WriteTo(xmltw);  
  
            xmltw.Close();  
        }  
    }  
}  

Below is my Sample SAML Response file

<?xml version="1.0" encoding="UTF-8"?>  
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_3b7df14a-0f79-4289-8cb8-efc3bace841c" Version="2.0" IssueInstant="2020-09-08T17:04:28.018Z" Destination="https://somewhere.abc/adminsso.do">  
   <Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">https://sts.windows.net/qwertyui-sdfg-4f45-a6d0-asdfghjklqwe/</Issuer>  
   <samlp:Status>  
      <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />  
   </samlp:Status>  
   <Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" ID="_asdfghjk-2345-5678-asdf-asdfghjklzxc" IssueInstant="2020-09-08T17:04:28.013Z" Version="2.0">  
      <Issuer>https://sts.windows.net/qwertyui-sdfg-4f45-a6d0-asdfghjklqwe/</Issuer>  
      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">  
         <SignedInfo>  
            <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />  
            <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />  
            <Reference URI="#_asdfghjk-2345-5678-asdf-asdfghjklzxc">  
               <Transforms>  
                  <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />  
                  <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />  
               </Transforms>  
               <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />  
               <DigestValue>Kglqb8fjGmMi2n4W8qXldBIY7VBi0xbNn+dZml7H3xw=</DigestValue>  
            </Reference>  
         </SignedInfo>  
         <SignatureValue>kAB5IaPijVsotG8UdbjBu8AYXCOE6vS+fruPlidSxqIUyzRMlLAsOG2iVEHbBPIWWF2Ujjs7PdQ1cZzPg3LhwHVMam9PRnxbUaqoI+RTqudtXS3Fk4zwpsbvPw0LctQdzelwZTFIK/8iiEh/MA+dqSlw/3r2c8rpsMPH59P4tnp7bxPDTXnAEiHvFPKmTswT5fq65ltvhbz5hI+pGAdtB1GMBrVpFnloOFi6Vl2aObDhlAwd4gNuNoKL/UvefWi4olPMIQeZMzKpjXpd7Y8xM40aI2ZCTYyvrZLxRUSH/rhmktdV9WTVUAKOeJK7N3v0qm8ugErthVsi07R1nTISNw==</SignatureValue>  
         <KeyInfo>  
            <X509Data>  
               <X509Certificate>MIIDIDCCAgygAwIBAgIQuE67xogamKtIq5JLOK6/SDAJBgUrDgMCHQUAMCMxITAfBgNVBAMeGABYAE0ATABEAFMASQBHAF8AVABlAHMAdDAeFw0xNDEyMzExODMwMDBaFw0yOTEyMzExODMwMDBaMCMxITAfBgNVBAMeGABYAE0ATABEAFMASQBHAF8AVABlAHMAdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMGyvAOfq+vKQq9oGtpsjL951MjqO0efmem3dYunHZbzqXM1T2yH0Kvk6k0BbvBvPgM/zH2NKRfy89uiOB2HeJOxdsYP1RUUsh3h4CpGkYrMrfwKkpuBH+/4JuswrdO6N953q3BGZeYKyN2R7RnUmemq4062GJlmQ0w1i1lWf8LSH/LK98KteIBtotyHuhNkrkqlKCu90sC0JGG1McG47WJV+fYyetYTLw6hz8/ZIhbO4mBE8vMp/1gbzt4wu2SV6udNy6PmzrUzKSYn3uybdvYLFb29rUzSN7MhDxd1pOjRME04EbiR4sG/Am3F1rNEqknWIGkhjnzar+s5ooeEHwkCAwEAAaNYMFYwVAYDVR0BBE0wS4AQGGmx80i4/Wy7yMYiizXboaElMCMxITAfBgNVBAMeGABYAE0ATABEAFMASQBHAF8AVABlAHMAdIIQuE67xogamKtIq5JLOK6/SDAJBgUrDgMCHQUAA4IBAQCkk5IuFV8JRE8tlFj8jXU0QsuFp/8YMUqGkMmWQ9cgYcYAsBYcLOYtZEvEfuxD8Pil4iOnXooibOrU0zArSPNdkIy8ka9A89CkaQXaC6Z8JGHJCjee6GdrHoJ1FtJ29XZqco1YVG6lMRug2pCSFa+fXnfyFofko4aSs7M76b4gQQPFgCHE4B8zvRaPdJu0D6nJcJOIVokIZIwF+fuQKNPnR0wranELBo6YbhSE0++a8lv3PBxkAscZ5svT8FdzcWzr6eaQJfLuWUsqWSjh1lE3cbZKHXnq5wBq149nzPQrvfgXTiil5YDCyZUN9xWU5ijCc2exFxPG4W8wqmnqxpPi</X509Certificate>  
            </X509Data>  
         </KeyInfo>  
      </Signature>  
      <Subject>  
         <NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">abc@domain.com</NameID>  
         <SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">  
            <SubjectConfirmationData NotOnOrAfter="2024-09-08T18:04:27.810Z" Recipient="https://somewhere.abc/adminsso.do" />  
         </SubjectConfirmation>  
      </Subject>  
      <Conditions NotBefore="2020-09-08T16:59:27.810Z" NotOnOrAfter="2024-09-08T18:04:27.810Z">  
         <AudienceRestriction>  
            <Audience>https://somewhere.abc</Audience>  
         </AudienceRestriction>  
      </Conditions>  
      <AttributeStatement>  
         <Attribute Name="http://schemas.microsoft.com/identity/claims/tenantid">  
            <AttributeValue>qwertyui-sdfg-4f45-a6d0-asdfghjklqwe</AttributeValue>  
         </Attribute>  
         <Attribute Name="http://schemas.microsoft.com/identity/claims/objectidentifier">  
            <AttributeValue>9a45ea45-6122-443a-8e01-45dc9a89e589</AttributeValue>  
         </Attribute>  
         <Attribute Name="http://schemas.microsoft.com/identity/claims/displayname">  
            <AttributeValue>sample, abc</AttributeValue>  
         </Attribute>  
         <Attribute Name="http://schemas.microsoft.com/identity/claims/identityprovider">  
            <AttributeValue>https://sts.windows.net/qwertyui-sdfg-4f45-a6d0-asdfghjklqwe/</AttributeValue>  
         </Attribute>  
         <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname">  
            <AttributeValue>sample</AttributeValue>  
         </Attribute>  
         <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname">  
            <AttributeValue>abc</AttributeValue>  
         </Attribute>  
         <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress">  
            <AttributeValue>abc@domain.com</AttributeValue>  
         </Attribute>  
         <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name">  
            <AttributeValue>sample</AttributeValue>  
         </Attribute>  
      </AttributeStatement>  
      <AuthnStatement AuthnInstant="2020-09-08T12:29:35.621Z" SessionIndex="_asdfghjk-2345-5678-asdf-asdfghjklzxc">  
         <AuthnContext>  
            <AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</AuthnContextClassRef>  
         </AuthnContext>  
      </AuthnStatement>  
   </Assertion>  
</samlp:Response>  

save the above file as SampleSamlResponse.xml in debug folder.

one thing I observed is that the code is working fine with the below Saml response (saml2p:resposne) but I need the code to work with first saml respose (samlp:resposne) file because we receive that from the client

<?xml version="1.0" encoding="UTF-8"?>  
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_a768f8de-d02c-4c61-9589-d7cc063d012a" Version="2.0" IssueInstant="2022-12-08T14:17:44.988Z" Destination="http://somewhere/">  
   <saml2:Issuer>sample-issuer</saml2:Issuer>  
   <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">  
      <SignedInfo>  
         <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />  
         <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />  
         <Reference URI="#_a768f8de-d02c-4c61-9589-d7cc063d012a">  
            <Transforms>  
               <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />  
               <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />  
            </Transforms>  
            <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />  
            <DigestValue>ap5YvbiOn91+4yyezmOilHJUyhzQ1mEDCjEfTQ/Zy+k=</DigestValue>  
         </Reference>  
      </SignedInfo>  
      <SignatureValue>dmrmEyCaf9PWG4Tx9KIyXyYy8YWdDai3fXjvtFVGl9NDHYIDKzuGUMtMxNFLiIWL4g/DlTG/V8TOyjh4HeJSqB8W4T7G3bDdVeOKpLWphWgn/87S1BEah3A9dvg29654kPNZhSQz5IF9wkWecN4pSMzlf4O85jFkcYq6DBVuw+3F2hSzrNWzB3bF4DGWBnpZE35gsjwS8MwPyZ1iIxIR+WTCmRi0OuHJVYIzNIIL5V/sP5JjhtGd6PwtKKZ1SpqcHNqoqTMV9hyXBwJK0EIacvIH3pGvqJAt7Yz6FRhJ1EADKymB/MVDdeKIO0m75/azeWVx6mPuIgzpF2zAdva9aA==</SignatureValue>  
      <KeyInfo>  
         <X509Data>  
            <X509Certificate>MIIDIDCCAgygAwIBAgIQuE67xogamKtIq5JLOK6/SDAJBgUrDgMCHQUAMCMxITAfBgNVBAMeGABYAE0ATABEAFMASQBHAF8AVABlAHMAdDAeFw0xNDEyMzExODMwMDBaFw0yOTEyMzExODMwMDBaMCMxITAfBgNVBAMeGABYAE0ATABEAFMASQBHAF8AVABlAHMAdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMGyvAOfq+vKQq9oGtpsjL951MjqO0efmem3dYunHZbzqXM1T2yH0Kvk6k0BbvBvPgM/zH2NKRfy89uiOB2HeJOxdsYP1RUUsh3h4CpGkYrMrfwKkpuBH+/4JuswrdO6N953q3BGZeYKyN2R7RnUmemq4062GJlmQ0w1i1lWf8LSH/LK98KteIBtotyHuhNkrkqlKCu90sC0JGG1McG47WJV+fYyetYTLw6hz8/ZIhbO4mBE8vMp/1gbzt4wu2SV6udNy6PmzrUzKSYn3uybdvYLFb29rUzSN7MhDxd1pOjRME04EbiR4sG/Am3F1rNEqknWIGkhjnzar+s5ooeEHwkCAwEAAaNYMFYwVAYDVR0BBE0wS4AQGGmx80i4/Wy7yMYiizXboaElMCMxITAfBgNVBAMeGABYAE0ATABEAFMASQBHAF8AVABlAHMAdIIQuE67xogamKtIq5JLOK6/SDAJBgUrDgMCHQUAA4IBAQCkk5IuFV8JRE8tlFj8jXU0QsuFp/8YMUqGkMmWQ9cgYcYAsBYcLOYtZEvEfuxD8Pil4iOnXooibOrU0zArSPNdkIy8ka9A89CkaQXaC6Z8JGHJCjee6GdrHoJ1FtJ29XZqco1YVG6lMRug2pCSFa+fXnfyFofko4aSs7M76b4gQQPFgCHE4B8zvRaPdJu0D6nJcJOIVokIZIwF+fuQKNPnR0wranELBo6YbhSE0++a8lv3PBxkAscZ5svT8FdzcWzr6eaQJfLuWUsqWSjh1lE3cbZKHXnq5wBq149nzPQrvfgXTiil5YDCyZUN9xWU5ijCc2exFxPG4W8wqmnqxpPi</X509Certificate>  
         </X509Data>  
      </KeyInfo>  
   </Signature>  
   <saml2p:Status>  
      <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />  
   </saml2p:Status>  
   <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_0449d2d8-5722-4c20-861f-056ddbb6c7fe" IssueInstant="2022-12-08T14:17:45.060Z" Version="2.0">  
      <saml:Issuer>sample-issuer</saml:Issuer>  
      <saml:Subject>  
         <saml:NameID>sample abc</saml:NameID>  
         <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">  
            <saml:SubjectConfirmationData NotOnOrAfter="2022-12-08T14:22:45.160Z" Recipient="http://somewhere" />  
         </saml:SubjectConfirmation>  
      </saml:Subject>  
      <saml:Conditions NotBefore="2022-12-08T14:17:45.113Z" NotOnOrAfter="2022-12-08T15:17:45.028Z">  
         <saml:AudienceRestriction>  
            <saml:Audience>http://somewhere</saml:Audience>  
         </saml:AudienceRestriction>  
      </saml:Conditions>  
      <saml:AttributeStatement>  
         <saml:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress">  
            <saml:AttributeValue>abc@domain.com</saml:AttributeValue>  
         </saml:Attribute>  
         <saml:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/locality">  
            <saml:AttributeValue>somewhere</saml:AttributeValue>  
         </saml:Attribute>  
      </saml:AttributeStatement>  
      <saml:AuthnStatement AuthnInstant="2022-12-08T14:17:45.157Z">  
         <saml:AuthnContext>  
            <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>  
         </saml:AuthnContext>  
      </saml:AuthnStatement>  
   </saml:Assertion>  
</saml2p:Response>  

I am not getting what I am missing. I am using .Net framework 4.8

Please help.

ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,288 questions
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,306 questions
0 comments No comments
{count} votes