XML 安全: 实现安全层,第 2 部分

转载 2006年05月27日 11:23:00

核心技术——XML 加密与 XML 签名
级别: 中级
Manish Verma, 首席架构师, Second Foundation
2003 年 12 月 01 日

许多新兴的技术,比如 Web 服务,都将 XML 广泛应用于数据交换。因此,XML 在传输和存储时的安全性成为非常重要的问题。本次系列文章介绍了保护 XML 的各种技术。第 1 部分介绍了 XML 安全性方面的基本支持技术。本文在前一部分的基础上,介绍了保障 XML 安全性的核心技术——XML 加密和 XML 签名。本文还循序渐进地介绍了用这些技术保护 XML 消息的过程。

有许多现有的加密技术,比如安全套接字层(Secure Sockets Layer,SSL),可以对 XML 文档进行加密,这和其他任何文档都一样,那么为什么还需要另一种加密标准呢?在本文中,我将从考察其目标和动机开始,引出另一种加密标准—— XML 加密(XML Encryption)。

XML 加密

XML 加密的首要目标是:

  • 支持对任意数字内容的加密,包括 XML 文档。
  • 确保经过加密的数据不管是在传输过程中还是在存储时,都不能被未经授权的人员访问到。
  • 即便在消息传送中的每一跳,都能维持数据的安全性——这句话的意思是,不仅数据正在传输的过程中要保证安全性(这就是 SSL 所作出的保证),当数据在某个特定的节点停留的时候,也要保证其安全性。
  • 以 XML 形式表现被加密的数据。
  • 可以从 XML 文档中选出一部分内容进行加密。

我们拿这个目标与基于 HTTP 的 SSL(又称 HTTPS)必须提供的功能进行比较。如果使用基于 HTTP 的 SSL,整条消息都会被加密;在第一个目的地,整条消息又被解密,在它被重新全部加密传输到第二跳的节点之前,可能受到嗅探器的威胁。基于 HTTP 的 SSL 提供的加密仅仅在传输的过程中存在,它是不持久的。

XML 加密概览

设计目标 之一清晰地表明,经过加密的 XML 数据应该用 XML 的形式表现。在得到的 XML 中,有两个重要的元素值得理解清楚: <EncryptedData> <EncryptedKey><EncryptedData> 中包含除加密密钥之外所有经过加密的内容。当对加密密钥进行加密的时候,得到的结果就放置在 <EncryptedKey> 元素中。

除了加密过的内容以外,XML加密还允许您在上面讨论的两个元素中指定用于加密的算法,或者是加入用于加密的密钥。这意味着您即便不将它们分别保存,也可以在后续引用这些数据;或者通过其他传输机制发送给接收方。

注意:XML 加密没有定义任何新的加密算法,只使用已有的算法。

XML 加密过程

在本节中,我先向您展示一段普通的 XML 代码,然后介绍用 XML Encryption 标准(参阅 参考资料)对这段代码进行加密的各个步骤。我将从清单 1 中显示的 XML 开始。

清单 1. XML 示例



清单 2 示范了如何对 清单 1中的部分 XML 进行加密。在这个清单之后,我解释了加密过程中的每一个步骤。

清单 2. XML 加密



步骤 1:将 XML 转换成 DOM 对象,如清单 3 所示:

清单 3. 根据 XML 创建 DOM 对象



步骤 2:获得共享密钥(shared secret)。您要用这个密钥来加密 XML 内容。本文附带的源代码使用的 XML 加密方法只能识别三重 DES(Triple-DES)加密算法,因此我就用这种算法创建密钥。

步骤 3:参照本系列文章 第 1 部分所述,获得公-私密钥对中的公钥;您需要用这个公钥给共享密钥加密。您从第 1 部分中可以看到,这个公钥是基于 RSA 算法生成的。

步骤 4:利用一个数据加密密钥、一个密钥加密密钥、与这两个密钥相关联的算法、以及将来包含在输出信息中的密钥信息,根据它们来创建一个 Encryptor 对象。创建 Encryptor 对象时指定的算法必须与密钥相符。 Encryptor 是加密过程中的主要对象。它的类在 com.verisign.xmlenc 这个包中。 Encryptor 根据 W3C XML Encryption 规范进行加密。您可以指定想要使用哪种加密类型,是 Element 还是 Content。在 清单 2 中,加密类型是 Element,这也是默认的类型。 Encryptor 要理解 XPath 表达式,这样才能识别出需要加密的 XML 元素。

