### 启用 XML 安全性(1)

XML 是因特网以及近来 Web 服务持续增长和开发的主要支持者。但是，在实现 XML 语言的全部能力之前，还有许多与安全性相关的工作要做。目前，加密整个 XML 文档、测试其完整性和确认其发送方的可靠性是一个简单的过程。但是，越来越有必要对文档的某些部分也使用这些功能，以便以任意顺序加密和认证以及涉及不同用户或发起方。目前，在与 XML 相关的安全性领域方面开发规范的最重要部分是 XML 加密、XML 签名、XACL、SAML 和 XKMS。本文介绍前两个。
简介
XML 已经成为一种用于在因特网上交换数据的有价值机制。SOAP，这种发送 XML 消息的方式，促使进程以一种前所未有的方式相互通信，而 UDDI 看起来正在快速成为整合 Web 服务的供应商和用户的标准；服务本身是 XML 以 WSDL （即“Web 服务描述语言”）形式描述的。如果没有 XML，将不可能有这种灵活性和能力，并且，正如许多人所说的，将有必要发明元语言。
安全性领域是另一个快速增长的领域。在不同团体之间建立信任的传统方法在公共因特网上已不合适，实际上，在大型 LAN 和 WAN 上也不合适。在这些情况下，基于非对称密码术的信任机制可能会非常有用，但实际上，部署和密钥管理的方便性、互操作性的范围和提供的安全性远不如各种的“公钥基础设施”（Public Key Infrastructures (PKI)）的热情的供应商曾让我们相信的那样。处理层次数据结构，以及带有机密、访问权限或完整性等不同需求的数据的子集特别困难。另外，具有不同于 XML 文档的现今标准安全性控制的应用程序一点都不简单。
目前，一些团体正积极投身于检查这些问题和开发标准的活动中。其中主要的相关开发是 XML 加密和相关的 XML 签名、“可扩展访问控制语言（XACL）”和相关的“安全性断言标记语言（SAML — 以前是互为竞争对手的 AuthML 和 S2ML 的结合）”。所有这些都由 OASIS 和“XML 密钥管理规范（XKMS）”驱动。本文将 介绍 XML 加密和 XML 签名。
XML 加密和 XML 签名
象其它任何文档一样，可以将 XML 文档整篇加密，然后安全地发送给一个或多个接收方。例如，这是 SSL 或 TLS 的常见功能，但是更令人感兴趣的是如何对同一文档的不同部分进行不同处理的情况。XML 的一个有价值的好处是可以将一整篇 XML 作为一个操作发送，然后在本地保存，从而减少了网络通信量。但是，这就带来了一个问题：如何控制对不同元素组的授权查看。商家可能需要知道客户的名称和地址，但是，无需知道任何正在使用的信用卡的各种详细信息，就像银行不需要知道购买货物的详细信息一样。可能需要防止研究人员看到有关个人医疗记录的详细信息，而管理人员可能正好需要那些详细信息，但是应该防止他们查看医疗历史；而医生或护士可能需要医疗详细信息和一些（但不是全部）个人资料。
密码术现在所做的远远不止隐藏信息。消息摘要确定文本完整性，数字签名支持发送方认证，相关的机制用于确保任何一方日后无法拒绝有效事务。这些都是远程交易必不可少的元素，现在，用于处理整个文档的机制开发得相当好。
有了一般的加密，对 XML 文档整体进行数字化签名不是问题。然而，当需要对文档的不同部分（可能由不同的人）签名，以及需要与选择性的方法一起来这样做时，就会出现困难。也许不可能或者不值得强制不同部分的加密工作由特定人员按特定顺序进行，然而成功地处理文档的不同部分将取决于是否知道这点。此外，由于数字签名断言已经使用了特定专用密钥来认证，所以要小心签名人是以纯文本形式查看文档项的，这可能意味着对由于其它原因而加密的部分内容进行了解密。在另一种情况下，作为更大集合中的一部分，可能对已经加密过的数据进行进一步加密。在牵涉单一 XML 文档（可能由一些不同的应用程序和不同的用户处理在工作流序列中使用的 Web 表单或一系列数据）的事务集中考虑的不同可能性越多，就越可能看到巨大的潜在复杂性。
还有其它问题。XML 语言的强项之一是，搜索是明确的，无二义性的：DTD 或 Schema 提供了相关语法的信息。如果将包括标记在内的文档的一部分作为整体加密，就会丧失搜索与那些标记相关的数据的能力。此外，如果标记本身被加密，那么一旦泄漏，它们将被利用对采用的密码术进行纯文本攻击。
这些是工作组正在考虑的一些方面。
XML 加密示例
XML 加密语法的核心元素是 EncryptedData 元素，该元素与 EncryptedKey 元素一起用来将加密密钥从发起方传送到已知的接收方，EncryptedData 是从 EncryptedType 抽象类型派生的。要加密的数据可以是任意数据、XML 文档、XML 元素或 XML 元素内容；加密数据的结果是一个包含或引用密码数据的 XML 加密元素。当加密元素或元素内容时，EncryptedData 元素替换 XML 文档加密版本中的该元素或内容。当加密的是任意数据时，EncryptedData 元素可能成为新 XML 文档的根，或者可能成为一个子代元素。当加密整个 XML 文档时，EncryptedData 元素可能成为新文档的根。此外，EncryptedData 不能是另一个 EncryptedData 元素的父代或子代元素，但是实际加密的数据可以是包括现有 EncryptedData 或 EncryptedKey 元素的任何内容。
加密工作草案给出了一些示例来演示：加密的颗粒度如何根据要求的不同而不同，以及可能出现什么结果。清单 1 中的代码片断显示了带有信用卡和其它个人信息的未加密 XML 文档。在某些情况下（例如，隐藏支付机制的信息），可能希望加密除客户名称以外的所有信息，清单 2 的代码片断演示了如何这样做。
清单 1. 显示 John Smith 的银行帐户、5000 美元限额、卡号和有效期的的信息
<?xml version='1.0'?>
<PaymentInfo xmlns='http://example.org/paymentv2'>
<Name>John Smith<Name/>
<CreditCard Limit='5,000' Currency='USD'>
<Number>4019 2445 0277 5567</Number>
<Issuer>Bank of the Internet</Issuer>
<Expiration>04/02</Expiration>
</CreditCard>
</PaymentInfo>
清单 2. 除名称之外全部被加密的加密文档
<?xml version='1.0'?>
<PaymentInfo xmlns='http://example.org/paymentv2'>
<Name>John Smith<Name/>
<EncryptedData Type='http://www.w3.org/2001/04/xmlenc#Element'
xmlns='http://www.w3.org/2001/04/xmlenc#'>
<CipherData><CipherValue>A23B45C56</CipherValue></CipherData>
</EncryptedData>
</PaymentInfo>
但是，在其它情况下，可能只需要隐藏一些敏感内容 — 可能来自商家或其它第三方 — 清单 3 演示了这点。（请注意，显示了与加密内容相关的标记名。）
清单 3. 只隐藏了信用卡号的加密文档
<?xml version='1.0'?>
<PaymentInfo xmlns='http://example.org/paymentv2'>
<Name>John Smith<Name/>
<CreditCard Limit='5,000' Currency='USD'>
<Number>
<EncryptedData xmlns='http://www.w3.org/2001/04/xmlenc#'
Type='http://www.w3.org/2001/04/xmlenc#Content'>
<CipherData><CipherValue>A23B45C56</CipherValue>
</CipherData>
</EncryptedData>
</Number>
<Issuer>Bank of the Internet</Issuer>