4

I am writing a piece of code to verify signature in Xml from X509 certificate and got the exception message in subject line.

My sample code

        Dim cert As X509Certificate2 = GetCertificate("Certificate Name")

        Dim signedXml As SignedXml = New SignedXml(Me.samlResponseXml)
        If (signedXml.CheckSignature(cert, True)) Then
            ' The signature is valid
        Else
            ' The signature is invalid
            Throw New ArgumentException("Invalid signature found in Saml Xml.")
        End If

I have loaded certificate from my certificate store successfully (1st line of the code). I have populated signedXml successfully (2nd line of the code).

The exception throws when I call signedXml.CheckSignature(cert, True) function. The message is very unclear:

Value cannot be null.
Parameter name: name

Any clue what is wrong here?

The call stacks:

System.ArgumentNullException was unhandled by user code
Message=Value cannot be null. Parameter name: name ParamName=name
Source=mscorlib StackTrace: at System.Security.Cryptography.CryptoConfig.CreateFromName(String name, Object[] args) at System.Security.Cryptography.Xml.SignedXml.CheckSignedInfo(AsymmetricAlgorithm key) at System.Security.Cryptography.Xml.SignedXml.CheckSignature(AsymmetricAlgorithm key) at System.Security.Cryptography.Xml.SignedXml.CheckSignature(X509Certificate2 certificate, Boolean verifySignatureOnly) at MyNamespace.MyClass.MyFunction() in D:\Projects\MyProject\Test.vb:line 117

Update 1 I turned on .Net Framework source debug, and the exception is thrown from SignedXml.CheckSignedInfo method, there is line of code

SignatureDescription signatureDescription = CryptoConfig.CreateFromName(SignatureMethod) as SignatureDescription;

It is obviously that SignatureMethod is a wrap of

    public string SignatureMethod  {
        get { return m_signature.SignedInfo.SignatureMethod; }
    }

The m_signature.SignedInfo.SignatureMethod is a null value. I read again from MSDN the explanation of SignatureMethod at http://msdn.microsoft.com/en-us/library/system.security.cryptography.xml.signedxml.signaturemethod.aspx and checked the Xml code with signature part is pasted below. I have a SignatureMethod tag with values in it, but why SignedXml is not able to process it?

  <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/2000/09/xmldsig#rsa-sha1" />
      <Reference URI="#_ea559faf-417b-407f-bdc2-bccc76dab76c">
        <Transforms>
          <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
          <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
            <InclusiveNamespaces PrefixList="#default samlp saml ds xs xsi" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" />
          </Transform>
        </Transforms>
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <DigestValue>fvQx+J90ZGKhwj8Mfhg6v/esOtI=</DigestValue>
      </Reference>
    </SignedInfo>
    <SignatureValue>Ft2mQEA3a39uRq5N94pDI8Y6B/UGLXHkZJ+/besOQmEtZoi630vBDzQfIxx5Djgg6YYeF/s67iF+KLgfvBrHxoe3E8xiqTwBigem41+PJdITlwgrOTkLo2sSdj4DaFdxeN+SCy6KfKXpDBvDyN4i/R0hBKodGwytfzK/DMeOhHU=</SignatureValue>
    <KeyInfo>
      <X509Data>
        <X509Certificate>MIICBjCCAXOgAwIBAgIQ3VhOVESMV71O0q5EttLxxDAJBgUrDgMCHQUAMBwxGjAYBgNVBAMTEUlkZW50aXR5UHJvdmlkZXIxMB4XDTExMDkwMTA1MDAwMFoXDTQwMTIzMTA1MDAwMFowHDEaMBgGA1UEAxMRSWRlbnRpdHlQcm92aWRlcjEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMBVhtKneTweMOgmvwO+i8AvZ5p0/PGatzLKNXVctTROcXb48u3L9JR3sVPasAFNsafq086xqaWyuFM7jAHtYHTQg/oLt+wGCKd7w/n4s0crxM3NVahDmSUPnBW9RZM2XD4pOs9DTu8aEEQGN/p01jrIMgPYhdlVsTJSg43lLyzjAgMBAAGjUTBPME0GA1UdAQRGMESAEHDoTOJwf2lSgqgCU4TXI2ShHjAcMRowGAYDVQQDExFJZGVudGl0eVByb3ZpZGVyMYIQ3VhOVESMV71O0q5EttLxxDAJBgUrDgMCHQUAA4GBAKvsy5KkU9dDNWDRW55/+s7txFfl4ZmWw45AmZYXEA90g+xzALFtWbX/QGqCOx4C0h5fB5Oco084B7gJK/uf2a8oaYvxYGwlxgRxJ9Dq5XBx5ZhOuobT8G2xVy575cbaGnFbObG6/E33Mva1gAYdw7rvGaz/dYuBeChsEIvzROYU</X509Certificate>
      </X509Data>
    </KeyInfo>
  </Signature>
hardywang
  • 4,864
  • 11
  • 65
  • 101
  • 1
    Is that XML you posted the full Me.samlResponseXml? AFAIK, you have to find the Signature element and pass it to the LoadXml element: signedXml.LoadXml(theSignatureElement). Similar to: http://msdn.microsoft.com/en-us/library/kd4wwa16.aspx – David Elizondo Apr 08 '12 at 07:36
  • Thanks for the comment, this is just the signature part of the Xml. Later on I figured out what you explained. – hardywang Apr 10 '12 at 00:16

1 Answers1

1

SignedXml requires two steps for verification. Step 1 is construction, where you give it the document or element in which the signed elements will be found. Part two is that you have to load in the Signature element (which could have come from a different document) via the LoadXml method.

To take an example from the SignedXml MSDN page, but modify it for certificates:

public static Boolean VerifyXmlFile(XmlElement samlResponseXml, X509Certificate2 cert)
{
    // Create a new SignedXml object and pass it the XML.
    SignedXml signedXml = new SignedXml(samlResponseXml);

    // Find the "Signature" node and create a new XmlNodeList object.
    XmlNodeList nodeList = xmlDocument.GetElementsByTagName("Signature");

    // TODO: Error checking.  Was it found? Were too many found?

    // Load the signature node.
    signedXml.LoadXml((XmlElement)nodeList[0]);

    // Check the signature and return the result.
    return signedXml.CheckSignature(cert, true);
}

When using SignedXml, be aware of the concerns that come from the Remarks section on the MSDN page. In particular, ensuring that the signing key is appropriate for the signed content (similar to performing hostname verification during a TLS session).

bartonjs
  • 30,352
  • 2
  • 71
  • 111