关闭

探索 XML 加密,第 2 部分

947人阅读 评论(0) 收藏 举报

实现 XML 加密引擎
级别: 初级
Bilal Siddiqui, CEO, WAP Monster
2002 年 8 月 01 日

在第二部分中,Bilal Siddiqui 借助于一个用例方案研究了 XML 加密的使用模型。他展示了一个简单演示应用程序,解释了该应用程序如何使用 XML 加密实现。接着他继续上一次的 XML 加密实现,并利用 JCA/JCE 类支持密码术。最后,他简要讨论了 XML 加密在基于 SOAP 的 Web 服务中的应用

在本系列专栏文章的 第 1 部分中,我介绍了 XML 加密(XML Encryption)及其基本语法和处理。我使用安全交换结构化数据的简单示例,研究了 XML 加密中的不同标记及其各自的用法,提出了基于 DOM 用于 XML 加密的 Java API,并简要概述了 Java 中的密码术(JCA/JCE)。

在这一部分中,我以一个信息交换方案开始我的讨论,该方案演示了 XML 加密的用法。

信息交换方案

请考虑两家企业间信息交换的过程。一家企业是在线图书销售商,另一家是出版社。图书销售商要采购图书时,向出版社提交采购订单。在出版社这一方,销售部门收到这份订单,对它进行处理,并将它转交给会计部门。这两家企业交换的是 XML 文档格式的信息。由于发送时一部分文档需要安全,而其余部分不需要安全,所以要将安全性应用于文档的不同部分,则 XML 加密是很自然的方法。

依据图书销售商的安全性策略,支付信息只能让会计部门知道。销售部门只需抽取出书名、它的项标识以及订购数量;因为这些信息是它可以保留的无需安全的不敏感信息。会计部门要使用一个预先交换的秘钥对采购订单中的支付信息解密。(注:XML 加密只关于加密和解密结构化信息,而不规定密钥交换的任何特定方法。)通过映射这个策略,XML 加密提高了销售部门支付信息的隐密性,也帮助了会计部门对此信息的解密。

基于文档的安全性

此时,稍许认真考虑一下基于文档的安全性概念可能很有用。使用这个安全性体系结构,您可以将安全性强制在文档级别。安全会话的上下文在安全文档内受到很有效的保护。在该文档内可以获得被授权方因解密文档可能需要的所有信息。创建的合乎逻辑的安全会话很灵活、具有很长的寿命,而且它允许多方参与同一安全会话。即将发布的 Web 服务协议“业务事务协议(Business Transaction Protocol (BTP ― 请参阅 参考资料))”依赖的是相同的概念,即在事务文档内保存会话上下文;这延长了事务的寿命,并增强了它的灵活性。


演示应用程序

要满足上述出版社和图书销售商之间的安全数据交换方案,我创建了一个称为 demoXmlEncApp 的演示应用程序类(请参阅 清单 1)。该类使用 XML 加密样本实现类 XmlEncryption (请参阅 清单 2)。

演示应用程序做了什么

在图书销售商一方,通过调用读取采购订单 XML 文件 Order.xml(请参阅 清单 3)的 simulateBookSellersEnd 方法, demoXmlEncApp 类的 main 方法首先执行处理,并通过 XML 加密中指定的三种加密方法(例如:整个 XML 文件加密、元素加密或元素内容加密)中的一种对该 XML 文件中的敏感信息加密。然后它将 XML 加密的文件以及用于加密的密钥保存到磁盘。


清单 3. Order.xml


<?xml version="1.0"?>
<!-- This Listing provides the sample XML File that will be encrypted. -->
<purchaseOrder>
	<Order>
		<BookName>Soccer For Dummies</BookName>
		<Id>123-958-74598</Id>
		<Quantity>500</Quantity>
	</Order>
	<Payment>
		<CardNo>4502-3456-3278-2011</CardNo>
		<CardType>VISA</CardType>
		<ValidDate>12-10-2004</ValidDate>
	</Payment>
</purchaseOrder>

