首页 | 互联网 | IT动态 | IT培训 | Cisco | Windows | Linux | Java | .Net | Oracle | 软件测试 | C/C++ | 嵌入式开发 | 存储世界 | 服务器
网络设备 | IDC | 安全 | 求职招聘 | 数字网校 | 网页设计 | 平面设计 | 技术专题 | 电子书下载 | 教学视频 | 源码下载 | 搜索 | 博客 | 论坛
中国IT实验室Dotnet频道
中国IT教育
Google
首页 ASP.NET  C#  XML/WebService ADO.NET VC.NET VB.NET .NET 资讯动态 专题 RSS订阅 讨论 下载
您现在的位置: 中国IT实验室 >> Dotnet >> XMLWeb >> 正文

用XML签名和加密更安全交换数据

 

.NET Framework 2.0中的新特性

    迄今为止讨论的所有XML签名特性在.NET Framework 1.x和2.0中都可用。XML加密和X.509证书集成对于版本2.0而言是新增特性。通过X.509证书集成,可以更容易地将X.509证书用于XML签名。通过新增的X509CertificateEx类和相关的类,可以更容易地操纵和使用证书,并且XML签名对象模型在适当的时候使用这些类。在本文的结尾,我们将对X.509集成进行更详细的讨论。XML加密是另外一个W3C标准。正如XML签名指定了有关创建XML形式的数字签名的格式和处理模型一样,XML加密对如何加密XML形式的数据进行了标准化。XML数字签名是通过SignedXml类驱动的,而XML加密是使用新的EncryptedXml类执行的。尽管XML加密可以用来加密任意数据,但它最常用于加密其他XML。当以这种方式使用时,您将在文档的加密方式上拥有很多的灵活性。例如,可以用不同的密钥加密XML文档的不同节点,同时将某些节点保留为明文。而且,由于用EncryptedXml类加密某些内容会产生XML,因此您甚至可以加密已经加密的结果,该过程称为“超级加密”。让我们考察一下一些已经加密的XML(参见图9)。一件可以立刻注意到的有趣的事情是,XML加密标准对某些元素(包括KeyInfo元素)使用XML签名命名空间。

一个简单的文档:


    Hello
    World


经过加密的文档:


            xmlns="http://www.w3.org/2001/04/xmlenc#"
    >
                    Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
       
           
                                    Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
               
                    recipient_public_key
               

               
                    PrI6(3 lines of Base64 text)Dwy4=
               

           

       

       
            awcH(3 lines of Base64 text)NNqQ=
       

   

图9 加密前后的XML文档

EncryptedData元素

    EncryptedData是通过加密XML生成的根元素,并且它包含有关数据的所有信息。EncryptedData包含三个主要的子元素:EncryptionMethod指定用来加密数据的算法;KeyInfo元素提供有关使用哪个密钥来解密数据的信息;CipherData或CipherReference元素则包含实际的加密信息。EncryptionMethod元素指定用来加密和解密密码数据的算法,这些算法由URI指定,就像XML签名标准一样。EncryptionMethod同时用于加密数据和加密密钥,但并非每个算法都可以同时用于这两个场合。图10显示了每个算法可以用在哪个场合。请注意,高级加密标准(Advanced Encryption Standard,AES)还可用于192位和128位密码;您只需在URI中更改密钥大小。

  EncryptedXml类的URI属性 加密数据 加密密钥
AES XmlEncAES256Url  
XmlEncAES256KeyWrapUrl  
DES XmlEncDESUrl  
TripleDES XmlEncTripleDESUrl  
XmlEncTripleDESKeyWrapUrl  
RSA XmlEncRSA1_5Url  

