<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>.NET Security Blog : XML</title><link>http://blogs.msdn.com/shawnfa/archive/tags/XML/default.aspx</link><description>Tags: XML</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>XML Digital Signature Verification with Unknown URI Schemes</title><link>http://blogs.msdn.com/shawnfa/archive/2006/10/12/xml-digital-signature-verification-with-unknown-uri-schemes.aspx</link><pubDate>Thu, 12 Oct 2006 19:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:819912</guid><dc:creator>shawnfa</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/shawnfa/comments/819912.aspx</comments><wfw:commentRss>http://blogs.msdn.com/shawnfa/commentrss.aspx?PostID=819912</wfw:commentRss><description>&lt;P&gt;A few years back, there was &lt;A class="" href="http://blogs.msdn.com/shawnfa/archive/2004/04/05/108098.aspx" mce_href="http://blogs.msdn.com/shawnfa/archive/2004/04/05/108098.aspx"&gt;a discussion thread on one of my XML digital signature posts&lt;/A&gt;&amp;nbsp;about verifying an XML digital signature which had references to a URI prefixed with cid:.&amp;nbsp; Recently &lt;A class="" href="http://blogs.msdn.com/mattlind" mce_href="http://blogs.msdn.com/mattlind"&gt;Mattias Lindberg&lt;/A&gt; ran into this problem as well, and &lt;A class="" href="http://blogs.msdn.com/mattlind/archive/2006/10/10/Validating-XML-Digital-Signatures-with-References-Using-Unrecognized-URI-Prefixes.aspx" mce_href="http://blogs.msdn.com/mattlind/archive/2006/10/10/Validating-XML-Digital-Signatures-with-References-Using-Unrecognized-URI-Prefixes.aspx"&gt;devised a clever solution to it&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Mattias realized that SignedXml uses WebRequest.Create to help resolve what the reference points to.&amp;nbsp; And since WebRequest is extensible, he registered a custom class to handle cid URLs.&amp;nbsp; Although his specific example is for cid, this technique will work for any other protocol that the .NET Framework does not know how to handle out of the box.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=819912" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Cryptography/default.aspx">Cryptography</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/XML/default.aspx">XML</category></item><item><title>Adding SignatureProperties to SignedXml</title><link>http://blogs.msdn.com/shawnfa/archive/2005/11/03/488807.aspx</link><pubDate>Thu, 03 Nov 2005 23:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:488807</guid><dc:creator>shawnfa</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/shawnfa/comments/488807.aspx</comments><wfw:commentRss>http://blogs.msdn.com/shawnfa/commentrss.aspx?PostID=488807</wfw:commentRss><description>&lt;P&gt;One of the optional portions of the &lt;A href="http://www.w3.org/TR/xmldsig-core"&gt;W3C XML digital signature specification&lt;/A&gt; allows for a set of &lt;A href="http://www.w3.org/TR/xmldsig-core/#sec-SignatureProperties"&gt;SignatureProperties&lt;/A&gt; to be assigned to a signature.&amp;nbsp; SignatureProperties allow the signer to place some metadata into the signature itself, such as the time the signature was created and the name of the person creating the signature.&amp;nbsp; Since the XML digital signature specification does not lay out specific properties, you are free to create as many domain specific properties as you'd like.&amp;nbsp; Although the SignedXml class does not support this feature, it's easy enough to add on your own by deriving from the default SignedXml implementation.&lt;/P&gt;
&lt;P&gt;Signature properties exist as a&amp;nbsp;SignatureProperties element in the signature itself, embedded as a DataObject.&amp;nbsp; The signature's references contain a pointer to this element with a Type of&amp;nbsp; "http://www.w3.org/2000/02/xmldsig#SignatureProperty", as specified in the W3C spec.&amp;nbsp; The SignatureProperties element will contain as many SignatureProperty elements as needed.&amp;nbsp; Each SignatureProperty will have a Target pointing to the signature that we're creating and will contain arbitrary XML (which should be in a different namespace to be valid).&lt;/P&gt;
&lt;P&gt;In order to implement this, we'll first create a SignaturePropertiesSignedXml class which derives from SignedXml&amp;nbsp;and takes the typical XmlDocument constructor parameter, as well as an ID for the signature (which is needed for the SignatureProperty Target attribute), and the ID of the SignatureProperties element itself (which is needed for the reference to work).&amp;nbsp; We then use this information to create the SignatureProperties element, and place it into a DataObject.&amp;nbsp; Finally we create and add the reference to the SignatureProperties element:&lt;/P&gt;
&lt;P&gt;
&lt;DIV style="BORDER-RIGHT: black thin inset; PADDING-RIGHT: 1em; BORDER-TOP: black thin inset; PADDING-LEFT: 2em; FONT-SIZE: x-small; PADDING-BOTTOM: 1em; MARGIN: 1em 1em 1em 2em; BORDER-LEFT: black thin inset; PADDING-TOP: 1em; BORDER-BOTTOM: black thin inset; FONT-FAMILY: monospace; BACKGROUND-COLOR: lightgrey; WORD-WRAP: break-word"&gt;&lt;SPAN style="COLOR: green"&gt;/// &amp;lt;summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: green"&gt;/// XML signature class which enables SignatureProperties&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: green"&gt;/// &amp;lt;/summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;sealed&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;class&lt;/SPAN&gt;&amp;nbsp;SignaturePropertiesSignedXml&amp;nbsp;:&amp;nbsp;SignedXml&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;private&lt;/SPAN&gt;&amp;nbsp;XmlDocument&amp;nbsp;doc&amp;nbsp;=&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;private&lt;/SPAN&gt;&amp;nbsp;XmlElement&amp;nbsp;signaturePropertiesRoot&amp;nbsp;=&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;/// &amp;lt;summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;/// Create a SignedXml class which can have SignatureProperties&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;/// &amp;lt;/summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;/// &amp;lt;param name="doc"&amp;gt;XML document the signature belongs in&amp;lt;/param&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;/// &amp;lt;param name="signatureId"&amp;gt;ID of the signature to create&amp;lt;/param&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;/// &amp;lt;param name="propertiesId"&amp;gt;ID of the SignatureProperties to create&amp;lt;/param&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt;&amp;nbsp;SignaturePropertiesSignedXml(XmlDocument&amp;nbsp;doc,&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&amp;nbsp;signatureId,&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&amp;nbsp;propertiesId)&amp;nbsp;:&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;base&lt;/SPAN&gt;(doc)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;(String.IsNullOrEmpty(signatureId))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;throw&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt;&amp;nbsp;ArgumentException("signatureId cannot be empty",&amp;nbsp;"signatureId");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;(String.IsNullOrEmpty(propertiesId))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;throw&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt;&amp;nbsp;ArgumentException("propertiesId cannot be empty",&amp;nbsp;"propertiesId");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.doc&amp;nbsp;=&amp;nbsp;doc;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Signature.Id&amp;nbsp;=&amp;nbsp;signatureId;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;// create a root element to hold the properties&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;signaturePropertiesRoot&amp;nbsp;=&amp;nbsp;doc.CreateElement("SignatureProperties",&amp;nbsp;XmlDsigNamespaceUrl);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;signaturePropertiesRoot.SetAttribute("Id",&amp;nbsp;propertiesId);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;// create a data object for the properties to go into&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DataObject&amp;nbsp;signatureProperties&amp;nbsp;=&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt;&amp;nbsp;DataObject();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;signatureProperties.Data&amp;nbsp;=&amp;nbsp;signaturePropertiesRoot.SelectNodes(".");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AddObject(signatureProperties);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;// and add a reference to the data object&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Reference&amp;nbsp;propertiesRef&amp;nbsp;=&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt;&amp;nbsp;Reference("#"&amp;nbsp;+&amp;nbsp;propertiesId);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;propertiesRef.Type&amp;nbsp;=&amp;nbsp;"http://www.w3.org/2000/02/xmldsig#SignatureProperty";&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AddReference(propertiesRef);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Now that the constructor has done the work of setting up the signature properties, we'll need a simple method to add individual properties.&amp;nbsp; This is easily accomplished by taking the XML content of the property, creating a SignatureProperty element with a Target of the containing signature, and adding the input XML to the SignatureProperty:&lt;/P&gt;
&lt;P&gt;
&lt;DIV style="BORDER-RIGHT: black thin inset; PADDING-RIGHT: 1em; BORDER-TOP: black thin inset; PADDING-LEFT: 2em; FONT-SIZE: x-small; PADDING-BOTTOM: 1em; MARGIN: 1em 1em 1em 2em; BORDER-LEFT: black thin inset; PADDING-TOP: 1em; BORDER-BOTTOM: black thin inset; FONT-FAMILY: monospace; BACKGROUND-COLOR: lightgrey; WORD-WRAP: break-word"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;/// &amp;lt;summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;/// Add a signature property to the document&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;/// &amp;lt;/summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;/// &amp;lt;param name="content"&amp;gt;XML contents of the property&amp;lt;/param&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;void&lt;/SPAN&gt;&amp;nbsp;AddProperty(XmlElement&amp;nbsp;content)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;(content&amp;nbsp;==&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;throw&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt;&amp;nbsp;ArgumentNullException("content");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;(String.Compare(content.NamespaceURI,&amp;nbsp;XmlDsigNamespaceUrl)&amp;nbsp;==&amp;nbsp;0)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;throw&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt;&amp;nbsp;InvalidOperationException("Signature properties must not be in the XML Digital Signature namespace");&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;// wrap the content in a SignatureProperty element&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XmlElement&amp;nbsp;property&amp;nbsp;=&amp;nbsp;doc.CreateElement("SignatureProperty",&amp;nbsp;XmlDsigNamespaceUrl);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;property.SetAttribute("Target",&amp;nbsp;"#"&amp;nbsp;+&amp;nbsp;Signature.Id);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;property.AppendChild(content);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;signaturePropertiesRoot.AppendChild(property);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Finally, we need to override GetIdElement (see &lt;a href="http://blogs.msdn.com/shawnfa/archive/2004/04/05/108098.aspx"&gt;my previous post on doing this&lt;/A&gt; for more information), since the default GetIdElement implementation does not search DataObjects and we have a reference that points to our SignatureProperties which is contained within a DataObject.&amp;nbsp; In the override, we just check to see if we're searching for the signature properties, and if not fall back to default behavior.&lt;/P&gt;
&lt;P&gt;
&lt;DIV style="BORDER-RIGHT: black thin inset; PADDING-RIGHT: 1em; BORDER-TOP: black thin inset; PADDING-LEFT: 2em; FONT-SIZE: x-small; PADDING-BOTTOM: 1em; MARGIN: 1em 1em 1em 2em; BORDER-LEFT: black thin inset; PADDING-TOP: 1em; BORDER-BOTTOM: black thin inset; FONT-FAMILY: monospace; BACKGROUND-COLOR: lightgrey; WORD-WRAP: break-word"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;/// &amp;lt;summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;/// Get an element refered to by its ID&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;/// &amp;lt;/summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;/// &amp;lt;param name="doc"&amp;gt;XML document to search for the element in&amp;lt;/param&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;/// &amp;lt;param name="id"&amp;gt;element to search for&amp;lt;/param&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;/// &amp;lt;returns&amp;gt;Element with the given ID, null if it could not be found&amp;lt;/returns&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;public&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;override&lt;/SPAN&gt;&amp;nbsp;XmlElement&amp;nbsp;GetIdElement(XmlDocument&amp;nbsp;doc,&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;&amp;nbsp;id)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;(id&amp;nbsp;==&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;// see if this is the signature properties being referenced, otherwise fall back to default behavior&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;if&lt;/SPAN&gt;(String.Compare(id,&amp;nbsp;signaturePropertiesRoot.GetAttribute("Id"),&amp;nbsp;StringComparison.OrdinalIgnoreCase)&amp;nbsp;==&amp;nbsp;0)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt;&amp;nbsp;signaturePropertiesRoot;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;else&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;return&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;base&lt;/SPAN&gt;.GetIdElement(doc,&amp;nbsp;id);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;And that's it!&amp;nbsp; We can now pretty easily use this class to add metadata to the signature.&amp;nbsp; For example:&lt;/P&gt;
&lt;P&gt;
&lt;DIV style="BORDER-RIGHT: black thin inset; PADDING-RIGHT: 1em; BORDER-TOP: black thin inset; PADDING-LEFT: 2em; FONT-SIZE: x-small; PADDING-BOTTOM: 1em; MARGIN: 1em 1em 1em 2em; BORDER-LEFT: black thin inset; PADDING-TOP: 1em; BORDER-BOTTOM: black thin inset; FONT-FAMILY: monospace; BACKGROUND-COLOR: lightgrey; WORD-WRAP: break-word"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XmlDocument&amp;nbsp;doc&amp;nbsp;=&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt;&amp;nbsp;XmlDocument();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;doc.Load("order.xml");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SignaturePropertiesSignedXml&amp;nbsp;signer&amp;nbsp;=&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt;&amp;nbsp;SignaturePropertiesSignedXml(doc,&amp;nbsp;"orderSignature",&amp;nbsp;"signatureProperties");&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RSA&amp;nbsp;key&amp;nbsp;=&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt;&amp;nbsp;RSACryptoServiceProvider();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;signer.SigningKey&amp;nbsp;=&amp;nbsp;key;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;// create a timestamp property&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XmlElement&amp;nbsp;timestamp&amp;nbsp;=&amp;nbsp;doc.CreateElement("TimeStamp",&amp;nbsp;"http://www.example.org/#signatureProperties");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;timestamp.InnerText&amp;nbsp;=&amp;nbsp;DateTime.Now.ToUniversalTime().ToString();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;signer.AddProperty(timestamp);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: green"&gt;// create a signed by property&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XmlElement&amp;nbsp;signedBy&amp;nbsp;=&amp;nbsp;doc.CreateElement("SignedBy",&amp;nbsp;"http://www.example.org/#signatureProperties");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;signedBy.InnerText&amp;nbsp;=&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt;&amp;nbsp;WindowsPrincipal(WindowsIdentity.GetCurrent()).Identity.Name;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;signer.AddProperty(signedBy);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Reference&amp;nbsp;orderRef&amp;nbsp;=&amp;nbsp;&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt;&amp;nbsp;Reference("");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;orderRef.AddTransform(&lt;SPAN style="COLOR: blue"&gt;new&lt;/SPAN&gt;&amp;nbsp;XmlDsigEnvelopedSignatureTransform());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;signer.AddReference(orderRef);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;signer.ComputeSignature();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;doc.DocumentElement.AppendChild(signer.GetXml());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;doc.Save("order-signed.xml");&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Will produce a signature that contains the time and person who signed the document:&lt;/P&gt;
&lt;P&gt;
&lt;DIV style="BORDER-RIGHT: black thin inset; PADDING-RIGHT: 1em; BORDER-TOP: black thin inset; PADDING-LEFT: 2em; FONT-SIZE: x-small; PADDING-BOTTOM: 1em; MARGIN: 1em 1em 1em 2em; BORDER-LEFT: black thin inset; PADDING-TOP: 1em; BORDER-BOTTOM: black thin inset; FONT-FAMILY: monospace; BACKGROUND-COLOR: lightgrey; WORD-WRAP: break-word"&gt;&amp;nbsp;&amp;nbsp;&amp;lt;Signature&amp;nbsp;Id="orderSignature"&amp;nbsp;xmlns="http://www.w3.org/2000/09/xmldsig#"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;SignedInfo&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;CanonicalizationMethod&amp;nbsp;Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"&amp;nbsp;/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;SignatureMethod&amp;nbsp;Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"&amp;nbsp;/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Reference&amp;nbsp;URI="#signatureProperties"&amp;nbsp;Type="http://www.w3.org/2000/02/xmldsig#SignatureProperty"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestMethod&amp;nbsp;Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"&amp;nbsp;/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestValue&amp;gt;KfpRjNAGP47ZKX/RZ9hFEpKo9u8=&amp;lt;/DigestValue&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Reference&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Reference&amp;nbsp;URI=""&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Transforms&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Transform&amp;nbsp;Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"&amp;nbsp;/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Transforms&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestMethod&amp;nbsp;Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"&amp;nbsp;/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestValue&amp;gt;BPoz+CmKZyTATOhskqke3iOXmvA=&amp;lt;/DigestValue&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Reference&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/SignedInfo&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;SignatureValue&amp;gt;CmMm&amp;nbsp;...&amp;nbsp;JKU=&amp;lt;/SignatureValue&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Object&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;SignatureProperties&amp;nbsp;Id="signatureProperties"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;SignatureProperty&amp;nbsp;Target="#orderSignature"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;TimeStamp&amp;nbsp;xmlns="http://www.example.org/#signatureProperties"&amp;gt;11/3/2005&amp;nbsp;9:35:37&amp;nbsp;PM&amp;lt;/TimeStamp&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/SignatureProperty&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;SignatureProperty&amp;nbsp;Target="#orderSignature"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;SignedBy&amp;nbsp;xmlns="http://www.example.org/#signatureProperties"&amp;gt;REDMOND\ShawnFa&amp;lt;/SignedBy&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/SignatureProperty&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/SignatureProperties&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Object&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/Signature&amp;gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;To verify this signature you don't even have to use the custom SignaturePropertiesSignedXml&amp;nbsp;class -- since the SignatureProperties element is now a child of the XML document (since we made this an enveloped signature), the standard SignedXml class will be able to find it to verify the signature.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=488807" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Cryptography/default.aspx">Cryptography</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/XML/default.aspx">XML</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Windows/default.aspx">Windows</category></item><item><title>Hitting the Mailbag</title><link>http://blogs.msdn.com/shawnfa/archive/2004/12/14/301229.aspx</link><pubDate>Tue, 14 Dec 2004 21:27:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:301229</guid><dc:creator>shawnfa</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/shawnfa/comments/301229.aspx</comments><wfw:commentRss>http://blogs.msdn.com/shawnfa/commentrss.aspx?PostID=301229</wfw:commentRss><description>&lt;p&gt;I've gotten quite a few questions&amp;nbsp;from this blog&amp;nbsp;over the past several months.&amp;nbsp; And although I can't answer all of them, here's some quick answers to some of the more common ones.&amp;nbsp; If you do have more questions, its usually best to post them in the comments here or in the microsoft.public.dotnet.security newsgroup.&amp;nbsp; That way if I don't get to them, somebody else may see it and have an answer for you.&amp;nbsp; (It also prevents my spam filter from snagging them).&lt;/p&gt; &lt;p&gt;Anyway, on to the questions:&lt;/p&gt; &lt;blockquote&gt;Hi, &lt;br /&gt;&lt;br /&gt;I just wanted to know what is the purpose of FirstMatchCodeGroup? &lt;br /&gt;&lt;br /&gt;For instance one could have guessed that all_code from machine security level would be FirstMatchCodeGroup, but it is not the case. &lt;/blockquote&gt;&lt;br /&gt; &lt;p&gt;The FirstMatchCodeGroup is different from the standard UnionCodeGroup (which is what the default policy uses) in how it deals with child code groups.&amp;nbsp; UnionCodeGroup will merge the permission set associated with itself with the permission sets returned by all of its children code groups.&amp;nbsp; FirstMatchCodeGroup on the other hand merges its permission set with only the first child code group that matches the evidence being evaluated. &lt;p&gt;Since FirstMatchCodeGroup stops evaluating its children code groups after it finds one that matches the evidence, it's not what we would want to use for the default policy, where we want all the code groups to have a chance at determining the final permission grant. &lt;br /&gt; &lt;hr /&gt; &lt;blockquote&gt;My question is how can I sign an assembly I compile myself using the Microsoft.CSharp.Compiler? In an IDE situation, this would obviously be done with the AssemblyInfo.cs file. &lt;br /&gt;&lt;br /&gt;I realize I could use CompileAssemblyFromFileBatch and create essentially an AssemblyInfo.cs on the fly. This seems a bit cheesy, and I'd prefer a cleaner way if there is one.&lt;/blockquote&gt;&lt;br /&gt; &lt;p&gt;Well, the easiest answer to this is to emit a System.Reflection.AssemblyKeyFileAttribute or System.Reflection.AssemblyKeyNameAttribute into the class you're compiling.&amp;nbsp; On Whidbey, this will &lt;A href="http://blogs.msdn.com/shawnfa/archive/2004/04/15/114258.aspx"&gt;give you warning CS1699&lt;/a&gt;, which can be avoided by using the /keyfile or /keycontainer options in the CompilerParameters object you pass to the C# CodeDOM compiler. &lt;p&gt;Now, that being said, if you're signing assemblies on the fly you'll need access to a private key on the machine.&amp;nbsp; And if you're making security decisions based entirely upon that key, you're opening a security hole since any other application could also potentially find that key and sign themselves with it.&amp;nbsp; Once they've done that, they'll match your code groups and get any permissions you grant to that key. &lt;br /&gt; &lt;hr /&gt; &lt;blockquote&gt;I am trying hard to understand how to sign an xml file using a private key file. I have the private key on windows certificate store but I don't want to use the private key from the store. I can export it as pfx. But I don't know what to do next. Can you assist me on this? &lt;/blockquote&gt; &lt;p&gt;If you need to do this on v1.1 of the framework, you'll need to &lt;a title="" href="http://www.pinvoke.net/"&gt;P/Invoke&lt;/a&gt; to the &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/seccrypto/security/cryptography_functions.asp"&gt;Windows Cryptography API&lt;/a&gt; in order to load your certificate back into a cert store, and create an RSACryptoServiceProvider object around it by passing in CspParameters to the constructor which point to the correct key container.&amp;nbsp; Since you said you already have the key in the store it might be easier to just do this without exporting to PFX first. &lt;p&gt;With Whidbey, we've enhanced the X.509 certificate support available in the framework, and you can now open an X.509 certificate stored in a file into an X509Certificate2 object directly by passing in the path to the PFX file and a &lt;A href="http://blogs.msdn.com/shawnfa/archive/2004/05/27/143254.aspx"&gt;SecureString&lt;/a&gt; as a password.&amp;nbsp; Then you'll be able to use the PrivateKey property of the certificate to get the signing key.&amp;nbsp; For a sample of what this might look like, check out &lt;a href="http://msdn.microsoft.com/msdnmag/issues/04/11/XMLSignatures/#S18"&gt;the section on X.509 Support&lt;/a&gt;&amp;nbsp;in the &lt;a href="http://msdn.microsoft.com/msdnmag/issues/04/11/XMLSignatures"&gt;article&lt;/a&gt; Mike Downen and I wrote for &lt;a href="http://msdn.microsoft.com/msdnmag/issues/04/11/"&gt;November's MSDN magazine&lt;/a&gt;. &lt;br /&gt; &lt;hr /&gt; &lt;blockquote&gt;I've just found a very interesting blog post of yours: &lt;A href="http://blogs.msdn.com/shawnfa/archive/2004/04/14/113514.aspx"&gt;"Generating a Key from a Password" &lt;/a&gt;which is all about PasswordDeriveBytes and CryptDeriveKey.&lt;br /&gt;&lt;br /&gt;I'm trying to use this class, but there isn't any support for RipeMD-160 hash algorithm which I have to use in case to decrypt an 2-Key TripleDES encrypted message (the key has been derived from password with RipeMD-160).&lt;br /&gt;&lt;br /&gt;My question:&lt;br /&gt;How can I set directly the key for TripleDESCryptoServiceProvider without using the PasswordDeriveBytes class?&lt;/blockquote&gt;&lt;br /&gt; &lt;p&gt;The blog post mentioned in the question shows how to use two built in helper classes to generate a key from a password.&amp;nbsp; PasswordDeriveBytes uses the &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/cryptderivekey.asp"&gt;CryptDeriveKey&lt;/a&gt; algorithm exposed by CAPI or PBKDF1.&amp;nbsp; Whidbey introduces Rfc2898DeriveBytes, which uses PBKDF2 to generate a key from a password.&lt;/p&gt; &lt;p&gt;However, there are other ways to go about generating a key, and if you need to use RIPEMD-160, then you'll find that Whidbey also introduces support for the RIPEMD160 hash algorithm.&amp;nbsp; Depending on how you're key is to be generated, you'll probably have to do some variation of PBKDF2 substituting HMACRIPEMD160 for HMACSHA1.&lt;/p&gt; &lt;p&gt;Once you've done that, you'll have a byte array to use as a key.&amp;nbsp; You can then just set the Key property of TripleDESCryptoServiceProvider in&amp;nbsp;order to decrypt your ciphertext.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=301229" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Cryptography/default.aspx">Cryptography</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/XML/default.aspx">XML</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/CAS/default.aspx">CAS</category></item><item><title>I'm Published!</title><link>http://blogs.msdn.com/shawnfa/archive/2004/10/19/244597.aspx</link><pubDate>Tue, 19 Oct 2004 16:34:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:244597</guid><dc:creator>shawnfa</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/shawnfa/comments/244597.aspx</comments><wfw:commentRss>http://blogs.msdn.com/shawnfa/commentrss.aspx?PostID=244597</wfw:commentRss><description>The &lt;a href="http://msdn.microsoft.com/msdnmag/issues/04/11/"&gt;November 2004 issue of MSDN magazine&lt;/a&gt; is available online now, and it includes the first article I've ever had published.&amp;nbsp; I co-authored this month's Trustworthy Code article, &lt;a href="http://msdn.microsoft.com/msdnmag/issues/04/11/XMLSignatures/"&gt;Exchange Data More Securely with XML Digital Signatures and Encryption&lt;/a&gt; with Mike Downen, the CLR Security PM.&amp;nbsp; Time to head out to the local bookstore and pick up a stack of these ... :-)&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=244597" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Cryptography/default.aspx">Cryptography</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/XML/default.aspx">XML</category></item><item><title>.NET 1.0 SP 3 and .NET 1.1 SP 1 Released</title><link>http://blogs.msdn.com/shawnfa/archive/2004/09/02/224918.aspx</link><pubDate>Thu, 02 Sep 2004 21:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:224918</guid><dc:creator>shawnfa</dc:creator><slash:comments>23</slash:comments><comments>http://blogs.msdn.com/shawnfa/comments/224918.aspx</comments><wfw:commentRss>http://blogs.msdn.com/shawnfa/commentrss.aspx?PostID=224918</wfw:commentRss><description>&lt;p&gt;Today we pushed .NET 1.0 SP3 and .NET 1.1 SP1 onto Windows Update as a Critical Update.&amp;nbsp; You can also download the service packs from the MSDN download center.&amp;nbsp; Here's a brief review of what's new for security in each service pack:&lt;/p&gt; &lt;p&gt;.NET 1.0 SP3 (v1.0.3705.6018) [&lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=6978D761-4A92-4106-A9BC-83E78D4ABC5B&amp;amp;displaylang=en"&gt;download &lt;/a&gt;| &lt;a href="http://support.microsoft.com/?id=867461"&gt;complete changelist&lt;/a&gt;]&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://support.microsoft.com/?id=323683"&gt;323683&lt;/a&gt;: NTLM authentication is lost on every call &lt;/li&gt; &lt;li&gt;&lt;a href="http://support.microsoft.com/?id=321562"&gt;321562&lt;/a&gt;: FIX: Role-based authentication fails for users who belong to many groups &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;and these security related fixes that weren't from the CLR security team:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://support.microsoft.com/?id=324488"&gt;324488&lt;/a&gt;: Forms authentication and view state fail intermittently under heavy load &lt;/li&gt; &lt;li&gt;&lt;a href="http://support.microsoft.com/?id=327132"&gt;327132&lt;/a&gt;: FIX: PassportIdentity does not require secure PIN when security-enhanced authentication is requested &lt;/li&gt; &lt;li&gt;&lt;a href="http://support.microsoft.com/?id=327523"&gt;327523&lt;/a&gt;: Users can open Web pages without the correct NTFS permissions &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;.NET 1.1 SP1 (v1.1.4322.2032) [&lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=A8F5654F-088E-40B2-BBDB-A83353618B38&amp;amp;displaylang=en"&gt;download &lt;/a&gt;| &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=AE7EDEF7-2CB7-4864-8623-A1038563DF23&amp;amp;displaylang=en"&gt;Windows 2003 download &lt;/a&gt;| &lt;a href="http://support.microsoft.com/?kbid=867460"&gt;complete changelist&lt;/a&gt;]&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://support.microsoft.com/?id=836989"&gt;836989&lt;/a&gt;: FIX: A user receives a "security exception" error message while running user code that is based on the .NET Framework 1.1 in a partial trust environment &lt;/li&gt; &lt;li&gt;&lt;a href="http://support.microsoft.com/?id=828295"&gt;828295&lt;/a&gt;: FIX: Error Message: Security Exception: PermissionToken Index Does Not Match Index into m_unrestrictedPermSet &lt;/li&gt; &lt;li&gt;&lt;a href="http://support.microsoft.com/?id=839289"&gt;839289&lt;/a&gt;: FIX: The GC heap becomes corrupted when you use the .NET Framework System.Security.Cryptography.RSACryptoServiceProvider class &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=224918" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Cryptography/default.aspx">Cryptography</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/XML/default.aspx">XML</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/CAS/default.aspx">CAS</category></item><item><title>Using DecryptDocument with Super-Encrypted Data</title><link>http://blogs.msdn.com/shawnfa/archive/2004/07/21/190073.aspx</link><pubDate>Wed, 21 Jul 2004 18:31:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:190073</guid><dc:creator>shawnfa</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/shawnfa/comments/190073.aspx</comments><wfw:commentRss>http://blogs.msdn.com/shawnfa/commentrss.aspx?PostID=190073</wfw:commentRss><description>&lt;P&gt;The EncryptedXml class comes with a nice utility&amp;nbsp;method called DecryptDocument (For more information about using DecryptDocument check out my &lt;A href="http://blogs.msdn.com/shawnfa/archive/2003/11/14/57032.aspx"&gt;previous post introducing XML Encryption&lt;/A&gt;).&amp;nbsp; This method will decrypt all the EncryptedData elements it finds, assuming that it is able to figure out what key to use to perform the decryption with.&amp;nbsp; However, what happens if you use this method with some super encrypted data?&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.w3.org/TR/xmlenc-core/#sec-eg-Super-Encryption"&gt;Super encryption &lt;/A&gt;is defined in the &lt;A href="http://www.w3.org/TR/xmlenc-core/"&gt;XML Encryption standard &lt;/A&gt;as encrypting an EncryptedData element (providing that you encrypt the entirety of the element).&amp;nbsp; In other words, it's encrypting already encrypted data.&lt;/P&gt;
&lt;P&gt;The DecryptDocument method will decrypt all top-level EncryptedData elements, however if they are super-encrypted, it will not continue to loop over the document to decrypt the resulting EncryptedData.&amp;nbsp; If you want to fully decrypt a document containing super-encrypted data, you'll need to do this looping yourself.&amp;nbsp; (Or if you want to be sure that you've fully decrypted a document, and you can't be sure if it contains super encrypted data or not).&lt;/P&gt;
&lt;P&gt;The code to do this is very simple, you just need to keep calling DecryptDocument while EncryptedData elements still exist.&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;&lt;SPAN class=keyword&gt;while&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;GetElementsByTagName&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"EncryptedData"&lt;/SPAN&gt;,&amp;nbsp;EncryptedXml&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;XmlEncNamespaceUrl&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Count&amp;nbsp;&lt;SPAN class=operator&gt;&amp;gt;&lt;/SPAN&gt;&amp;nbsp;0&amp;nbsp;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;exml&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;DecryptDocument&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=190073" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Cryptography/default.aspx">Cryptography</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/XML/default.aspx">XML</category></item><item><title>Using the XSLT Transform with XML Signatures</title><link>http://blogs.msdn.com/shawnfa/archive/2004/05/19/135262.aspx</link><pubDate>Wed, 19 May 2004 19:33:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:135262</guid><dc:creator>shawnfa</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/shawnfa/comments/135262.aspx</comments><wfw:commentRss>http://blogs.msdn.com/shawnfa/commentrss.aspx?PostID=135262</wfw:commentRss><description>&lt;P&gt;One of the transforms that ships with the .Net framework is the XmlDsigXsltTransform, which implements the &lt;A href="http://www.w3.org/TR/xmldsig-core/#sec-XSLT"&gt;XSLT transform&lt;/A&gt; specified in the W3C recommendation. A few people have asked me to write a bit on how to use this transform, so here's a brief explanation and some sample code. This transform basically applies an XSL transform to the XML that will be signed, before the signature is computed, but after the reference has been resolved.&lt;/P&gt;
&lt;P&gt;To clarify that last point, lets say I want to sign some XML with an id of "myxml". Currently no elements in the XML I want to sign have this ID, but I do have some XSL that will transform the input XML into some output that contains a node with the myxml id. This won't work, because the Reference will search my document for the element with the myxml id before the transform is applied. Since it won't find it, the transform will never be applied. (Something like the above scenario could be accomplished by creating a reference to the entire document, then applying a transform chain that first included the XSLT transform followed by&amp;nbsp;an XPath one.)&lt;/P&gt;
&lt;P&gt;One of the quirks of the XmlDsigXsltTransform class is that there is no easy way to&amp;nbsp;programmatically set the XSL you'd like the transform to use. In order to create XSLT transforms, I use the following utility function, which takes as input the XSL you'd like the transform to apply.&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;&lt;SPAN class=comment&gt;/// &amp;lt;summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// Utility method to create an XSLT transform from a string of XSL&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;/summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;param name='xsl'&amp;gt;XSL to use in the transform&amp;lt;/param&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;returns&amp;gt;An XmlDsigXsltTransform that will apply the given XSL transform before signing&amp;lt;/returns&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=keyword&gt;public&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;static&lt;/SPAN&gt;&amp;nbsp;XmlDsigXsltTransform&amp;nbsp;CreateXsltTransform&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=keyword&gt;string&lt;/SPAN&gt;&amp;nbsp;xsl&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XmlDocument&amp;nbsp;doc&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;XmlDocument&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;LoadXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;xsl&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XmlDsigXsltTransform&amp;nbsp;xform&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;XmlDsigXsltTransform&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xform&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;LoadInnerXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;ChildNodes&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;return&lt;/SPAN&gt;&amp;nbsp;xform;&lt;BR&gt;} &lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;This method is easy to use. Simply pass it the XSL you want in your transform, and it will return you an XmlDsigXsltTransform object containing this XSL. It works by turning the XSL string into an XmlNodeList, and then calling LoadInnerXml on XmlDsigXsltTranform with this node list.&lt;/P&gt;
&lt;P&gt;Using the transform is done in the same manner as the other transforms. First you create a reference to the XML you wish to sign. Then attach the transform object to that reference's transform chain. Verification code is unchanged from the standard verification code, since the transform will be embedded in the signature that is produced. Here's some sample code that signs a simple XML document using a basic XSL transform&lt;/P&gt;
&lt;P&gt;&lt;div class='codeblock'&gt;
&lt;span class='comment'&gt;// transform that will be used before signing the document&lt;/span&gt;&lt;br/&gt;
&lt;span class='keyword'&gt;string&lt;/span&gt;&amp;nbsp;xsl&amp;nbsp;&lt;span class='operator'&gt;=&lt;/span&gt;&amp;nbsp;@&amp;quot;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class='operator'&gt;&amp;lt;&lt;/span&gt;xs&lt;span class='operator'&gt;:&lt;/span&gt;transform&amp;nbsp;xmlns&lt;span class='operator'&gt;:&lt;/span&gt;xs&lt;span class='operator'&gt;=&lt;/span&gt;&lt;span class='literal'&gt;'ht&lt;/span&gt;tp&lt;span class='operator'&gt;:&lt;/span&gt;//www.w3.org/1999/XSL/Transform' version='1.0'&amp;gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class='operator'&gt;&amp;lt;&lt;/span&gt;xs&lt;span class='operator'&gt;:&lt;/span&gt;template&amp;nbsp;match&lt;span class='operator'&gt;=&lt;/span&gt;&lt;span class='literal'&gt;'/'&lt;/span&gt;&lt;span class='operator'&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class='operator'&gt;&amp;lt;&lt;/span&gt;xs&lt;span class='operator'&gt;:&lt;/span&gt;apply&lt;span class='operator'&gt;-&lt;/span&gt;templates&lt;span class='operator'&gt;/&lt;/span&gt;&lt;span class='operator'&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class='operator'&gt;&amp;lt;&lt;/span&gt;&lt;span class='operator'&gt;/&lt;/span&gt;xs&lt;span class='operator'&gt;:&lt;/span&gt;template&lt;span class='operator'&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class='operator'&gt;&amp;lt;&lt;/span&gt;xs&lt;span class='operator'&gt;:&lt;/span&gt;template&amp;nbsp;match&lt;span class='operator'&gt;=&lt;/span&gt;&lt;span class='literal'&gt;'el&lt;/span&gt;ementToTransform&lt;span class='literal'&gt;'&amp;gt;
&lt;/span&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class='operator'&gt;&amp;lt;&lt;/span&gt;transformedElement&lt;span class='operator'&gt;/&lt;/span&gt;&lt;span class='operator'&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class='operator'&gt;&amp;lt;&lt;/span&gt;&lt;span class='operator'&gt;/&lt;/span&gt;xs&lt;span class='operator'&gt;:&lt;/span&gt;template&lt;span class='operator'&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class='operator'&gt;&amp;lt;&lt;/span&gt;&lt;span class='operator'&gt;/&lt;/span&gt;xs&lt;span class='operator'&gt;:&lt;/span&gt;transform&lt;span class='operator'&gt;&amp;gt;&lt;/span&gt;&lt;span class='string'&gt;&amp;quot;;&lt;br/&gt;&lt;br/&gt;// XML document to sign&lt;br/&gt;&lt;span class='keyword'&gt;string&lt;/span&gt; xml = @&amp;quot;&lt;/span&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class='operator'&gt;&amp;lt;&lt;/span&gt;xml&lt;span class='operator'&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class='operator'&gt;&amp;lt;&lt;/span&gt;elementToTranform&lt;span class='operator'&gt;/&lt;/span&gt;&lt;span class='operator'&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class='operator'&gt;&amp;lt;&lt;/span&gt;&lt;span class='operator'&gt;/&lt;/span&gt;xml&lt;span class='operator'&gt;&amp;gt;&lt;/span&gt;&lt;span class='string'&gt;&amp;quot;;&lt;br/&gt;XmlDocument doc = &lt;span class='keyword'&gt;new&lt;/span&gt; XmlDocument();&lt;br/&gt;doc.LoadXml(xml);&lt;br/&gt;&lt;br/&gt;&lt;span class='comment'&gt;// setup the signature as usual -- generally you'd have a known key&lt;br/&gt;// to sign with instead of producing a random one.&lt;/span&gt;&lt;br/&gt;RSA signingKey = &lt;span class='keyword'&gt;new&lt;/span&gt; RSACryptoServiceProvider();&lt;br/&gt;SignedXml signer = &lt;span class='keyword'&gt;new&lt;/span&gt; SignedXml(doc);&lt;br/&gt;signer.SigningKey = signingKey;&lt;br/&gt;&lt;br/&gt;&lt;span class='comment'&gt;// create a reference to the entire document&lt;/span&gt;&lt;br/&gt;Reference r = &lt;span class='keyword'&gt;new&lt;/span&gt; Reference(&amp;quot;&lt;/span&gt;&lt;span class='string'&gt;&amp;quot;);&lt;br/&gt;r.AddTransform(new XmlDsigEnvelopedSignatureTransform());&lt;br/&gt;r.AddTransform(CreateXsltTransform(xsl));&lt;br/&gt;signer.AddReference(r);&lt;br/&gt;&lt;br/&gt;&lt;span class='comment'&gt;// signature computation works as usual&lt;/span&gt;&lt;br/&gt;signer.ComputeSignature();&lt;br/&gt;doc.DocumentElement.AppendChild(signer.GetXml());&lt;/span&gt;
&lt;/div&gt;
&lt;/P&gt;
&lt;P&gt;After running this code, the signed XML looks like this:&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;&amp;lt;xml&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;elementToTransform /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;Signature xmlns="http://www.w3.org/2000/09/xmldsig#"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;SignedInfo&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Reference URI=""&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Transforms&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;xs:transform xmlns:xs="http://www.w3.org/1999/XSL/Transform" version="1.0"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;xs:template match="/"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;xs:apply-templates /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/xs:template&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;xs:template match="elementToTransform"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;transformedElement xmlns="" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/xs:template&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/xs:transform&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Transform&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Transforms&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestValue&amp;gt;lqgLQKa0...e66pmKI=&amp;lt;/DigestValue&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Reference&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/SignedInfo&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;SignatureValue&amp;gt;juQQvRyG...E7r1Y0E=&amp;lt;/SignatureValue&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/Signature&amp;gt;&lt;BR&gt;&amp;lt;/xml&amp;gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;One thing to notice here is that the output XML contains the original XML, not the version that would be produced when transformed by the XSL. Since the output also contains your XSL, whoever is verifying the signature can recompute the output. This is convenient, sine it means that your XSL doesn't have to produce XML (for instance, it could create HTML). However, if you don't want to share your XSL, then this may not be the transform for you. Instead, you might want to apply your XSL before computing the signature, in which case the XSL you use will not be available for anyone to see.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=135262" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Cryptography/default.aspx">Cryptography</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/XML/default.aspx">XML</category></item><item><title>xml:id and SignedXml</title><link>http://blogs.msdn.com/shawnfa/archive/2004/04/27/121487.aspx</link><pubDate>Tue, 27 Apr 2004 21:53:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:121487</guid><dc:creator>shawnfa</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/shawnfa/comments/121487.aspx</comments><wfw:commentRss>http://blogs.msdn.com/shawnfa/commentrss.aspx?PostID=121487</wfw:commentRss><description>&lt;P&gt;A few weeks back, I &lt;A href="http://blogs.msdn.com/shawnfa/archive/2004/04/05/108098.aspx"&gt;posted&lt;/A&gt;&amp;nbsp;about customizing how &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemsecuritycryptographyxmlsignedxmlclasstopic.asp"&gt;SignedXml&lt;/A&gt;&amp;nbsp;searches for XML elements identified by a reference to an ID.&amp;nbsp; By default, SignedXml searches for elements with an attribute named Id that has the given value.&lt;/P&gt;
&lt;P&gt;Recently, the &lt;A href="http://www.w3.org/"&gt;W3C&lt;/A&gt; has come up with a working draft for &lt;A href="http://www.w3.org/TR/2004/WD-xml-id-20040407/"&gt;xml:id version 1.0&lt;/A&gt;.&amp;nbsp; xml:id is meant to be a uniform way for XML elements to be uniquely identified.&amp;nbsp; How it works is relatively simple.&amp;nbsp; Elements simply add an attribute named id, with a namespace prefix of xml, and give it a unique value.&amp;nbsp; For instance:&lt;/P&gt;
&lt;P&gt;&amp;lt;element xml:id='myElem'/&amp;gt;&lt;/P&gt;
&lt;P&gt;The xml prefix is a special prefix, and it should be mapped to the URI http://www.w3.org/XML/1998/namespace, according to the &lt;A href="http://www.w3.org/TR/REC-xml-names/"&gt;Namespaces in XML recommendation&lt;/A&gt;.&amp;nbsp; Before xml:id, the only attributes defined in the xml namespace were xml:lang,&amp;nbsp;xml:space, and xml:base.&lt;/P&gt;
&lt;P&gt;As a more realistic example than the one I posted in my earlier blog entry, I've written an extension to the SignedXml class which allows for nodes to be signed given their xml:id.&amp;nbsp;&amp;nbsp;I've also made&amp;nbsp;the complete source code to the &lt;A href="http://blogs.msdn.com/shawnfa/articles/121456.aspx"&gt;XmlIdSignedXml class available&lt;/A&gt;.&amp;nbsp; (With the standard disclaimers that Microsoft is not responsible if this code destroys your data, eats your dinner, or kicks your puppy when you're not looking.)&lt;/P&gt;
&lt;P&gt;The class is pretty simple, providing only one new property to the SignedXml class.&amp;nbsp; This property, a boolean called Strict, allows you to specify what the class should do if there's not a valid xml:id available.&amp;nbsp; If Strict is set to true, then the search will fail.&amp;nbsp; However, if Strict is set to false, then the default SignedXml id search is done.&amp;nbsp; In either case, xml:id's trump the default search.&amp;nbsp; XmlIdSignedXml also provides a constant that specifies the namespace URI that the xml prefix should map to.&amp;nbsp; (Although you'll never need this, since the System.Xml classes will provide this mapping for you).&lt;/P&gt;
&lt;P&gt;All of the interesting code is found in the GetIdElement override.&amp;nbsp; After validating its parameters, this method sets up an XmlNamespaceManager that maps the xml prefix to the URI specified in the W3C's specs.&amp;nbsp; Then the value to search for is quoted, in single quotes if it contains a double quote, and in double quotes if it contains a single quote.&amp;nbsp; Searching for an id that contains both single and double quotes is forbidden.&lt;/P&gt;
&lt;P&gt;The XPath query //*[@xml:id='idValue'] is used to get all the nodes that match the given xml id.&amp;nbsp; Since the xml:id recommendation specifically requires that ID's be unique within the document, matching more than one node will cause XmlIdSignedXml to throw an InvalidOperationException.&amp;nbsp; Assuming it finds only one match, this is returned as the result.&amp;nbsp; If no matches are found, then the behavior depends on the setting of the Strict property.&amp;nbsp; By default, Strict is set to false, so XmlIdSignedXml will revert back to the SignedXml semantics.&lt;/P&gt;
&lt;P&gt;Signing with this code works exactly the same as signing with a standard SignedXml object.&amp;nbsp; Remember that when validating documents signed by reference to xml:id, you must use an instance of the XmlIdSignedXml class, otherwise the validation will fail.&amp;nbsp; If you'd like some sample code to perform the signing / verification, check out my previous post on &lt;A href="http://blogs.msdn.com/shawnfa/archive/2004/04/05/108098.aspx"&gt;Searching for Custom IDs&lt;/A&gt;, or &lt;A href="http://blogs.msdn.com/shawnfa/archive/2004/01/22/61779.aspx"&gt;More Secure XML Digital Signatures&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;When using this class, XML that looks like this:&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;&amp;lt;xml&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;signed xml:id='tag1'&amp;gt;Signed Data&amp;lt;/signed&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;unsigned xml:id='tag2'&amp;gt;Unsigned Data&amp;lt;/unsigned&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;signed xml:id='tag3'&amp;gt;More Signed Data&amp;lt;/signed&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;signed id='tag4'&amp;gt;Signed with default processing&amp;lt;/signed&amp;gt;&lt;BR&gt;&amp;lt;/xml&amp;gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Will create a signature similar to the following:&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;&amp;lt;Signature xmlns="http://www.w3.org/2000/09/xmldsig#"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;SignedInfo&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Reference URI="#tag1"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestValue&amp;gt;feqM2k2kXyxPyXsKDgV8dsh74fE=&amp;lt;/DigestValue&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Reference&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Reference URI="#tag3"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestValue&amp;gt;VjjjaTwSg/OU6z3wOHoTa7gEnFM=&amp;lt;/DigestValue&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Reference&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Reference URI="#tag4"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestValue&amp;gt;bbKNmp7e3JFUDLpNdNGucke/g6o=&amp;lt;/DigestValue&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Reference&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/SignedInfo&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;SignatureValue&amp;gt;KAtTJfRQ ... hQUGA+Y=&amp;lt;/SignatureValue&amp;gt;&lt;BR&gt;&amp;lt;/Signature&amp;gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=121487" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Cryptography/default.aspx">Cryptography</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/XML/default.aspx">XML</category></item><item><title>Using XPath to Sign Specific XML</title><link>http://blogs.msdn.com/shawnfa/archive/2004/04/07/109386.aspx</link><pubDate>Thu, 08 Apr 2004 00:25:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:109386</guid><dc:creator>shawnfa</dc:creator><slash:comments>13</slash:comments><comments>http://blogs.msdn.com/shawnfa/comments/109386.aspx</comments><wfw:commentRss>http://blogs.msdn.com/shawnfa/commentrss.aspx?PostID=109386</wfw:commentRss><description>&lt;P&gt;In my &lt;A href="http://blogs.msdn.com/shawnfa/archive/2004/04/05/108098.aspx"&gt;last posting&lt;/A&gt;, I promised to write about a more general purpose way of selecting specific XML to sign. Although the technique I presented in the last post will work, it requires a custom class derived from SignedXml, and will not work unless both the signer and the verifier have access to, and use, that class. In order to have signatures validate by users who don't have your implementation of SignedXml (or don't even use the .NET XML digital signature mechanism at all), XPath is a better choice when initially signing a document.&lt;/P&gt;
&lt;P&gt;Using XPath to sign specific parts of the XML document involves adding an XPath transform to a reference in your signature. In .NET, the XPath transform is represented by the XmlDsigXPathTransform class. This transform will take an XPath expression, and act as a filter, selecting the nodes you want to sign while removing the others.&lt;/P&gt;
&lt;P&gt;The XPath transform works a little differently than you might expect. Instead of specifying an XPath expression that will result in the nodes you wish to sign, you specify a filter. Internally, the transform first takes the document that the reference points to and runs the following XPath expression on it:&lt;/P&gt;
&lt;DIV class=codeblock&gt;(//. | //@* | //namespace::*)&lt;/DIV&gt;
&lt;P&gt;This selects all of the nodes in the reference, and gets them into a node list. Each element in this node list is then evaluated against the XPath expression specified in the transform. If the result is true, the node is included in the signature, false excludes it.&lt;/P&gt;
&lt;P&gt;When working with the XmlDsigXPathTransform, I use a utility method that creates the transform for me. The reason is that the class does not actually contain a way to programmaticly set the XPath that will be used. Instead, the only way to accomplish this is to create the XML form of the transform and load it into the object. The utility method is shown here.&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;&lt;SPAN class=comment&gt;/// &amp;lt;summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// Create an XPath transform&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;/summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;param name='xpath'&amp;gt;XPath expression for the transform&amp;lt;/param&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;returns&amp;gt;XPath transform that filters according to the given XPath expression&amp;lt;/returns&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=keyword&gt;private&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;static&lt;/SPAN&gt;&amp;nbsp;XmlDsigXPathTransform&amp;nbsp;CreateXPathTransform&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=keyword&gt;string&lt;/SPAN&gt;&amp;nbsp;xpath&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=comment&gt;// create the XML that represents the transform&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XmlDocument&amp;nbsp;doc&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;XmlDocument&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XmlElement&amp;nbsp;xpathElem&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;CreateElement&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"XPath"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xpathElem&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;InnerText&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;xpath;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XmlDsigXPathTransform&amp;nbsp;xform&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;XmlDsigXPathTransform&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xform&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;LoadInnerXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;xpathElem&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;SelectNodes&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"."&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;return&lt;/SPAN&gt;&amp;nbsp;xform;&lt;BR&gt;} &lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;In order to use this transform, first create a reference to the entire document being signed (by passing in an empty string). Then call AddTransform on the reference, passing in the XPath transform. The following sample signs nodes named "signed", and ignores all others. Note the use of the ancestor-or-self:: axis in the query. If this weren't used, than any nodes that were children of the signed nodes wouldn't be signed. Most times this isn't the intention of the signer, and could lead to security holes.&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;&lt;SPAN class=comment&gt;// load the XML that will be signed&lt;/SPAN&gt;&lt;BR&gt;XmlDocument&amp;nbsp;doc&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;XmlDocument&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;LoadXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;xml&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;SignedXml&amp;nbsp;signer&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;SignedXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;doc&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;// create a reference to the whole document&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;// but sign only tags named signed&lt;/SPAN&gt;&lt;BR&gt;Reference&amp;nbsp;r&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;Reference&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;""&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;r&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AddTransform&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;CreateXPathTransform&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"ancestor-or-self::signed"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;signer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AddReference&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;r&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;signer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;SigningKey&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;RSACryptoServiceProvider&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;signer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;ComputeSignature&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;; &lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;In order to sign a document similar to the one from yesterday's post (where I'm signing based on "_Id" attributes, I would use code similar to this:&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;Reference&amp;nbsp;r&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;Reference&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;""&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;r&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AddTransform&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;CreateXPathTransform&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"ancestor-or-self::*[@_Id=signme'"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;signer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AddReference&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;r&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;; &lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Applying a signature containing that reference to this XML:&lt;/P&gt;
&lt;p&gt;&lt;div class='codeblock'&gt;
&amp;lt;xml&amp;gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;unimportant&amp;gt;Unsigned Data&amp;lt;/unimportant&amp;gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;important _Id='signme'&amp;gt;Signed Data&amp;lt;/important&amp;gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;vital _Id='signme'&amp;gt;More Signed Data&amp;lt;/vital&amp;gt;&lt;br/&gt;
&amp;nbsp;&amp;nbsp;&amp;lt;interesting&amp;gt;More Unsigned Data&amp;lt;/interesting&amp;gt;&lt;br/&gt;
&amp;lt;/xml&amp;gt;&lt;br/&gt;&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;Will result in a signature similar to the following:&lt;/p&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;&amp;lt;Signature xmlns="http://www.w3.org/2000/09/xmldsig#"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;SignedInfo&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Reference URI=""&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Transforms&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;XPath&amp;gt;ancestor-or-self::*[@_Id='signme']&amp;lt;/XPath&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Transform&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Transforms&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestValue&amp;gt;zGdeF6BumSVUfORJxKHfXvNQyG8=&amp;lt;/DigestValue&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Reference&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/SignedInfo&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;SignatureValue&amp;gt;meG/yZGO . . . vkjbOIU=&amp;lt;/SignatureValue&amp;gt;&lt;BR&gt;&amp;lt;/Signature&amp;gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;The code to verify this signature is exactly the same as the code to verify a standard signature. You'll notice that the output XML contains both the transform itself and the XPath used in the transform. This lets the validating code reconstruct the transform object without any special instructions from you.&lt;/P&gt;
&lt;P&gt;One note on using this to sign multiple nodes. If you need to use more than one XPath expression, then you need to use more than one reference. Adding multiple transforms to the same reference will actually just chain them together, making the second one filter the results of the first one. Two XPath transforms on separate references will work as expected, with each transform having access to all of the nodes in the document.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=109386" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Cryptography/default.aspx">Cryptography</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/XML/default.aspx">XML</category></item><item><title>Searching for Custom ID Tags With Signed XML</title><link>http://blogs.msdn.com/shawnfa/archive/2004/04/05/108098.aspx</link><pubDate>Tue, 06 Apr 2004 00:56:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:108098</guid><dc:creator>shawnfa</dc:creator><slash:comments>16</slash:comments><comments>http://blogs.msdn.com/shawnfa/comments/108098.aspx</comments><wfw:commentRss>http://blogs.msdn.com/shawnfa/commentrss.aspx?PostID=108098</wfw:commentRss><description>&lt;P&gt;Last week, I blogged about &lt;A href="http://blogs.msdn.com/shawnfa/archive/2004/03/31/105137.aspx"&gt;using references to sign only specific parts of an XML document.&lt;/A&gt; The biggest limitation with doing this is that you must refer to the nodes that are being signed by ID, which for v1.1 and 1.0 of the framework was given by an attribute named "Id". The problem there is that the Id attribute may already have another use in your schema, and you cannot reuse them for creating node names. Another problem that may come up is that the XML being signed may be generated by a tool or program, and it's not possible for you to add Id tags. Whidbey reduces this limitation somewhat by also allowing "id" and "ID", but the fundamental problem still exists.&lt;/P&gt;
&lt;P&gt;Recently, this problem cropped&amp;nbsp;for one of our customers&amp;nbsp;who&amp;nbsp;was having a problem getting signed XML to work in his environment. Their application was trying to sign XML generated by a Java program. The Java application had generated ids by using "_Id" attributes, making it impossible to sign with an id based reference.&amp;nbsp; If the only problem was creating a signature, then there would be an easy workaround.&amp;nbsp; However, the C# portion of the program was trying to verify the signature that the Java application had created, and could not resolve references to the _id elements.&lt;/P&gt;
&lt;P&gt;So, how did we solve this problem? Actually with a very clever solution from one of the other members of the security team. Nodes that are being referred to by ID are resolved in the GetIdElement method of the SignedXml class. By subclassing SignedXml and overriding this method, its possible to create your own id node resolver. I'll show a sample here that allows ids prefixed with underscores to be resolved by XML signature engine.&lt;/P&gt;
&lt;P&gt;Although this sample relies on a similar ID attribute mechanism for identifying nodes, there's nothing stopping you from creating a fancier system. Just as long as you always return exactly one XmlElement representing the specified node, or null if the node could not be found. The best use of this technique is to enable interop scenarios. If you're trying to do this simply to have more fine-grained control over which nodes your reference identifies, I'll show a better technique later this week.&lt;/P&gt;
&lt;H2&gt;Implementation&lt;/H2&gt;
&lt;P&gt;The only method that I'll need to override is the GetIdElement method. In addition, I'll provide a constructor that takes an XmlDocument, and passes it along to the SignedXml constructor. I've also defined an array of strings, which represent the attributes that I'll allow to identify nodes. Here's the code:&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;&lt;SPAN class=keyword&gt;public&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;class&lt;/SPAN&gt;&amp;nbsp;CustomIdSignedXml&amp;nbsp;&lt;SPAN class=operator&gt;:&lt;/SPAN&gt;&amp;nbsp;SignedXml&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;private&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;static&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;readonly&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;string&lt;/SPAN&gt;&lt;SPAN class=operator&gt;[&lt;/SPAN&gt;&lt;SPAN class=operator&gt;]&lt;/SPAN&gt;&amp;nbsp;idAttrs&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;string&lt;/SPAN&gt;&lt;SPAN class=operator&gt;[&lt;/SPAN&gt;&lt;SPAN class=operator&gt;]&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=string&gt;"_id"&lt;/SPAN&gt;,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=string&gt;"_Id"&lt;/SPAN&gt;,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=string&gt;"_ID"&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;public&lt;/SPAN&gt;&amp;nbsp;CustomIdSignedXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;XmlDocument&amp;nbsp;doc&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=operator&gt;:&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;base&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;doc&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;return&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;public&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;override&lt;/SPAN&gt;&amp;nbsp;XmlElement&amp;nbsp;GetIdElement&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;XmlDocument&amp;nbsp;doc,&amp;nbsp;&lt;SPAN class=keyword&gt;string&lt;/SPAN&gt;&amp;nbsp;id&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=comment&gt;// check to see if it's a standard ID reference&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XmlElement&amp;nbsp;idElem&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;base&lt;/SPAN&gt;&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;GetIdElement&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;doc,&amp;nbsp;id&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;if&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;idElem&amp;nbsp;&lt;SPAN class=operator&gt;!=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;null&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;return&lt;/SPAN&gt;&amp;nbsp;idElem;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=comment&gt;// if not, search for custom ids&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;foreach&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=keyword&gt;string&lt;/SPAN&gt;&amp;nbsp;idAttr&amp;nbsp;&lt;SPAN class=keyword&gt;in&lt;/SPAN&gt;&amp;nbsp;idAttrs&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;idElem&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;SelectSingleNode&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"//*[@"&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=operator&gt;+&lt;/SPAN&gt;&amp;nbsp;idAttr&amp;nbsp;&lt;SPAN class=operator&gt;+&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=string&gt;"=\""&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=operator&gt;+&lt;/SPAN&gt;&amp;nbsp;id&amp;nbsp;&lt;SPAN class=operator&gt;+&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=string&gt;"\"]"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;as&lt;/SPAN&gt;&amp;nbsp;XmlElement;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;if&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;idElem&amp;nbsp;&lt;SPAN class=operator&gt;!=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;null&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;break&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;return&lt;/SPAN&gt;&amp;nbsp;idElem;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;} &lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;So what's going on here? At the beginning of the method, I call the default GetIdElement, and if that found a match, return that node. This allows my resolver to continue working with "Id" nodes. Since I do this at the beginning of the method, it also makes it so that nodes with the standard id attributes take precedence over nodes with my custom attributes. Next, I loop over my custom attributes, and perform an XPath query, looking for the first node that has a custom attribute with the correct value. Since I quit searching for nodes as soon as I find a match, the order that the attributes appear in the idAttrs array is also the order of precedence. For instance a reference to #idnode when run over the following XML,&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;&amp;lt;root&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;node1 _id='idnode'/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;node2 Id='idnode'/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;node3 _ID='idnode'/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;node4 _ID='otherref'/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;node5 _id='otherref'/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;node6 _id='otherref'/&amp;gt;&lt;BR&gt;&amp;lt;/root&amp;gt; &lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;will match node2, since IDs found by the SignedXml class have the highest precedence. A reference to #otheref will match node5, since _id occurs before _ID in my search and only the first match is returned.&lt;/P&gt;
&lt;P&gt;Searching for the id nodes is done with the SelectSingleNode method, passing an XPath query customized for the name of the id attribute and the ID I'm looking for. For instance, when searching for nodes with an _ID attribute that would match a reference to #myref, the XPath would be:&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;//*[@_Id="myref"]&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;H2&gt;Signing With Custom IDs&lt;/H2&gt;
&lt;P&gt;Creating a signature that would use the custom id resolver is done in exactly the same way that normal signatures containing id references are done. The only difference is that instead of creating a SignedXml object, you create an instance of the custom ID resolver. Since GetIdElement is virtual, you can even assign the instance into a SignedXml object, and everything will still work as expected. This helps to enable scenarios where the code that actually computes signatures lives in a different method that you don't control, however you do have write access to the SignedXml object they use.&lt;/P&gt;
&lt;P&gt;Enough talk, here's some sample code showing a signature being created with my custom _Id resolver. The XML that I'm going to sign is:&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;&amp;lt;xml&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;tag Id='tag1'/&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;tag _Id='tag2'/&amp;gt;&lt;BR&gt;&amp;lt;/xml&amp;gt; &lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;And the code that computes the signature is:&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;XmlDocument&amp;nbsp;doc&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;XmlDocument&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;LoadXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;xml&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;SignedXml&amp;nbsp;signer&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;CustomIdSignedXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;doc&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;signer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AddReference&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;Reference&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"#tag1"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;signer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AddReference&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;Reference&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"#tag2"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;signer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;SigningKey&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;RSACryptoServiceProvider&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;signer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;ComputeSignature&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;Console&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;WriteLine&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;signer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;GetXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;OuterXml&lt;SPAN class=operator&gt;)&lt;/SPAN&gt; &lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;This produces a signature similar to the following:&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;&amp;lt;Signature xmlns="http://www.w3.org/2000/09/xmldsig#"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;SignedInfo&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Reference URI="#tag1"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestValue&amp;gt;/dsJPkLT3QydsHQ1dpmMLPEIbRo=&amp;lt;/DigestValue&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Reference&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Reference URI="#tag2"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestValue&amp;gt;AWY9mgt5Z+jRSS+CevluG77gFC8=&amp;lt;/DigestValue&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Reference&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/SignedInfo&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;SignatureValue&amp;gt;JVXWblnT . . . 55rZ7zc=&amp;lt;/SignatureValue&amp;gt;&lt;BR&gt;&amp;lt;/Signature&amp;gt; &lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;H2&gt;Verifying the Signature&lt;/H2&gt;
&lt;P&gt;Remember that since the standard SignedXml class will have no idea how to resolve references to custom ID nodes, so verification will also need an instance of the custom signed xml class. However, aside from this difference verification works exactly as you would expect&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;SignedXml&amp;nbsp;verifier&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;CustomIdSignedXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;doc&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;verifier&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;LoadXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;signer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;GetXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;SPAN class=keyword&gt;if&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;verifier&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;CheckSignature&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;signer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;SigningKey&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;WriteLine&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"Signature verified"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;SPAN class=keyword&gt;else&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;WriteLine&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"Invalid signature"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=108098" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Cryptography/default.aspx">Cryptography</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/XML/default.aspx">XML</category></item><item><title>Signing Specific XML With References</title><link>http://blogs.msdn.com/shawnfa/archive/2004/03/31/105137.aspx</link><pubDate>Wed, 31 Mar 2004 23:15:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:105137</guid><dc:creator>shawnfa</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/shawnfa/comments/105137.aspx</comments><wfw:commentRss>http://blogs.msdn.com/shawnfa/commentrss.aspx?PostID=105137</wfw:commentRss><description>&lt;P&gt;I've previously &lt;A href="http://blogs.msdn.com/shawnfa/archive/2004/01/22/61779.aspx"&gt;blogged&lt;/A&gt; 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.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;&amp;lt;xml&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;signed id='tag1'&amp;gt;Signed Data&amp;lt;/signed&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;unsigned id='tag2'&amp;gt;Unsigned Data&amp;lt;/unsigned&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;signed id='tag3'&amp;gt;More Signed Data&amp;lt;/signed&amp;gt;&lt;BR&gt;&amp;lt;/xml&amp;gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;XmlDocument&amp;nbsp;doc&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;XmlDocument&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;LoadXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;xml&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;SignedXml&amp;nbsp;signer&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;SignedXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;doc&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;signer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AddReference&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;Reference&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"#tag1"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;signer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AddReference&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;Reference&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"#tag3"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;signer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;SigningKey&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;RSACryptoServiceProvider&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;signer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;ComputeSignature&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;; &lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;This produces signed XML that looks like the following:&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;&amp;lt;Signature xmlns="http://www.w3.org/2000/09/xmldsig#"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;SignedInfo&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Reference URI="#tag1"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestValue&amp;gt;6kGyfacrtc02JR23FNmcoR+OKzc=&amp;lt;/DigestValue&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Reference&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Reference URI="#tag3"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;DigestValue&amp;gt;DtoiDLz3qs7wLwN8Y9A8J5Qpb/I=&amp;lt;/DigestValue&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Reference&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/SignedInfo&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;SignatureValue&amp;gt;SQN+6HlM . . . NqvsN04=&amp;lt;/SignatureValue&amp;gt;&lt;BR&gt;&amp;lt;/Signature&amp;gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;Verifying this signature works exactly the same as verifying the signature over an entire document.&amp;nbsp; You'll also notice that even if you modify the value of the unsigned element, the signature still verifies.&lt;/P&gt;
&lt;P&gt;
&lt;DIV class=codeblock&gt;&lt;SPAN class=comment&gt;// modify the unsigned element -- the signature should still verify&lt;/SPAN&gt;&lt;BR&gt;XmlElement&amp;nbsp;unsignedElem&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;SelectSingleNode&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"//xml/unsigned"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;as&lt;/SPAN&gt;&amp;nbsp;XmlElement;&lt;BR&gt;unsignedElem&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;InnerText&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=string&gt;"Modified Data"&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;SignedXml&amp;nbsp;verifier&amp;nbsp;&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt;&amp;nbsp;SignedXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;doc&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;verifier&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;LoadXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;signer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;GetXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=keyword&gt;if&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;verifier&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;CheckSignature&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;signer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;SigningKey&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;WriteLine&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"Pass"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;SPAN class=keyword&gt;else&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;WriteLine&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"Fail"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;; &lt;/DIV&gt;
&lt;P&gt;&lt;b&gt;Updated:&lt;/b&gt; 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.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=105137" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Cryptography/default.aspx">Cryptography</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/XML/default.aspx">XML</category></item><item><title>What's New in XML For Whidbey</title><link>http://blogs.msdn.com/shawnfa/archive/2004/03/30/104425.aspx</link><pubDate>Wed, 31 Mar 2004 02:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:104425</guid><dc:creator>shawnfa</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/shawnfa/comments/104425.aspx</comments><wfw:commentRss>http://blogs.msdn.com/shawnfa/commentrss.aspx?PostID=104425</wfw:commentRss><description>&lt;P&gt;The new &lt;A href="http://msdn.microsoft.com/xml/"&gt;XML Developer Center &lt;/A&gt;on MSDN has a nice &lt;A href="http://msdn.microsoft.com/xml/default.aspx?pull=/library/en-us/dnxml/html/SysXMLVS05.asp"&gt;article&lt;/A&gt; about the new XML features in &lt;A href="http://msdn.microsoft.com/vs2005"&gt;Whidbey&lt;/A&gt;.&amp;nbsp; The top 10 list is:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/xml/default.aspx?pull=/library/en-us/dnxml/html/SysXMLVS05.asp#sysxml_topic13"&gt;Performance&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/xml/default.aspx?pull=/library/en-us/dnxml/html/SysXMLVS05.asp#sysxml_topic12"&gt;XPathEditableNavigator, an Updatable Cursor&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/xml/default.aspx?pull=/library/en-us/dnxml/html/SysXMLVS05.asp#sysxml_topic11"&gt;The XPathDocument as a Better DOM&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/xml/default.aspx?pull=/library/en-us/dnxml/html/SysXMLVS05.asp#sysxml_topic10"&gt;Easier XPath Queries with Namespaces&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/xml/default.aspx?pull=/library/en-us/dnxml/html/SysXMLVS05.asp#sysxml_topic9"&gt;Security&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/xml/default.aspx?pull=/library/en-us/dnxml/html/SysXMLVS05.asp#sysxml_topic8"&gt;The XQuery Language&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/xml/default.aspx?pull=/library/en-us/dnxml/html/SysXMLVS05.asp#sysxml_topic7"&gt;XmlReader and XmlWriter Usability&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/xml/default.aspx?pull=/library/en-us/dnxml/html/SysXMLVS05.asp#sysxml_topic6"&gt;Universal Type Support and Conversion&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/xml/default.aspx?pull=/library/en-us/dnxml/html/SysXMLVS05.asp#sysxml_topic5"&gt;XML Standards Support by Default&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/xml/default.aspx?pull=/library/en-us/dnxml/html/SysXMLVS05.asp#sysxml_topic4"&gt;Static Creation Methods on XmlReader and XmlWriter&lt;/A&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=104425" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/shawnfa/archive/tags/XML/default.aspx">XML</category></item><item><title>Creating a SecurityElement from XML</title><link>http://blogs.msdn.com/shawnfa/archive/2004/02/24/79598.aspx</link><pubDate>Wed, 25 Feb 2004 02:25:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:79598</guid><dc:creator>shawnfa</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/shawnfa/comments/79598.aspx</comments><wfw:commentRss>http://blogs.msdn.com/shawnfa/commentrss.aspx?PostID=79598</wfw:commentRss><description>&lt;P&gt;Most of the .NET security system can be serialized out to XML, and knows how to deserialize itself from an XML stream. This would seem to make it easy to create security objects (such as PermissionSet's) from XML documents, or maybe use an XPath query or XSLT transform on one of these objects. However, instead of using standard System.Xml classes to represent our XML data, the security system uses its own XML class, System.Security.SecurityElement.&lt;/P&gt;
&lt;P&gt;There are several reasons for this, including the fact that security code must execute very quickly, and is executed quite frequently. The overhead of a full-fledged XML parser would be too much. Even if you accept the fact that we need a lightweight security XML object, we can't even provide utility methods on SecurityElement to convert back and forth System.Xml objects, since the CAS code lives in mscorlib.dll, and mscorlib cannot take a dependency on external DLL's. (Think of what would happen if mscorlib depended on System.Xml.dll, and System.Xml.dll depended on mscorlib ...). As if this weren't enough, there are at least 3 distinct XML parsers in v1.1 of the framework (System.Xml, SecurityElement, and a lightweight parser in mscoree.dll which handles parsing .config files ... this was actually optimized to be able to fit into no more than two pages of memory). Whidbey will be adding yet another parser to handle parsing ClickOnce manifests.&lt;/P&gt;
&lt;P&gt;With all these different XML representations, commonly people need to convert between them. Since you'll most likely never be handling the mscoree representation, I'll show some sample code for converting between System.Xml and SecurityElement.&lt;/P&gt;
&lt;H2&gt;Converting SecurityElement to XmlElement&lt;/H2&gt;
&lt;P&gt;Going from SecurityElement to XmlElement is relatively easy, since everything expressable within the SecurityElement object model is also available in System.Xml. All that needs to be done is to make a new XmlElement with a tag matching the SecurityElement, create any XmlAttributes on the element, and copy over any inner text that might exist. This needs to be done recursively for each child node of the SecurityElement.&lt;/P&gt;
&lt;DIV class=codeblock&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// Convert a security element XML tree into an System.Xml XML tree&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;/summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;param name="se"&amp;gt;security element at the root of the tree&amp;lt;/param&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;returns&amp;gt;an XML Node at the root of the System.Xml Tree&amp;lt;/returns&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=keyword&gt;public&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;static&lt;/SPAN&gt; XmlNode SecurityElementToXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;SecurityElement se&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;return&lt;/SPAN&gt; SecurityElementToXmlInternal&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;se, &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; XmlDocument&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// Convert a security element XML tree into an System.Xml XML tree&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;/summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;param name="se"&amp;gt;security element at the root of the tree&amp;lt;/param&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;param name="doc"&amp;gt;XML Document context to create new XML nodes from&amp;lt;/param&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;returns&amp;gt;an XML Node at the root of the System.Xml Tree&amp;lt;/returns&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=keyword&gt;private&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;static&lt;/SPAN&gt; XmlNode SecurityElementToXmlInternal&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;SecurityElement se, XmlDocument doc&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XmlNode root &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;CreateElement&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;se&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Tag&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;if&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;se&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Text &lt;SPAN class=operator&gt;!=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;null&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;root&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AppendChild&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;CreateTextNode&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;se&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Text&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;if&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;se&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Attributes &lt;SPAN class=operator&gt;!=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;null&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;foreach&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=keyword&gt;string&lt;/SPAN&gt; attr &lt;SPAN class=keyword&gt;in&lt;/SPAN&gt; se&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Attributes&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Keys&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XmlAttribute xmlAttr &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;CreateAttribute&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;attr&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xmlAttr&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Value &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=keyword&gt;string&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;se&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Attributes&lt;SPAN class=operator&gt;[&lt;/SPAN&gt;attr&lt;SPAN class=operator&gt;]&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;root&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Attributes&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Append&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;xmlAttr&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;if&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;se&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Children &lt;SPAN class=operator&gt;!=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;null&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;foreach&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;SecurityElement child &lt;SPAN class=keyword&gt;in&lt;/SPAN&gt; se&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Children&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;root&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AppendChild&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;SecurityElementToXmlInternal&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;child, doc&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;return&lt;/SPAN&gt; root;&lt;BR&gt;}&lt;BR&gt;&lt;/DIV&gt;
&lt;H2&gt;Converting from XmlElement to SecurityElement&lt;/H2&gt;
&lt;P&gt;Going from System.Xml to SecurityElement is a little more tricky, since SecurityElement cannot express every bit of valid XML. The only XML nodes in the SecurityElement object model are elements, attributes, and text, so anything in an XmlDocument that does not fall into one of these three categories cannot be converted. The following code performs the conversion by looking at each child of the XmlElement, and deciding what to do based on its type. If the child is an XmlElement, it recursively calls itself and appends the child node to the new SecurityElement's children. If it's an attribute, the attribute is added to the security element, and text is added as the inner text of the new SecurityElement. Comments are skipped over, and an InvalidOperationException is thrown if any other type of element is discovered.&lt;/P&gt;
&lt;DIV class=codeblock&gt;&lt;SPAN class=comment&gt;/// &amp;lt;summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// Convert an XML Element into a SecurityElement&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;/summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;remarks&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;///&amp;nbsp;&amp;nbsp;Throws an InvalidOperationException if there are nodes that are not&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// of type XmlElement, XmlAttribute or XmlText in the tree.&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;/remarks&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;param name="xml"&amp;gt;xml element to convert&amp;lt;/param&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;returns&amp;gt;SecurityElement representation&amp;lt;/returns&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=keyword&gt;public&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;static&lt;/SPAN&gt; SecurityElement XmlToSecurityElement&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;XmlNode xml&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SecurityElement root &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; SecurityElement&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;xml&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Name&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;foreach&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;XmlNode node &lt;SPAN class=keyword&gt;in&lt;/SPAN&gt; xml&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;ChildNodes&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;if&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;node &lt;SPAN class=keyword&gt;is&lt;/SPAN&gt; XmlElement&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;root&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AddChild&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;XmlToSecurityElement&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;XmlElement&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;node&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;else&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;if&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;node &lt;SPAN class=keyword&gt;is&lt;/SPAN&gt; XmlText&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;root&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Text &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;XmlText&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;node&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Value;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;else&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;if&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;node &lt;SPAN class=keyword&gt;is&lt;/SPAN&gt; XmlComment&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;continue&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;else&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;throw&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; InvalidOperationException&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"Cannot convert XML with nodes of type "&lt;/SPAN&gt; &lt;SPAN class=operator&gt;+&lt;/SPAN&gt; node&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;GetType&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;foreach&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;XmlAttribute attr &lt;SPAN class=keyword&gt;in&lt;/SPAN&gt; xml&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Attributes&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;root&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AddAttribute&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;attr&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Name, attr&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Value&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;return&lt;/SPAN&gt; root;&lt;BR&gt;}&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;Given this function, one nice piece of utility code to convert a string of XML into a SecurityElement (which is not possible with the current object model) is:&lt;/P&gt;
&lt;DIV class=codeblock&gt;&lt;SPAN class=comment&gt;/// &amp;lt;summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// Convert an XML string to a security element&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;/summary&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;param name="xml"&amp;gt;string of XML to convert&amp;lt;/param&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;/// &amp;lt;returns&amp;gt;SecurityElement that the string represents&amp;lt;/returns&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=keyword&gt;public&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;static&lt;/SPAN&gt; SecurityElement StringToSecurityElement&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=keyword&gt;string&lt;/SPAN&gt; xml&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;XmlDocument doc &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; XmlDocument&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;LoadXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;xml&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=keyword&gt;return&lt;/SPAN&gt; XmlToSecurityElement&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;DocumentElement&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;}&lt;BR&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=79598" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/XML/default.aspx">XML</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/CAS/default.aspx">CAS</category></item><item><title>Using XML Encryption With CipherReferences, Part 2 - Remote Data</title><link>http://blogs.msdn.com/shawnfa/archive/2004/02/18/75853.aspx</link><pubDate>Wed, 18 Feb 2004 22:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:75853</guid><dc:creator>shawnfa</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/shawnfa/comments/75853.aspx</comments><wfw:commentRss>http://blogs.msdn.com/shawnfa/commentrss.aspx?PostID=75853</wfw:commentRss><description>&lt;P&gt;Earlier this week, I &lt;A href="http://blogs.msdn.com/shawnfa/archive/2004/02/16/74454.aspx"&gt;posted&lt;/A&gt; about using cipher references to refer to data stored in the same document. Today I'll use the same technique, but instead of storing the encrypted data elsewhere in the document, I'm going to store it on a seperate server. Of course, I'll be using the familiar order.xml sample to work with. The samples all assume that I have a webserver with a shared root folder on \\webserver\wwwroot, which is accessed at http://webserver. &lt;/P&gt;
&lt;H2&gt;Encrypting the data&lt;/H2&gt;
&lt;P&gt;Encrypting the data to store on a server is very similar to the encryption step for storing locally. However, since my data will be in a seperate file, and not embedded in XML, I've decided to not base64 encode it. Instead, I'll just write the bytes out to a binary file.&lt;/P&gt;
&lt;DIV class=codeblock&gt;&lt;SPAN class=comment&gt;// load the data&lt;/SPAN&gt;&lt;BR&gt;XmlDocument doc &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; XmlDocument&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Load&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"order.xml"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;XmlElement paymentElem &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;SelectSingleNode&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"/order/payment"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;as&lt;/SPAN&gt; XmlElement;&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;// encrypt&lt;/SPAN&gt;&lt;BR&gt;SymmetricAlgorithm key &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; RijndaelManaged&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;SPAN class=keyword&gt;byte&lt;/SPAN&gt;&lt;SPAN class=operator&gt;[&lt;/SPAN&gt;&lt;SPAN class=operator&gt;]&lt;/SPAN&gt; cryptData &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; EncryptedXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;EncryptData&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;Encoding&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;UTF8.GetBytes(paymentElem.OuterXml), key&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;// store the encrypted data on a web server&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=keyword&gt;using&lt;/SPAN&gt;&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;FileStream writer &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; FileStream&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;@"\\webserver\wwwroot\orders\order.bin", FileMode&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Create&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;writer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Write&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;cryptData, 0, cryptData&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Length&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;writer&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Close&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;}&lt;BR&gt;&lt;/DIV&gt;
&lt;H2&gt;Creating the EncryptedData&lt;/H2&gt;
&lt;P&gt;Creating a cipher reference for this data will be much easier than it was when I was referencing the local data. Since the local data was base64 encoded, and stored within an XML element, I needed to apply a transform chain. However, the data this time is stored as raw bytes, so no transforms are needed. This means I can just use the CipherReference constructor to point to the URI where the data is stored, without having to hand-craft the CipherReference XML myself. Once I have the CipherReference, setting up the EncryptedData object is relativly straight forward, and very similar to the standard XML encryption case.&lt;/P&gt;
&lt;DIV class=codeblock&gt;&lt;SPAN class=comment&gt;// create a cipher reference to the stored data, and setup the encrypted data&lt;/SPAN&gt;&lt;BR&gt;CipherReference cr &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; CipherReference&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"http://webserver/orders/order.bin"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;EncryptedData encrypted &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; EncryptedData&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;encrypted&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;CipherData &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; CipherData&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;cr&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;encrypted&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;KeyInfo&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AddClause&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; KeyInfoName&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"key"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;encrypted&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;EncryptionMethod &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; EncryptionMethod&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;EncryptedXml&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;XmlEncAES256Url);&lt;BR&gt;EncryptedXml&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;ReplaceElement&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;paymentElem, encrypted, &lt;SPAN class=keyword&gt;false&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;This creates the following XML:&lt;/P&gt;
&lt;DIV class=codeblock&gt;&amp;lt;order&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;purchase&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;item quantity="1"&amp;gt;Def Leppard: Pyromania&amp;lt;/item&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;item quantity="1"&amp;gt;Ozzy Osbourne: Goodbye to Romance&amp;lt;/item&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/purchase&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;shipping&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;to&amp;gt;Shawn Farkas&amp;lt;/to&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;street&amp;gt;5 21st Street&amp;lt;/street&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;city&amp;gt;Seattle&amp;lt;/city&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;state&amp;gt;WA&amp;lt;/state&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;zip&amp;gt;98000&amp;lt;/zip&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/shipping&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;KeyName&amp;gt;key&amp;lt;/KeyName&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/KeyInfo&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;CipherData&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;CipherReference URI="http://webserver/orders/order.bin" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/CipherData&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/EncryptedData&amp;gt;&lt;BR&gt;&amp;lt;/order&amp;gt;&lt;/DIV&gt;
&lt;H2&gt;Decrypting&lt;/H2&gt;Decrypting this document works almost exactly the same as with standard XML encryption, however there is one difference. Since the XML decryption engine will have to go to an arbitrary website and download some data, this could expose a security hole (depending on how much you trust the XML document). In order to establish the trust-level for the specific document, there is a property, DocumentEvidence, on the EncryptedXml class which represents the evidence for this document. It is up to you to set this property properly. For instance, if the document came from the internet, you might add Zone evidence for the Internet zone, and perhaps some site evidence for the site it came from. Under the default security policy, that would restrict the document from getting data from any website but the same one it came from. In this instance, since http://webserver looks like an intranet site, I'm going to setup LocalIntranet and Site evidence. 
&lt;DIV class=codeblock&gt;EncryptedXml decryptXml &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; EncryptedXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;doc&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;decryptXml&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;DocumentEvidence &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; Evidence&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;decryptXml&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;DocumentEvidence&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AddHost&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; Zone&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;SecurityZone&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Intranet&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;decryptXml&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;DocumentEvidence&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AddHost&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; Site&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"webserver"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;decryptXml&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AddKeyNameMapping&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"key"&lt;/SPAN&gt;, key&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;decryptXml&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;DecryptDocument&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;Once again, after this is run, the XML document contained in the doc variable is exactly the same as the original order XML.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=75853" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Cryptography/default.aspx">Cryptography</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/XML/default.aspx">XML</category></item><item><title>Using XML Encryption With CipherReferences, Part 1 - Local Data</title><link>http://blogs.msdn.com/shawnfa/archive/2004/02/16/74454.aspx</link><pubDate>Tue, 17 Feb 2004 00:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:74454</guid><dc:creator>shawnfa</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/shawnfa/comments/74454.aspx</comments><wfw:commentRss>http://blogs.msdn.com/shawnfa/commentrss.aspx?PostID=74454</wfw:commentRss><description>&lt;P&gt;Most users of encrypted&amp;nbsp;XML will encrypt their data and embed the resulting cipher value directly into the EncryptedData element, using a CipherValue tag. However, XML encryption also supports the use of CipherReferences, which allow you to place the encrypted XML outside of the EncryptedData element, or even outside of the current document. Getting this to work is a little tricky, so I'll provide an example here of referring to encrypted data that is stored elsewhere in the current document. Once again, I'll be using my order XML to work with.&lt;/P&gt;
&lt;H2&gt;Encrypting the data&lt;/H2&gt;
&lt;P&gt;The first step is to encrypt the data into an array of bytes. This is easily accomplished in the same way as I showed in my &lt;A href="http://blogs.msdn.com/shawnfa/archive/2003/11/14/57032.aspx"&gt;previous discussion of XML Encryption&lt;/A&gt;.&lt;/P&gt;
&lt;DIV class=codeblock&gt;&lt;SPAN class=comment&gt;// load the data&lt;/SPAN&gt;&lt;BR&gt;XmlDocument doc &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; XmlDocument&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Load&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"order.xml"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;XmlElement paymentElem &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;SelectSingleNode&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"/order/payment"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;as&lt;/SPAN&gt; XmlElement;&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;// encrypt&lt;/SPAN&gt;&lt;BR&gt;SymmetricAlgorithm key &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; RijndaelManaged&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;SPAN class=keyword&gt;byte&lt;/SPAN&gt;&lt;SPAN class=operator&gt;[&lt;/SPAN&gt;&lt;SPAN class=operator&gt;]&lt;/SPAN&gt; cryptData &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; EncryptedXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;EncryptData&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;Encoding&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;UTF8.GetBytes(paymentElem.OuterXml), key&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;Now that the data is encrypted, it must be inserted into the document. To do this, I will create a new XML node (called encrypted), with a specific ID (payment), that I will use in the cipher reference to poin the XML decryption engine to the correct location. In order to store the binary data in XML, I must first transform it into a base64 string.&lt;/P&gt;
&lt;DIV class=codeblock&gt;&lt;SPAN class=comment&gt;// setup the element pointed to by the ciper reference&lt;/SPAN&gt;&lt;BR&gt;XmlElement cryptElem &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;CreateElement&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"encrypted"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;cryptElem&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;InnerText &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; Convert&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;ToBase64String(cryptData);&lt;BR&gt;XmlAttribute idAttr &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;CreateAttribute&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"id"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;idAttr&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Value &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=string&gt;"payment"&lt;/SPAN&gt;;&lt;BR&gt;cryptElem&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Attributes&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;Append&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;idAttr&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;DocumentElement&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AppendChild&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;cryptElem&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;/DIV&gt;
&lt;H2&gt;Creating the CipherReference&lt;/H2&gt;
&lt;P&gt;Unfortunately, there is no easy way to create a cipher reference programatically. In order to create the cipher reference, you must first create the XML that represents the reference, and then load that XML into a CipherReference object. There are a couple of things to look out for when creating this XML. You must include a transform chain that takes as input the node that the reference points to, and returns as output the byte array of encrypted data. In the above example, I transformed the byte array into a base 64 string, then placed it into the body of an XML element. In order to convert this back into a byte array, I must first use an XPath expression to get the value out of the XML element, and then use a base64 transform to convert the string into raw bytes. This transform chain is shown in the given XML. The other interesting part of the CipherReference XML is that the URI must be set to "#&lt;I&gt;id&lt;/I&gt;", where &lt;I&gt;id&lt;/I&gt; is the ID given to the XML element holding the encrypted data (in this case "payment").&lt;/P&gt;
&lt;DIV class=codeblock&gt;&lt;SPAN class=comment&gt;// Create a CipherReference to refer to the data in the /order/encrypted element&lt;/SPAN&gt;&lt;BR&gt;CipherReference cr &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; CipherReference&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;XmlDocument reference &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; XmlDocument&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=comment&gt;// note: make sure the appropriate transforms are added to convert the encrypted data back to bytes&lt;/SPAN&gt;&lt;BR&gt;reference&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;LoadXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@"&amp;lt;CipherReference URI&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&lt;SPAN class=literal&gt;'#p&lt;/SPAN&gt;ayment&lt;SPAN class=literal&gt;'&amp;gt; &lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&lt;SPAN class=operator&gt;&amp;lt;&lt;/SPAN&gt;Transforms xmlns&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&lt;SPAN class=literal&gt;'ht&lt;/SPAN&gt;tp&lt;SPAN class=operator&gt;:&lt;/SPAN&gt;&lt;SPAN class=comment&gt;//www.w3.org/2001/04/xmlenc#'&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=operator&gt;&amp;lt;&lt;/SPAN&gt;Transform xmlns&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&lt;SPAN class=literal&gt;'ht&lt;/SPAN&gt;tp&lt;SPAN class=operator&gt;:&lt;/SPAN&gt;&lt;SPAN class=comment&gt;//www.w3.org/2000/09/xmldsig#'&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Algorithm&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&lt;SPAN class=literal&gt;'ht&lt;/SPAN&gt;tp&lt;SPAN class=operator&gt;:&lt;/SPAN&gt;&lt;SPAN class=comment&gt;//www.w3.org/TR/1999/REC-xpath-19991116'&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=operator&gt;&amp;lt;&lt;/SPAN&gt;XPath&lt;SPAN class=operator&gt;&amp;gt;&lt;/SPAN&gt;self&lt;SPAN class=operator&gt;:&lt;/SPAN&gt;&lt;SPAN class=operator&gt;:&lt;/SPAN&gt;text&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=operator&gt;/&lt;/SPAN&gt;XPath&lt;SPAN class=operator&gt;&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=operator&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=operator&gt;/&lt;/SPAN&gt;Transform&lt;SPAN class=operator&gt;&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=operator&gt;&amp;lt;&lt;/SPAN&gt;Transform xmlns&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&lt;SPAN class=literal&gt;'ht&lt;/SPAN&gt;tp&lt;SPAN class=operator&gt;:&lt;/SPAN&gt;&lt;SPAN class=comment&gt;//www.w3.org/2000/09/xmldsig#'&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Algorithm&lt;SPAN class=operator&gt;=&lt;/SPAN&gt;&lt;SPAN class=literal&gt;'ht&lt;/SPAN&gt;tp&lt;SPAN class=operator&gt;:&lt;/SPAN&gt;&lt;SPAN class=comment&gt;//www.w3.org/2000/09/xmldsig#base64'/&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&lt;SPAN class=operator&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=operator&gt;/&lt;/SPAN&gt;Transforms&lt;SPAN class=operator&gt;&amp;gt;&lt;/SPAN&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN class=operator&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN class=operator&gt;/&lt;/SPAN&gt;CipherReference&lt;SPAN class=operator&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN class=string&gt;");&lt;BR&gt;cr.LoadXml(reference.DocumentElement);&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/DIV&gt;
&lt;H2&gt;Creating an EncryptedData object from the CipherReference&lt;/H2&gt;
&lt;P&gt;Next, an EncryptedData object must be created from the CipherReference. This step is very similar to the standard XML encryption. The only notable difference is that CipherData is created with a CipherReference instead of a CipherValue. Note that the encryption key and method must still be setup properly. Once I've constructed the EncryptedXml object, I replace the payment element with it.&lt;/P&gt;
&lt;DIV class=codeblock&gt;&lt;SPAN class=comment&gt;// Create the EncryptedData object from the cipher reference&lt;/SPAN&gt;&lt;BR&gt;EncryptedData encrypted &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; EncryptedData&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;encrypted&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;CipherData &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; CipherData&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;cr&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;encrypted&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;KeyInfo&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AddClause&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; KeyInfoName&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"key"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;encrypted&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;EncryptionMethod &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; EncryptionMethod&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;EncryptedXml&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;XmlEncAES256Url);&lt;BR&gt;EncryptedXml&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;ReplaceElement&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;paymentElem, encrypted, &lt;SPAN class=keyword&gt;false&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;This creates XML that looks like:&lt;/P&gt;
&lt;DIV class=codeblock&gt;&amp;lt;order&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;purchase&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;item quantity="1"&amp;gt;Def Leppard: Pyromania&amp;lt;/item&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;item quantity="1"&amp;gt;Ozzy Osbourne: Goodbye to Romance&amp;lt;/item&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/purchase&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;shipping&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;to&amp;gt;Shawn Farkas&amp;lt;/to&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;street&amp;gt;5 21st Street&amp;lt;/street&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;city&amp;gt;Seattle&amp;lt;/city&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;state&amp;gt;WA&amp;lt;/state&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;zip&amp;gt;98000&amp;lt;/zip&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/shipping&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;EncryptedData xmlns="http://www.w3.org/2001/04/xmlenc#"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;KeyName&amp;gt;key&amp;lt;/KeyName&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/KeyInfo&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;CipherData&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;CipherReference URI="#payment"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Transforms&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Transform&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xmlns="http://www.w3.org/2000/09/xmldsig#"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;XPath&amp;gt;self::text()&amp;lt;/XPath&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Transform&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;Transform&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Algorithm="http://www.w3.org/2000/09/xmldsig#base64"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xmlns="http://www.w3.org/2000/09/xmldsig#" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/Transforms&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/CipherReference&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/CipherData&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/EncryptedData&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;encrypted id="payment"&amp;gt;65ZxnnE3&amp;nbsp;&lt;i&gt;...&lt;/i&gt;&amp;nbsp;wRtm+A==&amp;lt;/encrypted&amp;gt;&lt;BR&gt;&amp;lt;/order&amp;gt;&lt;/DIV&gt;
&lt;H2&gt;Decrypting&lt;/H2&gt;
&lt;P&gt;Decrypting a document with a cipher reference works exactly the same as decrypting the document with the cipher value embedded in the encrypted data. All that has to be done is create an EncryptedXml object for the document, setup the key name, and call DecryptDocument. I also remove the cipher data from the resulting document, since DecryptDocument will only remove the EncryptedData. 
&lt;DIV class=codeblock&gt;EncryptedXml decryptXml &lt;SPAN class=operator&gt;=&lt;/SPAN&gt; &lt;SPAN class=keyword&gt;new&lt;/SPAN&gt; EncryptedXml&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;doc&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;decryptXml&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;AddKeyNameMapping&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"key"&lt;/SPAN&gt;, key&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;decryptXml&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;DecryptDocument&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;DocumentElement&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;RemoveChild&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;doc&lt;SPAN class=operator&gt;.&lt;/SPAN&gt;SelectSingleNode&lt;SPAN class=operator&gt;(&lt;/SPAN&gt;&lt;SPAN class=string&gt;"/order/encrypted[@id='payment']"&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;&lt;SPAN class=operator&gt;)&lt;/SPAN&gt;;&lt;BR&gt;&lt;BR&gt;&lt;/DIV&gt;
&lt;P&gt;After running the decryption code over the encrypted XML, the resulting XML is exactly the same as the original, unencrypted order.xml. In my next post, I'll show how to use CipherReferences to refer to encrypted data not even in the same document as the EncryptedData tag.&lt;/P&gt;&lt;/I&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=74454" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Security/default.aspx">Security</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/Cryptography/default.aspx">Cryptography</category><category domain="http://blogs.msdn.com/shawnfa/archive/tags/XML/default.aspx">XML</category></item></channel></rss>