转换
转换通过允许您在生成引用的数据的哈希值之前修改该数据,使您可以对已签名的内容进行更多的控制。例如,信封式签名转换在对XML文档进行签名之前会移除Signature节点。
引用可以指定任何数量的转换,这些转换按照在Transforms元素中指定的顺序而做用。.NET Framework中的类除了支持我们前面提到的信封式签名转换以外,还支持下列转换:- 任何规范化算法都可以用作转换。
- 通过Base64转换可以对Base64编码数据进行解码。
- 通过XSLT转换,可以在对XML数据进行签名之前,向其应用XSLT样式表。要应用的XSLT样式表被指定为Transform元素下的XML。
- 通过XPath转换可以用XPath表达式筛选XML数据。
XPath表达式被指定为Transform元素下的XPath元素的文本内容。需要注意的是,XPath转换充当筛选器,而不是充当在作为输入传递的XML中选择节点的手段。该转换针对作为输入传递给该转换的每个节点计算XPath表达式,结果被转换为布尔值。输入节点将被考虑以便传递计算,并且如果计算的结果为true,则输入节点将被包含在转换的输出中。考虑转换的以下XML输入:
<a>
<b>Some data</b>
<c>More data</c>
</a>
<d>
<b>Even more data</b>
</d>
假设我们只希望选择“b”节点进行签名。带有XPath表达式“ancestor-or-self::b”的XPath转换将返回以下节点集(它正是我们所需要的):
<b>Some data</b>
<b>Even more data</b>
该XPath表达式的Transform元素看起来类似于下面的代码片段:
<Transform
Algorithm="http://www.w3c.org/TR/1999/REC-xpath-19991116"
>
<XPath>ancestor-or-self::b</XPath>
</Transform>
要在签名时以编程方式创建转换,请创建某个转换对象的实例,适当设置它的属性,并且将其添加到它所应用于的引用。以下示例将上一个示例中使用的XPath转换添加到某个引用中,以便创建转换:
// Add an XPath transform to a reference.
// Assume a Reference object in refr
XmlDocument doc = new XmlDocument();
doc.LoadXml("ancestor-or-self::b");
XmlDsigXPathTransform xptrans = new XmlDsigXPathTransform();
xptrans.LoadInnerXml(doc.ChildNodes);
refr.AddTransform(xptrans);
规范化
规范化的目的是为两个逻辑上相同但可能不是由相同的文本表示的XML片段产生相同的XML数据。例如,请观察下面两个代码片段。它们在逻辑上是相同的;它们的不同之处仅仅在于文本表示。但是如果您要对它们按原样进行哈希运算,则得到的哈希值将是不同的:
<root>
<a>Some text</a>
<b attr1="yes" attr2="no"></b>
<c Id="foo">More text</c>
</root>
<root>
<a>Some text</a>
<b attr2="no" attr1="yes" />
<c Id="foo">More text</c>
</root>
要避免该问题,该标准中指定的默认规范化算法将执行很多任务,包括消除开始和结束标记中的空白以及将空元素转换为开始/结束标记对。但是,它不会更改元素内容中的任何空白。所执行操作的完整列表可以在Canonical XML(位于http://www.w3.org/TR/xml-c14n)中得到。
签名引擎在必要时自动规范化数据,以便符合W3C标准。特别地,每当签名引擎需要将XML数据转换为二进制数据以便进行哈希运算时,都会规范化该数据。例如,当它准备对SignedInfo元素及其子元素进行签名时,就会发生这种情况。当它准备引用或转换的输出以便进行签名时,也可能发生这种情况。例如,如果您使用基于ID的引用(指向包含签名的文档中的其他XML数据),并且该引用没有与其相关联的转换,则签名引擎在对该引用的XML数据进行哈希运算之前将规范化该数据。
密钥管理
XML签名标准提供了KeyInfo元素,帮助进行密钥管理。该元素可以存储密钥名称、密钥值、密钥检索方法或证书信息,以帮助接收方验证签名。该标准没有指定应当如何信任以及是否应当信任KeyInfo元素中的任何信息。如果发送方和接收方共享一个受信任密钥列表,或者如果您发现了其他某种用于将密钥名称映射到密钥的方法,则KeyInfo元素可能很有用。.NET Framework 1.x具有一些对密钥名称、值和检索方法的支持,.NET Framework 2.0还包含对X.509证书的支持。让我们假设发送方和接收方共享一个密钥列表,接收方对于他期望从其接收消息的每个发送方都具有一个公钥。签名应用程序可以添加以下代码,以便向签名中添加KeyInfo元素:
// Adds an KeyInfo element with RSA public key information to the
// signature.
// Assumes a SignedXml object in sig, and an RSA object in key.
KeyInfo ki = new KeyInfo();
ki.AddClause(new RSAKeyValue(key));
sig.KeyInfo = ki;
该代码应当在调用ComputeSignature之前添加。它将在签名中产生一个KeyInfo元素,该元素看起来类似于以下代码:
<KeyInfo>
<KeyValue>
<RSAKeyValue>
<Modulus>4LfG(2 lines of Base64 text)2Fr=</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</KeyValue>
</KeyInfo>
这表示用来对XML文档进行签名的RSA公钥。接收方应用程序应当将该密钥与受信任密钥列表进行比较,如果该公钥不在列表中,则不应当信任文档。否则,攻击者就可以在传输过程中替换已经签名的文档,并且用另外一个密钥对其进行签名。如果签名包含与此类似的RSAKeyValue,则验证代码可以调用SignedXml类的CheckSignature方法(它不采用任何参数),并且.NET Framework将根据RSAKeyValue元素计算出该密钥。下面是一个示例:
// Verify a signature that includes RSAKeyInfo or DSAKeyInfo.
// Assume a SignedXml object in sig.
bool verified = sig.CheckSignature();
相关专题
- WPF的Attached属性 (0次浏览)
- WPF,将颠覆的设计世界? (0次浏览)
- Windows是否已经变成了一个怪物? (0次浏览)
- Windows2008用RODC保证分支机构安全 (0次浏览)
- Windows2008的NLB配置攻略 (0次浏览)
- Windows SharePoint Services 和 SharePoint P (0次浏览)
- Windows Forms中实现统一的数据验证(一) (0次浏览)
- Windows API一日一练:DrawText函数 (0次浏览)
- Win2008初次体验的几个心得 (0次浏览)
- WEB应用数据库访问的优化 (0次浏览)