步骤 5:最后一步,调用 Encryptor 对象的 encrypt 或者 encryptInPlace 方法,并将 XPath 作为输入参数传入。XPath 定义了 XML 内部需要进行加密的元素。这个元素的所有子元素,以及 XPath 所指向的属性也都要进行加密。在本例中,您加密的是 XML 中的 /PurchaseOrderRequest/Payment 元素。 encryptencryptInPlace 两个方法都用传入的共享密钥对 XPath 指定的 XML 元素进行加密,两种方法也都用公钥对共享密钥进行加密,并将加密结果嵌入到 XML 加密后的内容之中。这两种方法的唯一区别在于, encrypt 返回一个全新的 DOM 文档,其中包含加密后的数据,而 encryptInPlace 方法对原有的文档本身进行修改,使其中包含加密后的数据。加密过的 XML 如清单 4 所示。

清单 4. 加密后的 XML



清单 4是部分加密的 XML 代码片断。只有当接收者具有与加密数据时使用的公钥相对应的私钥时,才能阅读这部分被加密的数据。

最后说一下,清单 5 中的代码可以对加密过的 XML 进行解密。

清单 5. XML 解密



清单 5示范了当您有正确的私钥时,如何对加密的数据进行解密。下面的步骤解释了解密的过程。

步骤 1:将加密过的 XML 转换成 DOM 对象,这一步与加密过程相同。

步骤 2:根据用于加密 XML 的公钥,获取密钥对中对应的私钥。请注意,解密过程使用的是加密 XML 时使用的公钥所对应的私钥。.

步骤 3:创建 XPath 以及相关名称空间,用于表示加密过的数据在加密过的 XML 中的位置。在本例中,XPath 的值是 //xenc:EncryptedData 。加密过的数据总是在加密过的 XML 中的 xenc:EncryptedData 元素下面,而与哪个元素被加密无关。XPath 为 //xenc:EncryptedData 则表示,从 XML 中可能出现加密数据的任何地方查找 EncryptedData 元素。

步骤 4:用解密密钥和需要解密的加密数据所在的位置创建 Decryptor 对象。 Decryptor 是解密过程中的主要对象。它的类在 com.verisign.xmlenc 包中。 Decryptor 根据 W3C XML Encryption 规范进行解密(参阅 参考资料)。解密过程支持 Element 和 Content 两种类型。为了识别需要解密的 XML 元素, Decryptor 要能理解 XPath 表达式。

步骤 5:解密过程的最后一个步骤是在 Decryptor 对象中调用 decryptInPlace 或者 decrypt 方法。这两种方法调用都使用提供的私钥来解密共享密钥(共享密钥是已加密消息中的一部分),然后用这个共享密钥来解密消息的其余部分。两种调用之间的唯一区别在于, decrypt 对 XML 解密之后创建一个新的 DOM 对象,而 decryptInPlace 在作为输入接收的同一 DOM 对象中解密消息。

XML 签名

