探索XML加密 第1部分

日期: 2009-03-16 作者:Bilal Siddiqui 来源:TechTarget中国 英文

  XML加密为需要结构化数据安全交换的应用程序提供了一种端到端安全性。XML本身是对数据进行结构化最流行的技术,因此基于XML的加密成为处理数据互换应用程序中安全性的复杂需求的方法。在这个两部分系列的第1部分中,Bilal解释了打算如何将XML和安全性集成到W3C XML加密工作草案中。

  当前,传输层安全性(Transport Layer Security(TLS))是因特网上安全通信的事实标准。TLS是继著名的安全套接字层(SSL)之后的端到端安全性协议。SSL最初是由Netscape设计的,而且,之后国际工程任务小组(Internet Engineering Task Force (IETF))改编了它的3.0版本,同时他们还在设计TLS。这是一个非常安全和可靠的协议,它提供了通信双方之间的端到端安全性会话。XML加密(XML Encryption)无意替换或取代SSL/TLS。相反,它提供了用于SSL未涵盖的安全性需求的机制。以下是两个SSL未涉及的重要领域:

  ·加密交换数据的一部分
  ·多方(不止两方)之间的安全会话

  使用XML加密,每一方都可以保持与任何通信方的安全或非安全状态。可以在同一文档中交换安全的和非安全的数据。例如,考虑一个包含许多聊天室的安全聊天应用程序,其中每个聊天室都有几个人。可以在聊天伙伴之间交换XML加密的文件,这样一个聊天室中的数据对其它聊天室而言是不可见的。

  XML加密能够处理XML和非XML(例如二进制)数据。现在我们将演示一个简单的数据交换,通过XML加密使它安全。然后我们将慢慢地增加安全性需求的复杂程度,并解释XML加密模式及其不同元素的使用。

  XML数据安全交换的简单示例

  假设您希望将清单1中的XML文件发送给出版公司。这个文件包含一本您要购买的书的详细信息。此外,它还包含您付款的信用卡信息。自然地,您希望对这些敏感数据使用安全通信。一种选择是使用SSL,它将保护整个通信的安全。备选方案是使用XML加密。正如已经提到的,XML加密不是SSL/TLS的替代。如果应用程序要求整个通信是安全的,则您将使用SSL。另一方面,如果应用程序需要安全和非安全通信的组合(这意味着部分数据将被安全地交换,而其它数据将按原样交换),那么XML加密是最佳选择。

  清单1. 要加密的样本XML文件

<purchaseOrder>
 <Order>
  <Item>book</Item>
  <Id>123-958-74598</Id>
  <Quantity>12</Quantity>
 </Order>
 <Payment>
  <CardId>123654-8988889-9996874</CardId>
  <CardName>visa</CardName>
  <ValidDate>12-10-2004</ValidDate>
 </Payment>
