1

I'm generating a SAML2 token from ADFS, signed by certificate. Now I'm trying to verify that signature, using the same certificate.

X509Certificate2 cert = LoadCert();
XmlDocument token = LoadXmlToken(); //SAML2 token
XmlElement signature = GetSignatureElement(token);

SignedXml signedXml = new SignedXml(token);
signedXml.LoadXml(signature);
bool result1 = signedXml.CheckSignature();            //true
bool result2 = signedXml.CheckSignature(cert, false); //false

CheckSignature() verifies signature against the public key contained in the token. CheckSignature(cert, [true/false]) verifies signature against the private key from the certificate.

How can it be that one works and the other doesn't?

friggle
  • 3,362
  • 3
  • 35
  • 47

3 Answers3

2

The method signedXml.CheckSignature() evaluates the xml signature integrity against the certificate contained inside the own signature.

The method SignedXml.CheckSignature(X509Certificate2, Boolean) evaluates the xml signature integrity against the certificate passed as first parameter, and optionally if the second parameter is false it checks also the validity of the certificate in the first parameter.

Probably the second method returns false because you are specifying a wrong certificate: is not the certificate which performs the signature or its state is revoked or expired or it is issued by an untrusted certificate authority.

albciff
  • 18,112
  • 4
  • 64
  • 89
  • That's the thing, it IS the same certificate. I'm controlling both ends of the equation right now, and it's the same certificate. It's not expired. How would trust play into this, and how can it be resolved? – friggle Mar 17 '14 at 13:52
  • 1
    The signedXml.CheckSignature() is not verifying the certificate validity against machine trust store. If you want to be sure that you are validating the original certificate you can do this: KeyInfoX509Data x509data = signedXml.Signature.KeyInfo.OfType().First(); X509Certificate2 cert = x509data.Certificates[0]; bool verified = cert != null && signedXml.CheckSignature(cert, false); – albciff Mar 17 '14 at 14:10
  • Ah! There's the issue. It is being signed by a different certificate than the one I have set on the Relying Party. – friggle Mar 17 '14 at 14:37
  • great you finally found the issue :) – albciff Mar 17 '14 at 18:38
2

We had to enable IP address and/or URL's on our outbound firewall for the checksignature method when using the certificate check. In our case it tried to communicate with the root CA and the sub CA's website. With the firewall closed the method failed, but once we identified the URL's being accessed and opened up the firewall it started to work as expected.

Morph
  • 196
  • 2
  • 7
1

The difference is in the second parameter (boolean). If you look at documentation of parameterless CheckSignature method you can find this:

This method also computes the digest of the references and the value of the signature.

The second method has this documentation. If the second parameter is set to

false then verify both the signature and certificate.

To verify certificate this method will probably build whole certificate chain and check revocation information of all certificates in this chain.

pepo
  • 8,644
  • 2
  • 27
  • 42
  • Unfortunately, it gets the same result for both true and false. – friggle Mar 17 '14 at 13:52
  • Are you sure that certificate from KeyInfo element from signed xml matches the certificate you use in CheckSignature method overload? When you manually extract certificate from KeyInfo element and check the signature using that certificate what does it do? Please set the second parameter to true in this test. – pepo Mar 17 '14 at 14:07