数字签名已经应用了相当长一段时间,任何数字化内容都可以用公钥密码标准(Public Key Cryptography Standards,最常用的是 PKCS#7 签名)进行数字签名。安全多用途 Internet 邮件扩展(Secure Multipurpose Internet Mail Extensions,S/MIME)允许将数字签名附加到电子邮件消息上,这样接收方就可以验证签名者的身份。

XML 签名是对现有数字签名基础设施的扩展。下面列出了创建 XML 签名的一些目标和动机:

  • 在数字签名周围建立一些结构,这样就可以用 XML 文档的形式来表现数字签名。
  • 实现对一部分 XML 进行签名,而剩余部分则不签名。
  • 实现对同一份 XML 文档的不同部分使用多于一种的数字签名。
  • 不仅仅在文档传送和通信的时候使用签名,还要使签名能够持久保留。

XML 签名概览

XML 签名可以用于对包括 XML 文档在内的任何数字内容进行签名。对数字内容进行签名的过程分为两个阶段。在第一阶段中,对数字内容进行整理,得到的结果放在一个 XML 元素中。第二阶段挑选出经过整理的值,并对其进行签名。这样做的原因非常简单:对原始内容进行整理之后,可以得到一个很小的但是唯一的加密结果(称为摘要),这样比对原始内容进行签名花费的时间少。

当 XML(或其中的一部分)经过数字签名之后,得到的 XML 签名用一个 XML 元素表现出来,这个元素的标识是 <Signature> ,最初的内容与这个数字签名的关系基于下面几种 XML 签名类型:

  • 封外签名(Enveloping signature)<Signature> 元素中包含了进行数字签名的元素。被签名的元素成为了 <Signature> 元素的子元素。
  • 封内签名(Enveloped signature)<Signature> 元素成为被签名数据的子元素。 <Signature> 元素通过它其中的 <Reference> 元素提供的信息引用被签名的元素。
  • 分离签名(Detached signature )<Signature> 元素与被签名的元素各自独立存在。被签名的元素和 <Signature> 元素可以同属于一个文档,或者, <Signature> 元素也可以在另一个完全不同的文档中。

除了引用被签名的数字内容之外, <Signature> 元素还包括了有关如下方面的信息:

  • 用于使数字内容规范化的方法。
  • 为待签名的规范化元素生成签名的算法。
  • 指定在整理之前如何处理待签名元素的附加信息。

XML 签名过程

接着 清单 1中的例子看,我现在将带你经历对 XML 元素进行数字签名的全过程。清单 6 示范了如何对部分 XML 进行数字签名;签名过程中的每一步骤都会在这个清单后面解释。

清单 6. 数字签名的过程



步骤 1:同前面加密的步骤一样,将需进行数字签名的 XML 转换为 DOM 对象。

步骤 2:获得您在本系列第 1 部分的“ 生成公-私密钥对”一节中生成的密钥对,其中同时包括公钥和私钥。您将用私钥对内容进行数字签名,然后将公钥随着经过数字签名的消息一起发送到接收方,以便用来验证其中的数字签名。前面讲过,公-私密钥对是基于 RSA 算法的。

步骤 3:根据需要签名的 DOM 文档、用来签名的私钥以及用于验证的公钥,创建一个 signer 对象。验证用的公钥并不是一定要有。 signer 是数字签名过程中的主要对象。它的类在 com.verisign.xmlsig 包中。 signer 对象根据 W3C XML Signature 规范(参阅 参考资料)对 XML 文档签名。共支持全部三种签名模式:封外、封内以及分离模式。

步骤 4:指定 XML 中的哪一部分需要签名。通过增加到 Signer 对象的引用,可以指定数字签名的 XML 位置。增加引用的方法是调用 Signer 对象中的 addReference 方法。需要签名的元素的 XPath 也作为一个参数提供给 addReference 。您可以多次调用 addReference ,来指定想要进行签名的不同元素。

步骤 5:最后一步是对 XML 签名,您可以通过调用 signer 对象中的 sign 方法来完成。当调用 sign 方法时,如果不传递任何参数的话,生成的就是封外签名。调用带有 XPath 参数的 sign 方法,并且数字签名放置在文档中,则生成封内签名。

结束语

随着这个 XML 安全专题深入到这里,我已经定义了安全的含义,并讨论了 XML 规范化、PKI 基础设施、XML 加密和 XML 签名。通过介绍 XML 安全背后的理论,并竭力向您展示 XML 加密和数字签名有多么容易,希望这一切努力能为您揭开 XML 安全的神秘面纱。

在今后的文章中,我将要讨论安全性断言标记语言(Security Assertion Markup Language,SAML)和 XML 密钥管理系统( XML Key Management System,XKMS)。SAML 可以用于在不同的协作实体之间传送凭证以及其他一些与主题、人等相关的信息,而不会损失信息的所属关系。通过将管理公钥基础设施(Public Key Infrastructure,PKI)的复杂性从客户机应用程序提取到一个可信任的第三方机构中, XKMS 使得管理 PKI 变得非常容易。

参考资料

关于作者

Manish Verma 是全球性 IT 服务公司 Second Foundation 的首席架构师。Manish 在软件开发生命周期的各个方面具有 10 年的工作经验,曾经为运行异构系统的的客户组织设计集成策略。Manish 的集成经验建立在他对各种技术的理解之上,其中包括各种遗留系统、.NET、Java 技术以及最新的中间件。在加盟 Second Foundation 之前,Manish 先后在 Quark Inc.、Hewlett Packard、Endura Software 和 The Williams Company 等公司担任软件架构师和技术负责人。可以通过 mverma@secf.com 与 Manish 取得联系。

第二部分 线程安全(2)——ThreadLocal变量

在前面已经讲到了,变量安全问题。1.尽量不让线程运行在同一个对象实例上,这是效率比较低的方式,而且在有的场合下,线程之间共享对象是不可避免的。2.把可能被共享的变量封装在方法内部,使其成为方法的内部变...
  • cuiran
  • cuiran
  • 2011年01月19日 09:09
  • 2622

J2EE的Servlet实现SSL(安全套接字层)会话

SSL(Secure Socket Layer,安全套接字层)是一种运行在TCP/IP之上和像HTTP这种应用层协议之下的加密技 术. SSL是在HTTPS协议中使用的加密技术.SSL可以让采用SS...

C#——安全护卫设计和部分实现

其实这个是很久以前改的一个软件了,修改了大量的fooying的代码,3q fooying,他的个人博客点击打开链接 简单备注:该软件使用C#写成,内容见下图集,其中大部分功能都已经能够很好的执行,但...
  • hannax
  • hannax
  • 2012年06月23日 22:31
  • 291

Windows Azure 安全最佳实践 - 第 2 部分:Azure 提供哪些现成可用的安全机制

在WindowsAzure 安全最佳实践 - 第 1 部分:深度解析挑战防御对策中,我介绍了威胁形势以及在您的应用程序中采用深度防御的计划。   在本部分中,我将说明 Windows Azure...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:XML 安全: 实现安全层,第 2 部分
举报原因:
原因补充:

(最多只允许输入30个字)