Vincent.Chan‘s Blog

常用链接

统计

积分与排名

网站

最新评论

探索 XML 加密,第 1 部分::演示结构化数据的安全交换

级别: 初级

Bilal Siddiqui, CEO

2002 年 3 月 01 日

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 属性里指定它们。另一个属性 xmlns 指定了用来加密 XML 数据的 XML 加密名称空间。

使用 XML 加密对单个元素加密

您可能只想加密 清单 1 中的一个元素 ― 例如 Payment 元素。在这种情况下, 清单 3中阐明了其结果。比较 清单 2清单 3,您将发现下列差异:

  1. 清单 2只包含 XML 加密的模式,而 清单 3既包含 XML 加密模式又包含来自 清单 1中原始数据的元素。在 清单 3中,XML 加密被嵌入到用户的 XML 中。
  2. 清单 3<EncryptedData> 中也有一个 Type 属性,但它的值是 http://www.w3.org/2001/04/xmlenc#Element。我们不再使用 IANA 类型;相反,我们使用 XML 加密已指定的类型。
  3. 请特别注意末尾的片段 #Element,它表示 EncryptedData ― 这代表一个元素。

加密元素的内容

如果您只要加密 清单 1 中元素 CardId 中的内容, 清单 4 就是其结果。这次,我们使用 http://www.w3.org/2001/04/xmlenc#Content 作为 Type 属性的值。每当我们都仅须加密内容时都使用这个值。

加密非 XML 数据

假如您希望通过 XML 加密发送一个 JPEG 文件,那会怎么样呢? 清单 5 是将产生的一个典型文件。按字节序列加密的整个 JPEG 文件将作为 CipherValue 元素的内容出现。 请注意, 清单 2清单 5 之间唯一的差异: EncryptedData 元素的 Type 属性。 清单 5包含了 JPEG 格式的 IANA 类型。类似地,可以通过提供 IANA 值(参考 IANA 网站,请参阅 参考资料)加密任何格式。





回页首


XML 加密的密钥

在清单 1 到 5 中,我们已经演示了加密,而加密就不可能不使用密钥(请参阅侧栏 公钥、私钥和秘钥)。使用 XML 加密,所有与密钥相关的问题划分成两个部分:

  • 密钥的交换(非对称加密)
  • 使用预先交换的密钥(对称加密)

这样,用户可以交换密钥并在以后使用它们。

用于交换秘钥的非对称密钥

在这个方案中,一方将它的公钥发送给另一方。另一方使用这个公钥加密其秘钥。 清单 6(请求)和 清单 7 (响应)中显示了这种数据交换。我们假设 Imran 和 Ali 分别是相互通信的第一方和第二方。Imran 初始化了公钥交换请求并在名为 KeyValue 的元素中发送了他的公钥。 属性 CarriedKeyName 表示所传输密钥的名称。请注意这个结构的根元素是 EncryptedKey ,它包含 ds:KeyInfods:KeyValue 元素。 ds: KeyInfods:KeyValue 元素属于 XML 数字签名(ds:)名称空间。对于密钥交换 XML 加密完全依赖于 XML 数字签名规范。因此, <ds:EncryptedKey><ds:KeyValue> 都属于 XML 数字签名规范名称空间。 清单 7是 Ali 发送的响应。 清单 7 中的 CipherValue 元素包含一个新生成的秘钥,它是用第一方的公钥加密的。仔细看清单 6 和清单 7,您将注意到请求和响应都包含 EncryptedKey 元素。 EncryptedKey 元素内的 ds:KeyInfods:KeyValue 元素携带着公钥( 清单 6 )。另一方面, EncryptedKey 元素内的 CipherDataCipherValue 元素( 清单 7 )将传输(加密的)秘钥。还请注意 EncryptedKey 元素总是包含一个 CarriedKeyName 属性来指定其所携带密钥的名称。

使用我们过去已经交换的密钥

在前一节中,我们交换了一个秘钥。现在我们将使用那个密钥来加密数据。我们将假定 Imran 发送了一条 XML 消息( 清单 8)来响应 清单 7(请回忆 清单 7包含一个名为“Imran Ali”的加密的秘钥)。Imran 将使用他的(Imran 自己的)私钥来解密这个秘钥(因为 Ali 用 Imran 的公钥加密了这个秘钥)。Imran 可以使用这个秘钥并将它放在 清单 8 中的 CipherValue 元素中来加密他打算发送给 Ali 的数据。

清单 8 中的 ds:KeyInfo 元素包含一个 KeyName 元素。这个组合引用了 Imran 用于数据加密的密钥名称。

图 1 是显示用于安全数据交换的 XML 文件的这种交换的可视图。


图 1. 使用 XML 加密进行密钥与数据交换的顺序
使用 XML 加密进行密钥与数据交换的顺序。

清单 57 中, CipherData 元素可以出现在 EncryptedData 元素或 EncryptedKey 元素中。我们使用 CipherData 元素来引用加密数据(当它出现在 EncryptedData 元素中时)或加密密钥(当它出现在 EncryptedKey 元素中时)。在清单 57 中,包含实际加密数据的 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 方法来指定加密参数,包括下列:

  1. 要加密的文件名称
  2. 所产生的 XML 加密文件的名称
  3. 加密算法的名称
  4. 将用于加密的密钥名称
  5. 用于 <EncryptedData> 结构标识的 ID

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

公钥、私钥和秘钥

我们使用了三个与密钥相关的术语(公钥、私钥和秘钥)。尽管这些术语对从事端到端安全性的开发人员而言是众所周知的,但 XML 开发人员可能并不熟悉它们。让我们阐明这些术语:

公钥和私钥:我们成对使用它们。有些算法生成一对公钥和私钥。我们将公钥发送给任何希望与我们交换加密数据的人。使用公钥,我们只能加密有限大小的数据。通信伙伴使用我们的公钥加密数据,然后将加密的数据发送给我们。接着,我们用私钥解密数据。这是非对称加密。

秘钥: 我们使用公钥和私钥来交换秘钥。通常随机生成秘钥。一旦使用非对称加密与通信伙伴交换了秘钥,我们就可以在两端都使用这个秘钥加密数据了。这是对称加密。

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

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

posted on 2006-03-21 23:31 Vincent.Chen 阅读(272) 评论(0)  编辑  收藏 所属分类: XML


只有注册用户登录后才能发表评论。


网站导航: