
通过ML签名和加密更安全地交换数据.doc
51页[摘要]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签名规范,请参阅位于的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签名标准还非常灵活,它允许您在签名之前对数据进行筛选和转换,并且使您可以精确地选择要签名的内容以及签名方式 一个简单的文档:
请注意已经被添加到文档中的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.XmlDocument doc = new XmlDocument();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。