图10 使用加密算法的场合

    在加密或解密任何数据之前,加密引擎需要知道应当使用哪个密钥来加密和解密。可以用两种方式标识密钥,最容易的方式是为该密钥分配一个名称,并且在KeyInfo元素内部放置一个KeyName元素。解密文档的应用程序可以获得KeyName标记,并提供与给定的名称相匹配的密钥。该应用程序不仅提供密钥的名称,还可以将密钥作为EncryptedKey直接嵌入到KeyInfo元素中。EncryptedKey与EncryptedData包含相同的元素:加密方法、用来解密该密钥的密钥以及构成加密密钥的密码数据。加密密钥通常与命名密钥结合使用,以作为随机会话密钥。首先,生成一个随机会话密钥并使用它来加密XML;然后,用需要解密文档的众所周知的命名密钥加密会话密钥本身;最后,将该命名密钥插入到加密会话密钥的KeyInfo元素中,并且将该加密会话密钥附加到加密数据中。图9中的示例说明了这一点。XML数据的加密方法是256位的AES,而AES算法的密钥也已经被加密。EncryptedKey元素包含有关如何加密AES算法的密钥的信息,在该示例中,它是使用名为recipients_public_key的RSA密钥加密的。使用XML加密的应用程序必须将该名称映射到实际的密钥。

    可以将实际的加密数据嵌入到EncryptedData元素中,或者将其放到单独的位置,然后从EncryptedData中引用它。如果要将密码数据直接放到EncryptedData中,则会将其作为Base64编码的二进制文件放到CipherData元素中。图9中的示例使用了一个CipherData元素。另一个方案是将加密数据放到EncryptedData元素外部。可以将密码文本放在从该文档中的另一个元素到远程Web站点的任何位置。在这两种情况下,都将使用CipherReference元素而不是CipherData元素(参见图11)。

CipherReference的位置 URI格式 密码文本格式
相同文档中 #order Base64字符串
远程Web站点 http://www.example.com/order.bin 二进制

图11 CipherReferences

    对远程Web站点的CipherReferences提出了一个有趣的安全方案。在解密XML的过程中,解密引擎必须转到任意Web站点并下载密码文本。由于要解密的文档可能不会受到与完成解密的代码同等程度的信任,因此应当在沙箱中完成该操作。这是通过向EncryptedXml对象提供它将在解析任何CipherReferences时使用的证据来完成的。通过沙箱可以更安全地执行代码,因为解密应用程序可能不具有与提供加密数据的站点相同的权限。例如,如果应用程序试图解密不受信任的站点,并且该不受信任的站点不能够访问位于安全的、受信任站点上的某些受信任的数据,则它可以通过包含密码引用,让解密应用程序为它访问该文件。由于.NET安全策略是以证据为中心的,因此所提供的证据通常应当至少包含Site、Zone和Url对象,如下所示:

// Create evidence based on the referring document
Evidence evidence = new Evidence();
evidence.AddHost(new Zone(SecurityZone.Internet));
evidence.AddHost(new Site("untrustedsite"));
evidence.AddHost(new Url("untrustedsite/encrypted.xml"));

EncryptedXml exml = new EncryptedXml(untrustedDoc, evidence);

XML加密示例

    现在,让我们考察一下如何使用.NET Framework 2.0中的类。该示例说明了一个销售CD的Web站点,每次购买活动都被归档到一个XML文档中,其中包含有关订购了哪些商品、发货信息和信用卡号的详细信息。图12显示了订单的一些示例XML。


   
        Def Leppard: Pyromania
        Ozzy Osbourne: Goodbye to Romance
   

   
        Shawn Farkas
        One Microsoft Way
        98052
   

   
        0000-0000-0000-0000
   

图12 一个CD订单的XML

    在该实例中,公司内部的任何人查看订单中的项目是一件可以接受的事情,但是您可能希望对某些更为敏感的数据(例如,发货地址和信用卡信息)进行保密。实际上,您甚至可能希望对它们分别进行加密,以便只有计帐部门能够访问信用卡信息,并且只有发货部门能够访问发货地址。要做到这一点,需要对付款元素下的XML部分进行加密,以便只有计帐部门能够访问它,只有发货部门可以获得的单独密钥将用来加密发货元素。最后,整个订单将用公司中任何人都可以获得的密钥加密。

    第一步是创建一个EncryptedXml对象。这是通过传入具有要加密或解密的数据的文档完成的,如下所示:

// Assumes the order is in the order.xml file.
XmlDocument doc = new XmlDocument();
doc.Load("order.xml");
EncryptedXml exml = new EncryptedXml(doc);

    在加密XML之前,必须将要使用的密钥映射到它们的相应名称,这些名称将出现在KeyName元素中。可以使用EncryptedXml的AddKeyMapping方法完成该任务:

