1

I was looking at the various posts around Validating SAML Response generated by Java in C#. I have been trying all the suggestions and am still getting a False from the SignedXml.CheckSignature and am totally out of ideas now on what could be wrong and am reaching out to you folks to see if you had suggestions I can use.

The Signature node in the Response is

 <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
  <ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
   <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
   <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
   <ds:Reference URI="#SM16afb708b851b15451d92108ac8c6a2a627a2643667" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:Transforms xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
     <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
     <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
    </ds:Transforms>
    <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/>
    <ds:DigestValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">kOlL02M8icLI1MtFnFUAcf/yols=</ds:DigestValue>
   </ds:Reference>
  </ds:SignedInfo>
  <ds:SignatureValue xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
   d2wjnwPdzDrsWvMq9EElkb0TVsj8LmMXqTusPuG3GbxsqVLFryqaMkwv/whTYD/evw8WNClJm1nC
   VpGTEPEB/voPiFJaNpdwvs6a6PuTizLQQaqOC1H6JC6KboUVR87wuJ4kV3W9QoGEft+OmZXMgUU6
   54PgOX3d/czqlQWS9Z8=
  </ds:SignatureValue>
  <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
   <ds:X509Data xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <ds:X509Certificate xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
     MIICCjCCAXOgAwIBAgIQazR4XEyfFItIKZvB/IC3/jANBgkqhkiG9w0BAQQFADATMREwDwYDVQQD
     EwhTYW1sVGVzdDAgFw0wMDAxMDEwNDAwMDBaGA8yMDk5MDEwMTA0MDAwMFowEzERMA8GA1UEAxMI
     U2FtbFRlc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK4kfW9Jg/WtQ+4yy631r2qkCVyK
     odGL0A3lg+4w3BfCSGf4N7GkAlHI4G582tC4tlwd/mj/IvN6qxhIyu45OlENZhWOXFOCogoX7Tfx
     Vd7XRUqNwdndjy9KY7uyIrXVczpGbk+ahp6SS0NAG9i1rYR/pxTvW4zUHkrFbgm8gdghAgMBAAGj
     XTBbMBMGA1UdJQQMMAoGCCsGAQUFBwMDMEQGA1UdAQQ9MDuAEHITUeo8fKKVys7DcdV65hmhFTAT
     MREwDwYDVQQDEwhTYW1sVGVzdIIQazR4XEyfFItIKZvB/IC3/jANBgkqhkiG9w0BAQQFAAOBgQA/
     Dm+yk4K3q8AG3q4dorWswL8fwU9dpjuvheRjAveaL5kr59QRanG+lLi8Wefg6iTPKDgIGc2VG13T
     KP7pZSysaXJ5i8N0zCg+eu/YL7Hw1kSXW/CdxwQ+qI1W53fQ9NXlLVWPXhIepAOL46EEZgACHEhv
     tG30XtStycyLOsgm9A==
    </ds:X509Certificate>
   </ds:X509Data>
  </ds:KeyInfo>
 </ds:Signature>

And the C# code I am using to validate the response is

try
{
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.PreserveWhitespace = true;
    xmlDoc.Load(@"C:\SAMLSSOResponse.txt");

    XmlNamespaceManager _documentNamespaceManager;
    _documentNamespaceManager = new XmlNamespaceManager(xmlDoc.NameTable);
    _documentNamespaceManager.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");
    _documentNamespaceManager.AddNamespace("samlp", "urn:oasis:names:tc:SAML:1.0:protocol");
    _documentNamespaceManager.AddNamespace("saml", "urn:oasis:names:tc:SAML:1.0:assertion");

    SignedXml signedXml = new SignedXml(xmlDoc);
    XmlNodeList nodeList = xmlDoc.GetElementsByTagName("ds:Signature");

    XmlNode xmlNode = xmlDoc.DocumentElement.SelectSingleNode("/samlp:Response/ds:Signature", _documentNamespaceManager);
    //xmlDoc.GetElementsByTagName("Signature");
    //signedXml.LoadXml((XmlElement)xmlNode);
    signedXml.LoadXml((XmlElement)nodeList[0]);

    X509Certificate2 certificate = null;
    foreach (KeyInfoClause clause in signedXml.KeyInfo)
    {
        if (clause is KeyInfoX509Data)
        {
            if (((KeyInfoX509Data)clause).Certificates.Count > 0)
            {
                certificate = (X509Certificate2)((KeyInfoX509Data)clause).Certificates[0];
            }
        }
    }

    if (certificate == null)
    {
        Console.WriteLine("No Certificate found");
    }

    Console.WriteLine("Testing with Certificate in the XML");
    if (signedXml.CheckSignature(certificate, true))
        Console.WriteLine("Validated");
    else
        Console.WriteLine("Failed");
}
catch (Exception ex)
{
}

I even tried to validate the signature by loading the Certificate in the code and still got the same issue.

Any one have any suggestions on why the signature is not getting validated ?

Doug Porter
  • 7,721
  • 4
  • 40
  • 55
user495261
  • 11
  • 3

1 Answers1

0

I solved the issue. There were multiple issues I had to deal with:

  1. The Response I was dealing with was a string that I got and was not validating. When I got the Base64Encoded string and then tried to validate it gave me a different error (Malformed Reference Element) which was solved by step 2.

  2. The Malformed Reference Element issue was resolved by creating a new class that inherited from SignedXML and then overwrite the GetIdElement class. Here is the code for that:

public class SamlSignedXml : SignedXml
    {
        private string _referenceAttributeId = "";
        public SamlSignedXml(XmlElement element, string referenceAttributeId)
            : base(element)
        {
            _referenceAttributeId = referenceAttributeId;
        }
        public override XmlElement GetIdElement(
            XmlDocument document, string idValue)
        {
            return (XmlElement)
                document.SelectSingleNode(
                    string.Format("//*[@{0}='{1}']",
                    _referenceAttributeId, idValue));
        }
    }

And when you create an instance of the SamlSignedXml class, you do as follows: SamlSignedXml signedXml = new SamlSignedXml(element, "ResponseID");

where element is the XmlDocument.DocumentElement.

That solved the issue

user495261
  • 11
  • 3