none
SignedXml.Checksignature returns false RRS feed

  • Question

  • Trying this with .NetFramework 4.0.

    I am working on implementatio of SSO using SAML for security. My code need to work as a Identity Service Provider where I need to validate a SAML Assertion generated from customer's Federation Server and sent to my web-site. As of now everything was good till I received a SAML Assertion with SHA1 algoritm but when it starts sending SHA256, the nighemare started. :)

    Well, I have read a lot around this and implemented provided suggestions but could not get through it yet. I have two ways to validate no one is working.

    In below code, as .Net Framework 4.0 does not support SHA256, I have create extension class (public class RSAPKCS1SHA256SignatureDescription : SignatureDescription) as mentioned here we well as here2, but did not help.

    Any help would be saviour.

    1. With only SAML Assertion hits my site (code is below). Always getting Fals as result from Checksignature.

    RSAPKCS1SHA256SignatureDescription.Register();
    
    XmlNamespaceManager nsm = new XmlNamespaceManager(new NameTable());
                    nsm.AddNamespace("dsig", SignedXml.XmlDsigNamespaceUrl);
                    XmlElement sigElt = (XmlElement)m_xmlDoc.SelectSingleNode(
                        "//dsig:Signature", nsm);
    
                    // Load the signature for verification
                    SignedXml sig = new SignedXml(m_xmlDoc);
                    sig.LoadXml(sigElt);
                    if (!sig.CheckSignature())
                        return "Invalid Signature";

    2. With the certificate (.cer) file provided by client and situated locally on Server.

    ///// WAY - 1
    private string VerifyCert1()
            {
    //m_xmlDoc - is a received SAMLAssertion converted to text
                if (m_xmlDoc == null)
                    return "Could not load SAMLResponse in XMLDocument object";
    
                if (m_useExternalCertificate && m_cert == null)
                    return "Could not load certificate in X509Certificate object from file";
    
    			// Call to register SHA256	
    			RSAPKCS1SHA256SignatureDescription.Register();
    				
                SamlSignedXml msSignedXML = new SamlSignedXml(m_xmlDoc);            
                string xmlDsigNS = "http://www.w3.org/2000/09/xmldsig#";            
    
                XmlNodeList nodeList = null;
                XmlNodeList keyInfoNodes = null;
                RSACryptoServiceProvider rsaKey = null;
    
                try
                {
                    nodeList = m_xmlDoc.GetElementsByTagName("Signature", xmlDsigNS);
                    rsaKey = GetPubKeyFromCert();
    
                    keyInfoNodes = m_xmlDoc.GetElementsByTagName("KeyInfo");
                    if (keyInfoNodes.Count > 0)
                    {
                        nodeList[0].RemoveChild(keyInfoNodes[0]);
                    }
                    msSignedXML.LoadXml((XmlElement)nodeList[0]);
                    
                    if (!msSignedXML.CheckSignature(rsaKey))
                        return "Invalid Signature";
                }
                catch (Exception e)
                {
                    return e.Message;
                }
                return "success";
            }
    
    ////////////////////////////////
    ///// WAY - 2
    private string VerifyCert2()
            {
                if (m_xmlDoc == null)
                    return "Could not load SAMLResponse in XMLDocument object";
    
                if (m_useExternalCertificate && m_cert == null)
                    return "Could not load certificate in X509Certificate object from file";
    
    			// Call to register SHA256	
                RSAPKCS1SHA256SignatureDescription.Register();
    
                string xmlDsigNS = "http://www.w3.org/2000/09/xmldsig#";
    
                XmlNodeList nodeList = null;
                XmlNodeList keyInfoNodes = null;
                RSACryptoServiceProvider rsaKey = null;
    
                try
                {
                   
                    nodeList = m_xmlDoc.GetElementsByTagName("ds:Reference");
                    // Throw an exception if no Reference node was found.
                    if (nodeList.Count <= 0)
                    {
                        throw new CryptographicException("Verification failed: No Reference was found in the document.");
                    }
    
                    rsaKey = GetRSAPublicKeyFromCertificate();
    
                    System.Security.Cryptography.Xml.Reference refDocNode =
                        new System.Security.Cryptography.Xml.Reference(nodeList[0].Attributes["URI"].Value);
    
                    SignedXml refDocument = new SignedXml(m_xmlDoc);
    
                    refDocument.AddReference(refDocNode);
                    refDocument.SigningKey = new RSACryptoServiceProvider(2048);
                    refDocument.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigC14NTransformUrl;
                    refDocument.ComputeSignature();
    
                    SignedXml mainDoc = new SignedXml(m_xmlDoc);
    
                    mainDoc.LoadXml(refDocument.GetXml());
    
                    if (!mainDoc.CheckSignature(rsaKey))
                        return "Invalid Signature";
                    
                }
                catch (Exception e)
                {
                    return e.Message;
                }
                return "success";
            }
    
    		//Utility function 
    private RSACryptoServiceProvider GetRSAPublicKeyFromCertificate()
            {
                RSACryptoServiceProvider rsaKey = null;
                RSAParameters rsaParams = new RSAParameters();
                CspParameters cspParam = new CspParameters();
    
                      //------------------------
                cspParam.Flags = CspProviderFlags.NoFlags;
                cspParam.KeyContainerName = Guid.NewGuid().ToString().ToUpperInvariant();
                cspParam.ProviderType = ((Environment.OSVersion.Version.Major > 5) || ((Environment.OSVersion.Version.Major == 5) && (Environment.OSVersion.Version.Minor >= 1))) ? 0x18 : 1;
                
                byte[] publicKeyBytes = m_cert.GetPublicKey();
                byte[] exponents = null;
                byte[] modulus = null;
    
                //MOD
    			//m_cer is created from .cer file which is available - its created as 
    			//			 m_cert = new X509Certificate2(m_certPath, "", X509KeyStorageFlags.Exportable);
                RSACryptoServiceProvider key = m_cert.PublicKey.Key as RSACryptoServiceProvider;
    
                if (key != null)
                {
                    RSAParameters parameters = key.ExportParameters(false);
                    exponents = parameters.Exponent;
                    modulus = parameters.Modulus;
                }
                //------------------------
    
                rsaParams.Modulus = modulus;
                rsaParams.Exponent = exponents;
    
                rsaKey = new RSACryptoServiceProvider(cspParam);
                rsaKey.ImportParameters(rsaParams);
                return rsaKey;
            }

    Regards

    Sandeep


    "An investment in knowledge pays the best interest." - Ben Franklin


    Tuesday, May 26, 2015 10:51 AM

