Xml signature validation on part of document fails in C# .NET

1.8k views Asked by At

Given an XML document where the root node is signed with an RSA+SHA2 signature, which contains an XML element that is signed separately again with RSA+SHA2, I find that:

  • The signature on the root node is invalid
  • The separate signature on the child node is invalid

When copying the signed child node into a new XML file, also moving the xmlns: declarations to that node as well to maintain namespace scope, I find that

  • The signature is valid

The XML structure is something like. In real life the XML is a signed SAML2 ArtifactResolve element containing a signed SAML2 Assertion.

<Root id="_1">
  <ds:Signature reference="_1" />
  <Child id="_2">
    <ds:Signature reference="_2" />
  </Child>
</Root>

The code used to validate all of this is quite simple, the SignedXml class.

  SignedXml signedDocument = new SignedXml(document.DocumentElement);
  signedDocument.LoadXml(GetSignatureElement(document.DocumentElement));
  Console.WriteLine("Document valid: {0}", 
    signedDocument.CheckSignature(cert, true)); // returns false

My main issue here is the odd behaviour of being able to validate the node by copying it into a new XML file. If I query that node through XPath and load that up into SignedXml, it fails.

  XmlElement element = (XmlElement)document.SelectSingleNode("//Child");
  SignedXml signedDocument = new SignedXml(element);
  signedDocument.LoadXml(GetSignatureElement(element));
  Console.WriteLine("Element valid: {0}", 
    signedDocument.CheckSignature(cert, true));  // returns false

Now if there were a ton of settings on SignedXml that I can botch up, hey, but there aren't that much. Load the Xml, load the signature, validate.

Anyone with any clue why this behavior is the way it is? Already tried using PreserveWhitespace=true on the XmlDocument but that didn't help.

Much appreciated!

Wouter

1

There are 1 answers

0
ricksmt On

I had a similar problem. Here's the Q & A. First, the reference attributes should be of the format reference="#{insert id here}". That should cause the document signature to validate. Then move/append the child's signature to the root element, and then the child signature should validate.

Truth be told, I'm having an issue where the document hasn't been signed, but a child element has, and I can't validate that signature. Not yet at least. I'll update if I figure that out.