由于文件交换和密钥交换协议不是这里所涉及的内容,因此我假定出版商可以通过任何适当的方法使用这些协议(例如,分别通过 HTTP 和某些公钥加密算法交换 XML 加密的文件和秘钥)。 main 方法接着通过调用 simulatePublishersEnd 方法来担任出版商这一角色,抽取销售部门所需的信息,并在控制台上显示收到的 XML 文件。而且,它还向会计部门解密支付信息,并在控制台上显示。

demoXmlEncApp 类中的 simulateBookSellersEnd 函数首先实例化 XmlEncryption 对象,然后调用 XmlEncryption 的各种设置方法来设置如下属性:

  • clearDoc :要加密的 XML 文件(请参阅 清单 3)的 DOM 对象形式
  • encKey :用于加密的密钥
  • algoName :加密算法名称
  • keyName :加密密钥的名称;在如本专栏文章第 1 部分解释的 XML 加密期间,它是 KeyName 元素的子文本节点值
  • encId :文档中赋予 EncryptedData 标记唯一的名称

根据调用应用程序时所传递的命令行参数, demoXmlEncApp 类的 simulateBookSellersEnd 方法调用 XML 加密引擎( XmlEncryption 类)的不同方法。让我们看一下在 XmlEncryption 类内部发生了什么,它是主 XML 加密处理引擎。


XML 加密实现细节

在第 1 部分中,我已经介绍了被提议的 XML 加密 API 的一部分内容。请回忆在类 XmlEncryption (请参阅 第 1 部分的清单 11)中有一个用于对整个 XML 文件加密的名为 encryptCompleteXmlFile 的方法。除了 encryptCompleteXmlFile 方法,我现在添加了以下两个方法来为不同数据类型的加密要求(加密颗粒度)提供服务。

  • encryptElementOfXmlFile ,用于加密 XML 文件中的特定元素
  • encryptElementContentOfXmlFile ,用于加密 XML 文件中特定元素的内容

通过使用 XmlEncryption 类的以下三种 XML 加密方法中的任何一种,图书销售商就可以保护采购订单中的敏感信息:

  1. 加密整个 XML 文件
  2. 加密 XML 文件中的元素
  3. 加密 XML 文件中元素的内容

1. 用 XML 加密对整个 XML 文件加密

图书销售商可以对整个 Order.xml文件加密,以产生 XML 加密的文件,这样就可以发送到出版社的销售部门。虽然这种方法在端对端通信链路中提供了适当的安全性,但违反了图书销售商的安全性策略。该策略要求不透露销售部门的支付信息而向会计部门提供该信息。在这种情况下,销售部门对整个 XML 文档解密,这就泄露了支付信息。因此这种方法看来不合适,虽然如果您使用 超级加密(本文稍后讨论)可能会有用。

如果图书销售商决定对整个 Order.xml 文件加密,那么类 demoXmlEncApp 中的 simulateBookSellersEnd 函数就生成对类 XmlEncryption 的公用方法 encryptCompleteXmlFile 的调用。

该方法首先调用 getString 私有方法将要加密的 XML 文件序列化成字符串形式。接着它调用加密方法 getEncryptedData ,返回用 Base 64 编码的密码文本字符串。接着该密码文本字符串传递给 getCipherDataDoc 私有方法。该方法创建并返回带有 CipherValue 子标记的 CipherData 标记,该标记含有用 Base 64 编码的密码文本字符串。类似地,创建 EncryptionMethodds:KeyInfo 标记。这三个标记 ― 即 CipherData (携带 CipherValue 子标记)、 EncryptionMethodds:KeyInfo ― 是作为 EncryptedData 标记的子标记随后添加的。 EncryptedData 标记实际上被装入到 DOM 文档对象 encDataObj 中,该对象被序列化并返回给 simulateBookSellersEnd 方法。

2. 用 XML 加密对 XML 文件中的元素加密

图书销售商可以用会计部门的秘钥对 XML 文件的支付信息部分加密,而使文件内容其余部分保持不加密,以便销售部门查看。可以通过对 Order.xml 文件中的 Payment 元素加密来完成这个处理。信用卡信息也变得安全,因为它驻留在加密的 Payment 元素的子节点中。由于安全性要求规定必须对未授权的查看者保密支付方式(诸如信用卡或银行支票),对 Payment 元素加密就做到了这一点。

在这种情况中,类 demoXmlEncApp 中的 simulateBookSellersEnd 函数生成对类 XmlEncryption 的公用方法 encryptElementOfXmlFile 的调用。私有方法 getElement 返回元素节点,随后对它序列化并加密以产生 CipherData 标记。 EncryptedData 标记的创建过程与前一种方法相同,只是这种方法通过调用私有方法 replaceElement ,将 clearDoc 中的 Payment 元素替代为 EncryptedData 元素。完成替代后,序列化 clearDoc 并返回。

3. 用 XML 加密对 XML 文件中的元素内容加密

图书销售商可以实行的第三种加密选择是只加密 Order.xml 中的信用卡号。调用元素内容加密方法,它只对 CardNo 元素的文本内容加密。这就提出了一个重要问题:使用元素加密就可以实现同样的内容加密,那为什么还要提出内容加密呢?使用哪种方法取决于文档的安全性策略;如果存在透露元素名称或其属性的特殊需要,而又要保持其内容安全时,内容加密就很方便。

如果图书销售商只想保密信用卡号,就加密 Order.xml 中元素 CardNo 的文本内容。 simulateBookSellersEnd 方法调用公用方法 encryptElementContentOfXmlFile ,它与 encryptElementOfXmlFile 方法的不同之处仅仅在于,它对元素的内容操作,而不是元素本身。

使用 XML 加密来解密 XML 加密的文件

出版社一方接收 XML 加密的文件时,就要对该文件解密。对于所述的所有三种方法,解密的方法都是 getDecryptedDatademoXmlEncApp 中的 simulateBookSellersEnd 方法将 XML 加密的文件序列化成文本字符串,并将它传递给 getDecryptedData 方法进行解密。

getDecryptedData 方法标识 EncryptedData 标记,并抽取出用 Base 64 编码的密码值。XML 加密标记中存在着解密需要的所有信息:加密算法的名称、加密的数据类型以及加密密钥的名称。

注:XML 加密规范没有规定 XML 加密标记内 应该提供所有这些信息。这些属性的提供是可选的。应用程序可能通过某些其它方式提供这些信息,但演示应用程序和样本 XML 加密实现假定 XML 加密标记内提供了所有这些信息。

getDecryptedData 方法现在根据密钥和算法名称生成解密密钥。接着它将抽取出的用 Base 64 编码的密码值、解密密钥以及算法名称传递给名为 Decrypt 的方法(见 密码术中的研究)。

Decrypt 方法将已译码和解密的数据作为文本字符串返回。依照 EncryptionData 元素的类型属性对该文本字符串操作,该类型属性可能是以下属性中的任意一个:

  • 整个 XML 文件,作为新的 XML 文件保存到磁盘
  • 元素,替代 EncryptedData 标记以产生原始 XML 文件
  • 元素内容,替代 EncryptedData 标记以产生原始 XML 文件

超级加密

使用超级加密时,您可以用会计部门的秘钥只加密支付信息,以产生元素加密的 XML 文件。接着,通过使用销售部门的秘钥对这个结果文件完成加密,这就产生了超级加密的 XML 文件。

这里,我必须指出:使用 XML 加密规范可以对 XML 加密的文件再加密,这会产生超级加密的 XML 文件。但是,您不能使用 XML 加密对 EncryptedDataEncryptedKey 元素的特定子元素加密。换句话说, EncryptedData 元素不能是另一个 EncryptedData 元素的父元素或子元素。

依据 XML 加密规范,还可以对任意数据(例如,.jpg 图像或 Web 上几乎任何内容)加密。这几乎等同于整个 XML 文件的加密;唯一区别是 EncryptedData 元素类型属性的值不同(请参阅 参考资料)。

IANA 值
在本系列文章的 第 1 部分中,我使用了因特网赋号管理局(Internet Assigned Numbers Authority (IANA))类型定义作为 EncryptedData 标记中 Type 属性的值。第 1 部分基于 2001 年 10 月 18 日的 XML 加密 W3C 工作草案。最近,XML 加密已成为 W3C 候选建议书,它不再使用 IANA 值(请参阅 参考资料)。

密码术

XML 加密规范列出了许多必需的和可选的密码术算法,包括:

  • 块加密
  • 流加密
  • 密钥传送
  • 密钥协议
  • 对称密钥包
  • 消息摘要
  • 消息认证

另外,Base 64 编码算法(请参阅 参考资料)也是必需的。在可以将每个密码插入到 XML 文档之前,它们都必须用 Base 64 编码。在这个演示中,我使用了 SunJCE 密码术供应商的 TripleDES 块加密算法。加密方式是块大小为 8 字节的 CBC(Cipher Block Chaining,密码块链接)。

XmlEncryption 类使用由以下方法实现的 JCA/JCE 密码术:

  • getEncryptedData这个方法接受文本字符串,并使用 TripleDES 算法对它加密。对于对称加密(请参阅 参考资料),除了加密的明文数据以外,还需要加密密钥。这个密钥可以用作为类 XmlEncryption 的私有属性 encKey 。输入文本字符串转换成了字节数组,并用它填充。我对需要将明文数据字节放在 8 字节块的加密使用块密码算法,所以我用一些字符填充最后一个不完整的块。样本实现使用空格(" ")作为填充字符。

    接着创建 Cipher 类对象,并以加密方式对它初始化。随后我将初始向量(IV)抽取到字节数组,对明文数据进行块加密,并将 IV 字节置于加密的数据字节之前。使用类 XmlEncryption 的方法 getBase64Encoded 时,结果字节数组转换成了用 Base 64 编码的字符串,随后被返回。

  • Decrypt这个方法与 getEncryptedData 方法根本相反。它接受用 Base 64 编码的密码字节数组,并对它译码和解密以返回明文数据字符串。接着将 IV 与真正的密码字节数组分离。这样就用解密方式创建并初始化了 Cipher 类对象。接着对该密码字节数组解密,解密的字节数组作为文本字符串返回。

我已经对 TripleDES 块密码算法提供了支持,但只用于演示。作少量修改,您还可以使用诸如 AES 等其它算法。

这个简单实现演示了 XML 加密如何能够成为用于较大型以及比较复杂业务应用程序的可行的安全性框架。


XML 加密和 SOAP

简单对象访问协议(Simple Object Access Protocol),或简称为 SOAP(请参阅 参考资料)是用于数据交换的轻量级的以 XML 为基础的协议。它促进了由远程过程调用和响应产生的数据传送。它设计成用于分布式和远程应用程序中,并且它是 Web 服务的主要组件。SOAP 提供了包含消息及其处理信息的信封。由于这个信封内容很机密,所以安全性就是您必须解决的问题。XML 加密对此问题提供了无缝的解决方案。

SOAP 本身是 XML,它让您使用 XML 加密以任何合适的方式随意处理加密问题。例如,您可以决定对整个 SOAP 主体加密,也可以对部分主体加密。然而,XML-SEC 是 W3C 的成果,它的目的在于使实现基于 SOAP 的 Web 服务中的安全性的方法标准化。目前,它不包含 XML 加密;我期望 XML 加密或类似的加密方法将来成为它的一部分。

结束语

在第 1 部分中,我介绍了 XML 加密,并讨论了它在实现安全的数据交换中的使用。我详细描述了不同的 XML 加密标记的使用,并提出了基于 DOM 的用于 XML 加密的 Java API。

在这个第 2 部分中,我研究了典型的数据交换方案,其中您可以使用 XML 加密概念。我还演示了各种类型的 XML 加密方法:加密整个 XML 文件、加密 XML 文件的元素或者加密 XML 元素的内容。我还讨论了解密、超级加密以及 XML 加密概念在基于 SOAP 的 Web 服务中的应用。


参考资料

关于作者

XML 顾问 Bilal Siddiqui 在 1995 年从巴基斯坦的拉合尔工程与技术大学获得电子工程学位。接着他开始设计用于工控系统的软件解决方案。后来他转向 XML,并用他在 C++ 方面的编程经验构建了基于 Web 和 WAP 的 XML 处理工具、服务器端解析解决方案以及服务应用程序。可以通过 wap_monster@yahoo.com与他联系。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:48954次
    • 积分:614
    • 等级:
    • 排名:千里之外
    • 原创:0篇
    • 转载:40篇
    • 译文:1篇
    • 评论:3条
    文章存档
    最新评论