All replies

  • Hi sandy,

    Thanks for posting in MSDN forums.

    I am not expert on SSO using SAML for security. Based on your description, As you said,

    >>In below code, as .Net Framework 4.0 does not support SHA256, I have create extension class (public class RSAPKCS1SHA256SignatureDescription : SignatureDescription)

    In .NET 4.0, you can create your certificate with an additional option: -sp "Microsoft Enhanced RSA and AES Cryptographic Provider" (or an equivalent -sy 24) and then your code would look like.

    var rsa = signerCertificate.PrivateKey as RSACryptoServiceProvider;
    //
    byte[] signature = rsa.SignData(data, CryptoConfig.CreateFromName("SHA256"));

    For more detailed information, please refer to Can RSACryptoServiceProvider (.NET's RSA) use SHA256 for encryption (not signing) instead of SHA1?

    In addition, please check this similar thread

    Unexpected false result of SignedXml.CheckSignature()

    I haven't seen your original XML document.Please check your XML file whether contained the ”xml:lang” tag. Refer to above thread for more information.

    Hope this will be helpful.

    Best regards,

    Kristin


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Wednesday, May 27, 2015 7:51 AM
  • Thank you so much Kristin for your reply. 

    Answering the questions and asking new :) as below.

    >>I haven't seen your original XML document.Please check your XML file whether contained the ”xml:lang” tag. Refer to above thread for more information.
    No, the original XML does not contain "xml:lang" tag.

    >>In .NET 4.0, you can create your certificate with an additional option: -sp "Microsoft Enhanced RSA and AES Cryptographic Provider" (or an equivalent -sy 24) and then your code would look like.
    >> var rsa = signerCertificate.PrivateKey as RSACryptoServiceProvider;
    >> //
    >> byte[] signature = rsa.SignData(data, CryptoConfig.CreateFromName("SHA256"));
    I am also really novice in this area and trying to find out the solution based on the already written code and articles on the net. But I did not get whats provided above. I am trying to Verify the signature with the help of SAML Assertion received.
    Is the code mentioned above for signing the document?

    In the thread mentioned in <Unexpected false result of SignedXml.CheckSignature()> the function definition is as - 
    public static bool VerifySignature(XNode originalDocument, XNode signedDocument)
    Here I am unable to guess how to get 'originalDocument' and 'signedDocument' from the assertion i receive.

    Could you please elaborate ?

    Apologies for dumb questions (if they are). :(

    "An investment in knowledge pays the best interest." - Ben Franklin

    Wednesday, May 27, 2015 8:36 AM
  • Hello sandy gadre,
    To further help you about this issue, I am trying to invoke someone experienced to help look into this thread, this may take some time and as soon as we get any result, we will post back.

    Regards,

    Kristin


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Thursday, May 28, 2015 11:09 AM
  • Hello Kristin,

    Any update on this? Really waiting for the help.

    Sandeep


    "An investment in knowledge pays the best interest." - Ben Franklin

    Tuesday, June 2, 2015 5:41 PM
  • Hi sandy,

    Sorry for late.

    Please check if the following thread helps.

    SignedXml.CheckSignature fails in .NET 4 but it works in .NET 3.5, 3 or 2

    Additionally, I've found some helpful documents from MSDN.

    How to: Sign XML Documents with Digital Signatures

    How to: Verify the Digital Signatures of XML Documents

    Regards,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    • Edited by Kristin Xie Wednesday, July 1, 2015 3:31 AM
    Wednesday, July 1, 2015 3:26 AM