// Set up the key mapping. Assumes a method called GetBillingKey
// that returns the RSA key for the billing department.
RSA billingKey = GetBillingKey();
exml.AddKeyNameMapping("billing", billingKey);

    在设置了密钥-名称映射以后,加密XML就很容易了。第一步是调用Encrypt方法,它完成实际的加密,并且返回一个EncryptedData对象以表示文档的加密部分。之后,您需要调用一个工具方法,将原始XML文档的未加密部分换为新的加密数据:

// Find the element to encrypt.
XmlElement paymentElement =
    doc.SelectSingleNode("//order/payment") as XmlElement;
// Encrypt the payment element, passing in the key name.
EncryptedData encryptedPayment =
    exml.Encrypt(paymentElement, "billing");
// Swap the encrypted element for the unencrypted element.
EncryptedXml.ReplaceElement(paymentElement, encryptedPayment, true);

    这将产生图13中所示的加密XML。


   
        Def Leppard: Pyromania
        Ozzy Osbourne: Goodbye to Romance
   

   
        Shawn Farkas
        One Microsoft Way
        98052
   

   
                    xmlns="http://www.w3.org/2001/04/xmlenc#"
        >
           
           
               
                   
                   
                        billing
                   

                   
                       
                            Sce6lLD+u2f8HzPFyuGxTF32z4mb2ugql3JuJIPAqIP98iYs+Muhqg==
                       

                   

               

           

           
                FXKC(3 lines of Base64 text)ApqQt
           

       

   

图13 加密了支付信息的CD订单

    请观察一下加密数据,您可以看到我们已经描述的各个部分。首先,EncryptionMethod元素显示了AES-256的URI,这意味着该文档用带有256位密钥的AES算法(由RijndaelManaged类实现)加密。Encrypt方法为您生成一个随机的会话密钥;该密钥在KeyInfo元素中加密。通过观察EncryptedKey元素,您可以看到它是用RSA算法并借助于一个名为“billing”的密钥加密的。CipherData元素存放了该密钥的加密值。在KeyInfo的后面是包含加密内容(原来的付款元素)的CipherData。解密刚才说明的文档很容易,这要归功于EncryptedXml的DecryptDocument方法。首先,加载含有加密内容的文档:

// Assumes the encrypted order is in encrypted.xml
XmlDocument doc = new XmlDocument("encrypted.xml");
EncryptedXml exml = new EncryptedXml(doc, documentEvidence);

    接下来,设置密钥-名称映射,如下所示:

// Set up the key mapping. Assumes a method called GetBillingKey
// that returns the RSA key for the billing department.
RSA billingKey = GetBillingKey();
exml.AddKeyNameMapping("billing", billingKey);

    最后,调用DecryptDocument。该方法将负责解密密码文本,并且将加密的XML替换为它的解密内容。

// Decrypt the encrypted XML in the document
exml.DecryptDocument();

    在幕后,加密引擎将在调用DecryptDocument时寻找任何EncryptedData元素,在这种情况下,它只找到付款元素下面的那个元素。在找到该元素以后,它将查看KeyInfo子句并且看到它持有加密的256位AES密钥。加密密钥的KeyInfo将显示它是用名为billing的RSA密钥加密的。然后,它检查密钥映射表以寻找名为billing的密钥。我们为一个名为billing的密钥添加了一个密钥映射,因此引擎随后将解密加密密钥。既然引擎具有密钥,那么它将解密CipherData。然后,用解密的CipherData的结果来替换EncryptedData元素。当DecryptDocument被调用时,引擎将对它在该文档中找到的每个EncryptedData元素执行这一过程。

上一页  [1] [2] [3] [4] [5] 下一页

【责编:Kittoy】

中国IT教育

相关产品和培训
文章评论
 友情推荐链接
 认证培训
 专题推荐

 ·WEB程序开发--ASP.NET和PHP、JSP究竟学哪个?
 ·五步带你入门XML
 ·关于Java框架技术专题
 ·XML全攻略技术专题
 ·JAVA开源技术介绍专题
 ·Java嵌入式开发之J2ME技术专题
 ·超前体验 Oracle 11g的5个新特性…
 ·揭密使用VB.NET的五个实用技巧
 ·Oracle和SQL Server常用函数对比专题…
 ·展现C#世界 C#程序设计专题…
 今日更新
 社区讨论
 博客论点
 频道精选
 Dotnet频道相关导航