Signing Specific XML With References

I've previously blogged about creating XML digital signatures using the .NET framework, but today I'd like to write about a more advanced technique using these signatures. My previous post signed an entire XML document, however, this is not always necessary or even desirable. For instance, if a particular XML document was being authored by several people, you might only want to sign the portions that you worked on.

In this post, I'm going to work with the following XML, signing the elements named signed, but not providing a signature for the unsigned element.

  <signed id='tag1'>Signed Data</signed>
  <unsigned id='tag2'>Unsigned Data</unsigned>
  <signed id='tag3'>More Signed Data</signed>

Previous signatures I've shown have all contained only one reference, which referred to the entire document. In order to sign more specific portions of the document, you can sign elements by id. An element's id is any element that contains an 'id', 'Id', or 'ID' attribute. Its important to keep in mind that signing an element will also sign any sub elements.

In order to refer to an element by ID, the reference must be created by passing a string of the form "#id". Here's some sample code that will create references to the signed data from above.

XmlDocument doc = new XmlDocument();

SignedXml signer = new SignedXml(doc);
signer.AddReference(new Reference("#tag1"));
signer.AddReference(new Reference("#tag3"));

Notice that its perfectly legal to use multiple references in the same signature. This allows me to sign multiple portions of the document with my key. The process of actually signing the document is the same as it was with only one reference. Of course, in reality I would not be generating a random key to sign with, but I would use a key pair that was available for interested parties to find, so that they could verify the signature.

signer.SigningKey = new RSACryptoServiceProvider();

This produces signed XML that looks like the following:

<Signature xmlns="">
    <CanonicalizationMethod Algorithm="" />
    <SignatureMethod Algorithm="" />
    <Reference URI="#tag1">
      <DigestMethod Algorithm="" />
    <Reference URI="#tag3">
      <DigestMethod Algorithm="" />
  <SignatureValue>SQN+6HlM . . . NqvsN04=</SignatureValue>

Verifying this signature works exactly the same as verifying the signature over an entire document.  You'll also notice that even if you modify the value of the unsigned element, the signature still verifies.

// modify the unsigned element -- the signature should still verify
XmlElement unsignedElem = doc.SelectSingleNode("//xml/unsigned") as XmlElement;
unsignedElem.InnerText = "Modified Data";

SignedXml verifier = new SignedXml(doc);


Updated: I needed to be more clear above. "id" and "ID" only work on Whidbey. If you're using v1.0 or 1.1 of the framework, you'll need to use "Id" attributes.

Comments (6)

  1. Orlando says:

    Nice, but I could only get it to work with "Id". id or ID causes compute signature to throw a Malformed reference element exception.

    XmlDocument doc = new XmlDocument();

    doc.LoadXml("<xml><signed Id=’tag1′>Signed Data</signed><unsigned Id=’tag2′>Unsigned Data</unsigned><signed Id=’tag3′>More Signed Data</signed></xml>");

    SignedXml signer = new SignedXml(doc);

    signer.AddReference(new Reference("#tag1"));

    signer.AddReference(new Reference("#tag3"));

    signer.SigningKey = new RSACryptoServiceProvider();


  2. Shawn says:

    Hi Orlando — good catch! You’re right, on v1.0 and v1.1 of the framework, only Id will work. New with Whidbey is the inclusion of id and ID. I’ll update the post with this information. Thanks!

  3. John says:

    What about if we have an attribute of type ID but its name is for example ResponseID (as in SAML). It throughs an exception before the signature is created. Is there any way. to sign it like #ResponseID

    Thanks in advance

  4. John says:

    What about if we have an attribute of type ID but its name is for example ResponseID (as in SAML). It throughs an exception before the signature is created. Is there any way. to sign it like #ResponseID

    Thanks in advance

  5. Shawn says:

    Hi John,

    There sure is a way to do that. I’ve written two posts and given some sample code showing how. Check out: (Searching for Custom ID Tags with Signed XML)

    and (xml:id and SignedXml)


Skip to main content