</purchaseOrder>
 
  注意:我们故意使清单1中的XML文件非常简单。这有助于将我们的注意力集中在与加密相关的问题上。用于合作商业或Web服务的现实XML文件将有类似的结构,但更冗长。WSDL(Web服务定义语言)和SOAP(简单对象访问协议)是B2B集成中经常使用的基于XML的语法。WSDL和SOAP都可使用XML加密来提供企业内的安全通信。有关它们的详细信息,请访问W3C。

  使用XML加密对整个文档加密

  XML加密提供各种选项。清单2、清单3和清单4显示了不同的加密结果。让我们逐个仔细研究它们。

  倘若您决定加密清单1中的整个XML文档,则清单2显示最后所得到的XML加密的文件。请注意<CipherData>和<CipherValue>标记。实际加密的数据作为<CipherValue>标记的内容出现。整个CipherData元素出现在一个EncryptedData元素内。EncryptedData元素包含用于加密的XML名称空间。例如,加密前的原始数据是XML并且Internet Assigned Numbers Authority(IANA)对XML的正式类型定义是http://www.isi.edu/in-notes/iana/assignments/media-types/text/xml。这作为Type属性的值出现。XML对各种流行的数据格式(如RTF、PDF和JPG)使用IANA的类型定义。完整细节,请参阅它们的网站。如果有特殊的应用程序数据类型(可能是属于您公司的内容管理系统特有的DTD或XSD),可以在EncryptedData 素的Type属性里指定它们。另一个属性 border=0>

  图1. 使用XML加密进行密钥与数据交换的顺序
 
  在清单5和7中,CipherData元素可以出现在EncryptedData元素或EncryptedKey元素中。我们使用CipherData元素来引用加密数据(当它出现在EncryptedData元素中时)或加密密钥(当它出现在EncryptedKey元素中时)。在清单5和7中,包含实际加密数据的CipherData元素中都有一个CipherValue子元素。

  我们也可以引用外部加密数据或加密密钥。这意味着实际加密数据或密钥将出现在别的地方(可能是因特网上的某个地方),而不是在XML加密文件内。在这种情况下,我们将在CipherData中使用CipherReference而不是CipherValue子元素。我们将通过URI引用实际加密数据。这在清单9中显示。

  引用外部XML文件中的特定元素

  清单10说明了引用外部XML文件的一个变体。这里我们只引用了URI所指向的外部文件的一部分。CipherReference元素中有一个Transforms子元素。这个Transforms元素可以包含许多Transform元素,其中每个都将包含单个XPath元素。这个XPath元素指定一个XPath表达式,该表达式引用外部XML文档的特定节点。

  我们的API的DOM结构

  我们已经演示了如何创建XML加密文件以及交换加密数据。现在我们将推荐用于XML加密的Java API并提供一个样本实现。为达到这个目的,我们将使用DOM。

  我们的DOM实现由一组类组成(清单11到16)。XmlEncryption类(清单11)是其余类的封装器,这意味着我们的API用户将只需要与这个类交互。在内部它使用其它类的功能。

  清单11是一个能够生成完整XML加密文件的封装器类。

  清单12创建EncryptedData元素。

  清单13创建EncryptionMethod元素。

  清单14创建KeyInfo元素。

  清单15创建CipherData元素。

  清单16包含作为静态整数的算法名称及其作为字符串的相应名称空间。

  XmlEncryption类(清单11)包含各种公用Get/Set方法。用户将调用Set方法来指定加密参数,包括下列:

  ·要加密的文件名称
  ·所产生的XML加密文件的名称
  ·加密算法的名称
  ·将用于加密的密钥名称
  ·用于<EncryptedData>结构标识的ID

  我们已经通过main()方法演示了XmlEncryption类(清单11)的使用。我们在main()方法中创建了这个类的实例。构造器实例化了DOM,因此所有基本类都将使用同一个对象。

  如清单2中所示,这个实现只支持整个文件的加密。EncryptCompleteXmlFile()方法将通过按序列调用下列方法完成这个任务:

  ·GetEncryptedDataDoc()返回EncryptedData类(清单12)的对象。它包含EncryptedData元素的结构。
  ·GetEncryptionMethodDoc()返回Document对象,该对象包含对应于EncryptionMethod元素的XML结构。GetEncryptionMethodDoc()使用EncryptionMethod类(清单13)来创建XML。
  ·GetKeyInfoDoc()返回Document对象,该对象包含对应于KeyInfo元素的XML结构。GetKeyInfoDoc()使用GenericKeyInfo类(清单14)的对象来创建XML。这个类仅提供最小的必需功能(对KeyName和KeyValue元素的支持),您将通过对GenericKeyInfo类的继承来提供完整的功能,其中包含对X509证书、PGP数据等的支持。
  ·ReadFile()取得我们希望加密的数据(整个XML文件)。
  ·GetEncryptedData()暂时不做任何事情。我们将在本文的下一部分实现这个方法。它应该创建在步骤4中取得的XML数据的加密格式。在上一节(Java密码体系结构)中,我们已经简要地讨论了我们的加密策略。
  ·GetCipherDataDoc()将加密数据作为参数,然后返回包含CipherData元素的Document对象。GetCipherDataDoc()使用CipherData类(清单12)的对象来创建XML。
  ·最后,三次调用EncryptedData(清单15)对象的addChild()方法,该方法将获得步骤2、3和6的Document对象,然后将它们添加到<EncryptedData>结构,这是它们所有对象的父类。
  ·SaveEncryptedFile()保存完整的XML加密文件。

  AlgoNames(清单16)是一个只指定XML加密所需要的名称空间声明的助手类。

  XmlEncryption类(清单11)也可以作为服务器端组件使用。在本系列的下一部分中,我们将演示它在独立应用程序中以及在服务器端应用程序中的使用。

  我们已开发的这组类只执行基于DOM的XML创建。我们还需要实现密码功能。现在我们将尝试形成一个用于密码支持的策略。出于这个目的,我们需要研究Java密码体系结构(Java Cryptographic Architecture(JCA))。

  Java密码体系结构(JCA)

  Java提供对密码术的完整支持。出于这个目的,J2SE中有几个包,它们涵盖了安全性体系结构的主要特性,如访问控制、签名、证书、密钥对、密钥存储和消息摘要等。

  JCA设计的主要原理是将密码概念从算法实现中分离出来,以便不同的供应商可以在JCA框架内提供他们的工具。

  JCA引擎类

  JCA定义了一系列引擎(Engine)类,其中每个引擎提供一种密码功能。例如,MD(消息摘要)算法有几种不同的标准。这些标准的实现各不相同,但在引擎API级别,它们都是相同的。不同的供应商可以自由地提供特定算法的实现。

  Java密码扩展(JCE)

  所有独立(第三方)供应商的密码算法实现都称为Java密码扩展(Java Cryptographic Extension(JCE))。Sun Microsystems也提供了JCE的一种实现。无论何时使用JCE,都必需将它和JCA一起配置。为此,我们需要执行如下操作:

  1. 添加jar文件的地址以在CLASSPATH环境变量中配置供应商(将所有JCE实现称为供应商)。

  2. 通过编辑java.security文件,在您认可的供应商列表中配置供应商。这个文件位于JavaHome/jre/lib/security文件夹。下列是指定优先级的语法:security.provider.<n>=<masterClassName>。这里n是优先级号(1、2、3等等)。MasterClassName是引擎类将为特定算法实现调用的主类的名称。供应商文档将指定其主类名称。例如,考虑java.security文件中的下列项:

  ·security.provider.1=sun.security.provider.Sun
  ·security.provider.2=com.sun.rsajca.Provider
  ·security.provider.3=com.sun.net.ssl.internal.ssl.Provider

  这些项意味着引擎类将按上面提到的顺序搜索任何算法实现。它将执行最先找到的实现。完成这些简单步骤之后,我们完全准备好开始在XML加密应用程序中使用JCA/JCE。

  在我们的XML加密实现中使用JCA和JCE

  封装器类XmlEncryption(清单11)中的GetEncryptedData()函数是处理所有与JCA/JCE相关问题的所在。目前,这个方法仅返回字符串“This is Cipher Data”。我们还没有编写与JCA/JCE相关的类。这个方法获得未加密数据,然后将它作为加密字符串返回。在编写了用于JCA/JCE的封装器类之后,我们将在这个方法中处理所有与算法和密钥相关的问题。

  下一次:在这一系列文章的下一部分中,我们将讨论并实现密码术的细节。我们将演示加密和解密类的工作方式以及它们使用解析逻辑的交互,并展示Web服务中XML加密的应用程序。

  关于作者
 
  XML顾问Bilal Siddiqui于1995年从巴基斯坦的拉合尔工程与技术大学获得电子工程学学位。然后他开始设计用于工业控制系统的软件解决方案。后来,他转向XML并运用他在C++方面的编程经验来构建基于Web和WAP的XML处理工具、服务器端解析解决方案和服务应用程序。您可以通过向Bilal发电子邮件索取本文包含的代码文件的工作副本,他的电子邮箱是
wap_monster@yahoo.com

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