新版本突显原生 XML 类型和高级数据处理的优势
2007-11-11 08:41:42 来源:WEB开发网[摘要]xml(标准化越来越近了)签名和xml(标准化越来越近了)加密标准目前被广泛地用作构建快(building-block)技术。本文解释了xml(标准化越来越近了)签名和xml(标准化越来越近了)加密标准,并且说明了如何通过.NET使用它们。
注:本文的某些部分基于 .NET Framework 2.0 的预发布版本。与这些部分有关的所有信息都有可能更改。
xml(标准化越来越近了)签名和xml(标准化越来越近了)加密标准目前被广泛地用作积木(building-block)技术。Microsoft Office InfoPath使用xml(标准化越来越近了)签名对部分或整个表单进行签名。Web服务使用xml(标准化越来越近了)签名对SOAP消息进行签名,并且使用xml(标准化越来越近了)加密技术对它们进行加密。基于ClickOnce的应用程序的xml(标准化越来越近了)清单(Visual Studio 2005中的新增功能)也使用xml(标准化越来越近了)签名。.NET Framework 1.x包含xml(标准化越来越近了)签名标准的对象模型,而.NET Framework 2.0则添加了其他支持,同时还添加了xml(标准化越来越近了)加密的对象模型。本文解释了xml(标准化越来越近了)签名和xml(标准化越来越近了)加密标准,并且说明了如何通过.NET使用它们。有关实际的xml(标准化越来越近了)签名规范,请参阅位于http://www.w3.org/TR/xml(标准化越来越近了)dsig-core的W3C标准。
数字签名
在深入探讨xml(标准化越来越近了)签名标准之前,让我们回顾一下数字签名的基础知识。因为防止恶意用户在传输期间改变消息很重要,所以数字签名保护数据的完整性,并且可以检测数据在到达接收地的途中受到的任何更改。因为能够标识发送方也很重要,所以消息通常使用发送方的私有(秘密)密钥进行签名,并且用相应的公钥进行验证,从而使接收者在知道发送方的公钥时可以确认发送方的标识。这可以防止恶意用户通过尝试作为已知的发送方发送消息,或者通过截获来自已知发送方的消息并将其替换为他们自己的消息(一种中间人形式的攻击),冒充已知的发送方。
要创建数字签名,首先需要使用加密哈希函数来对需签名的消息进行哈希运算。对于任何长度的输入,加密哈希函数都会返回固定长度的位组,称为哈希值。该哈希值无法容易地重新转换为原来的输入。即使输入中只有一个位发生更改,哈希值也会以不可预知的方式更改,因此无法仅仅通过查找类似的哈希值来找到与原始输入类似的输入。一个常用的哈希函数是SHA-1,它可以产生160位的哈希值。下一个步骤是使用签名算法和您的私钥对该哈希值进行签名,以产生签名值。您用您的私钥创建该签名,以便具有您的公钥的其他人可以对其进行验证(本文稍后将对此进行详细讨论)。RSA是一种流行的用于签名的加密算法。在您将消息和该签名发送给接收者之后,验证过程开始。收到的消息被在签名时使用的相同哈希函数用来进行哈希运算;然后,通过将签名值以及公钥和计算得到的哈希一起传递给签名算法,对签名值进行验证。如果计算得到的哈希与签名哈希相匹配,则签名有效。如果这两个哈希不匹配,则表明数据或签名已经更改,因此不能确保数据的完整性。还可以使用密钥哈希算法签名和验证数据,但是这超出了本文讨论的范围。.NET Framework已经为所有种类的哈希、加密/解密和签名/验证算法包含了一组丰富的类。有关这些类的详细信息,请参阅.NET Framework SDK文档以及由Brian LaMacchia等人编写的《NET Framework Security 》(Addison-Wesley, 2002)。
xml(标准化越来越近了)签名基础知识
您可以使用xml(标准化越来越近了)签名对任何种类的数据进行签名,这些数据包括xml(标准化越来越近了)文档的某个部分、其他xml(标准化越来越近了)文档或任何格式的其他数据。但是,实际上,xml(标准化越来越近了)签名最常用于对以xml(标准化越来越近了)表示的其他数据进行签名。xml(标准化越来越近了)签名标准还非常灵活,它允许您在签名之前对数据进行筛选和转换,并且使您可以精确地选择要签名的内容以及签名方式。
一个简单的文档:
<docRoot>
<a>Hello</a>
<b>World</b>
</docRoot>
经过签名的文档:
<docRoot>
<a>Hello</a>
<b>World</b>
<Signature xml(标准化越来越近了)ns="http://www.w3c.org/2000/09/xml(标准化越来越近了)dsig#">
<SignedInfo>
<CanonicalizationMethod
Algorithm="http://www.w3c.org/TR/2001/REC-xml(标准化越来越近了)-c14n-20010315"/>
<SignatureMethod
Algorithm="http://www.w3c.org/2000/09/xml(标准化越来越近了)dsig#rsa-sha1"/>
<Reference URI="">
<Transforms>
<Transform
Algorithm=
"http://www.w3.org/2000/09/xml(标准化越来越近了)dsig#enveloped-signature"/>
</Transforms>
<DigestMethod
Algorithm="http://www.w3c.org/2000/09/xml(标准化越来越近了)dsig#sha1"/>
<DigestValue>cbPT0951Ghb2G3UjpVjWw+7q0Bc=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>IoEwS(3 lines of Base64 text)XSo=</SignatureValue>
</Signature>
</docRoot>
图1 签名前后的简单xml(标准化越来越近了)文档
让我们考察一个简单的xml(标准化越来越近了)签名方案:对整个文档进行签名并且包含签名(参见图1)。请注意已经被添加到文档中的Signature元素,该元素包含xml(标准化越来越近了)签名。让我们看一下每个元素所包含的内容:
SignedInfo——该元素的子元素包含有关所签名的内容以及签名方式的所有信息。签名算法实际上应用于该元素及其所有子元素以生成签名。
CanonicalizationMethod——该元素指定了用于SignedInfo元素以便将xml(标准化越来越近了)规范化的规范化(C14N)算法。我们将在下文中讨论C14N。
SignatureMethod——该元素指定了该签名的签名算法。在该示例中,签名算法是带有RSA(用于对产生的哈希值进行签名)的SHA-1(用于哈希运算)。
Reference——这些元素指定了将要签名的数据以及在哈希运算之前应当如何对该数据进行处理。URI属性(它表示统一资源标识符)标识要签名的数据,而Transforms元素(稍后描述)指定在进行哈希运算之前如何处理数据。在该示例中,我们将使用特殊的URI——空字符串,它指定包含签名的文档是要包含在签名中的数据。xml(标准化越来越近了)签名标准对Reference数据使用间接签名机制。该标准不是对Reference中的所有数据进行哈希运算然后加密哈希值,而是使用由Reference的DigestMethod元素所指定的算法对每个Reference的数据进行哈希运算,然后将哈希值存储到Reference的DigestValue元素中。接下来,对SignedInfo元素和它的所有子元素(包括Reference元素)进行哈希运算;哈希值被加密以生成签名。因此,您实际上是对Reference元素中所引用数据的哈希的哈希进行签名,但是该方案仍然可以保护数据的完整性。图2和图3在匹配的xml(标准化越来越近了)旁边显示了签名和验证过程。
Transforms——每个Reference元素都可以具有零个或更多个为它指定的转换。这些转换按照它们在xml(标准化越来越近了)中列出的顺序应用于该Reference的数据。转换使您可以在对Reference的数据进行哈希运算之前对该数据进行筛选或修改。在该示例中,我们将使用包封式签名转换,该转换选择了包含文档中除Signature元素以外的所有xml(标准化越来越近了)。我们必须从将被签名的数据中移除Signature元素,否则,当我们存储签名值时,可能会修改我们尝试签名的数据。我们将在下文中详细讨论转换。
SignatureValue——该元素包含通过签名SignedInfo元素及其所有子元素而计算得到的签名值。
(标准化越来越近了)签名和加密更安全地交换数据(图一)" />
图2 签名过程
现在,让我们讨论用于创建签名的处理模型(参见图2)。首先,对于签名中的每个Reference元素:
- 按照转换在Transforms元素下面出现的顺序,将Transform元素中指定的每个转换算法应用于Reference的数据。
- 使用Reference的DigestMethod元素所指定的哈希算法对经过转换的数据进行哈希运算。
- 在Reference的DigestValue元素中存储产生的哈希值。
下一个步骤是使用在签名的CanonicalizationMethod元素中指定的算法规范化SignedInfo元素及其子元素。然后,使用在签名的SignatureMethod元素中指定的算法对SignedInfo元素及其子元素进行签名。签名值被存储在SignatureValue元素中。
(标准化越来越近了)签名和加密更安全地交换数据(图二)" />
图3 验证过程
签名验证是刚刚描述的过程的逆过程(参见图3)。首先,必须使用CanonicalizationMethod元素中指定的C14N算法规范化SignedInfo元素及其子元素。然后,必须针对SignedInfo元素及其子元素验证SignatureValue元素中存储的签名值。
最后,对于签名中的每个Reference元素:
- 按照转换在Transforms元素下面出现的顺序,将Reference的Transform元素中指定的每个转换算法应用于Reference的数据。
- 使用Reference的DigestMethod元素所指定的哈希算法对Reference的经过转换的数据进行哈希运算。
- 将计算得到的哈希值与DigestValue元素中存储的值进行比较。
如果签名验证成功,并且每个Reference的哈希值与签名中存储的哈希值相等,则xml(标准化越来越近了)签名有效。否则,或者由Reference元素之一引用的数据已经更改,或者Signature元素已经更改。
嵌入到由其签名的文档中的签名称为信封签名。用于创建这种签名的代码如图4所示,用于验证该签名的代码如图5所示。
using System.Security.Cryptography;
using System.Security.Cryptography.xml(标准化越来越近了);
// Also, add a reference to System.Security.dll
// Assume the data to sign is in the data.xml(标准化越来越近了) file, load it, and
// set up the signature object.
xml(标准化越来越近了)Document doc = new xml(标准化越来越近了)Document();
doc.Load("data.xml(标准化越来越近了)");
Signedxml(标准化越来越近了) sig = new Signedxml(标准化越来越近了)(doc);
// Make a random RSA key, and set it on the signature for signing.
RSA key = new RSACryptoServiceProvider();
sig.SigningKey = key;
// Create a Reference to the containing document, add the enveloped
// transform, and then add the Reference to the signature
Reference refr = new Reference("");
refr.AddTransform(new xml(标准化越来越近了)DsigEnvelopedSignatureTransform());
sig.AddReference(refr);
// Compute the signature, add it to the xml(标准化越来越近了) document, and save
sig.ComputeSignature();
doc.DocumentElement.AppendChild(sig.Getxml(标准化越来越近了)());
doc.Save("data-signed.xml(标准化越来越近了)");
图4 创建一个信封签名
更多精彩
赞助商链接