using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
// Also, add a reference to System.Security.dll
// Load the signed data
XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;
doc.Load("data-signed.xml");
// Find the Signature element in the document
XmlNamespaceManager nsm = new XmlNamespaceManager(new NameTable());
nsm.AddNamespace("dsig", SignedXml.XmlDsigNamespaceUrl);
XmlElement sigElt = (XmlElement)doc.SelectSingleNode(
"//dsig:Signature", nsm);
// Load the signature for verification
SignedXml sig = new SignedXml(doc);
sig.LoadXml(sigElt);
// Verify the signature, assume the public key part of the
// signing key is in the key variable
if (sig.CheckSignature(key))
Console.WriteLine("Signature verified");
else
Console.WriteLine("Signature not valid");
图5 验证一个信封签名
您已经了解了如何创建和验证包封式签名,它们很常用并且在对整个XML文档进行签名时很方便,而且XML签名标准还使您可以通过在Reference元素中指定不同的URI对其他数据进行签名。因此,让我们接下来考察一下不同类型的引用。
除了包封式引用(其URI属性为空字符串的Reference元素)以外,在XML签名标准中还定义了其他两个宽泛类型的引用:对分离数据的引用以及通过ID对XML数据进行的引用。分离数据位于包含签名的XML文档的外部,这些引用可以指向另外一个XML文档或任何其他类型的资源。当您在一个签名中对多个资源(例如,一个XML文档以及由该文档引用的其他一些文件)进行签名时,通常会使用该类型的引用。下面的XML代码片段显示了分离引用的一个示例:
为了使用Framework中的类来创建分离引用,只需在创建引用对象时将该引用的URI设置为资源的URI,然后 将该引用添加到签名中,如下所示:
// Create a Reference to detached data, assume a SignedXml object in sig
Reference refr = new Reference("http://dotnet.chinaitlab.com/UploadFiles_6597/200608/20060808155829128.jpg");
sig.AddReference(refr);
通过ID对XML数据进行的引用指向包含签名的文档内部或签名本身内部的XML。对于这些引用,签名引擎寻找其ID属性与引用中的URI匹配(不包括#)的元素。以下为一个基于ID的引用的示例:
如果ID为“myData”的元素位于包含签名的文档中,则该引用是完整的,并且签名引擎将在处理该签名时找到它。您通常使用该类型的引用将签名的作用范围限制到示例文档的特定部分。例如,在文档处理应用程序中,审阅者通常只对他审阅的XML文档部分(而不是整个文档)进行签名。该标准还允许您向Object元素中的签名添加任意数据。Object元素的XML看起来类似于以下代码行:
要创建基于ID的引用(该引用指向包含签名的文档中已经存在的元素),请添加如下所示的代码:
// Create a Reference to XML data in the containing document,
// assume a SignedXml object in sig
Reference refr = new Reference("#myData");
sig.AddReference(refr);
如果基于ID的引用指向了签名中的一个Object元素,则除了添加该引用以外,还必须向签名中添加一个DataObject,如刚才显示的代码中所示。数据对象可以包含您传入的任何XML。
// Adds a DataObject with an Id of "#myData" to the signature, assume a
// SignedXml object in sig, and xml data of type XmlNodeList in data
DataObject dobj = new DataObject();
dobj.Id = "myData"; // Note: no #
dobj.Data = data; // XML Data of the Object
sig.AddObject(dobj);
您通常使用指向Object元素的引用来对有关签名的元数据进行签名,例如,签名者的唯一标识符或有关该签名的其他一些信息。

