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 >
<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 >
<Name>John Smith<Name/>
<EncryptedData Type=’http://www.w3.org/2001/04/xmlenc#Element’
>
<CipherData><CipherValue>A23B45C56</CipherValue></CipherData>
</EncryptedData>
</PaymentInfo>
但是,在其它情况下,可能只需要隐藏一些敏感内容 ― 可能来自商家或其它第三方 ― 清单3演示了这点。(请注意,显示了与加密内容相关的标记名。)
清单3. 只隐藏了信用卡号的加密文档
<?xml version=’1.0′?>
<PaymentInfo >
<Name>John Smith<Name/>
<CreditCard Limit=’5,000′ Currency=’USD’>
<Number>
<EncryptedData
Type=’http://www.w3.org/2001/04/xmlenc#Content’>
<CipherData><CipherValue>A23B45C56</CipherValue>
</CipherData>
</EncryptedData>
</Number>
<Issuer>Bank of the Internet</Issuer>
<Expiration>04/02</Expiration>
</CreditCard>
</PaymentInfo>
可能还有必要加密文档中的所有信息,清单4演示了这点。
清单4. 隐藏了全部内容的加密文档
<?xml version=’1.0′?>
<EncryptedData
Type=’http://www.isi.edu/in-notes/iana/assignments/media-types/text/xml’>
<CipherData><CipherValue>A23B45C56</CipherValue></CipherData>
</EncryptedData>
CipherData可以封装,也可以引用原始加密数据。在第一种情况下,CipherValue元素的内容显示原始数据,而在第二种情况,使用CipherReference元素,这包括了一个指向加密数据位置的URI。
规范的XML
对应用了密码散列算法的消息进行最轻微的更改也会产生不同的值。这为消息完整性方面提供了信任,并适于通常用法,但是也引入了进一步的复杂性 ― 两个XML文档虽然在逻辑上相等,但可能在确切文本比较中不同。象行定界符、空标记、在属性中使用十六进制而不是名称以及在特定情况下存在注释或注释变体这样的事情都可以成为文档的逻辑结构不受影响而实际彼此不同的实例。规范的XML规范描述了一种生成文档的物理表示(也成为范式)的方法,该范式解释允许的变体,以便如果两个文档具有同一范式,则认为两个文档在给定应用程序上下文中是逻辑相等的。
对于加密、特别是数字签名来说,这尤为重要,因为很明显,逻辑上相同的文本变体不应该表示文档的完整性及其发送方的认证是可疑的。用不同工具(譬如,解析器)生成不同文本(并因而生成不同消息摘要)进行处理时也可能发生这样的事。因此,在生成签名和验证计算期间,应该在范式上进行消息摘要。如果摘要匹配,这将确定:即使文本形式可能不同,它们在其上计算的范式也匹配。
XML签名示例
可以将XML签名应用到任意数据内容。那些应用到相同XML文档中数据的签名称为封装或被封装的签名,而那些数据在签名元素外部的签名称为分离签名。清单5取自签名候选推荐文档,它是一个简单分离签名的实例。
清单5. 一个简单分离签名的示例
[s01] <Signature Id=”MyFirstSignature”
>
[s02] <SignedInfo>
[s03] <CanonicalizationMethod Algorithm=”http://www.w3.org/TR/2001/
REC-xml-c14n-20010315″/>
[s04] <SignatureMethod Algorithm=”http://www.w3.org/2000/09/
xmldsig#dsa-sha1″/>
[s05] <Reference URI=”http://www.w3.org/TR/2000/REC-xhtml1-20000126/”>
[s06] <Transforms>
[s07] <Transform Algorithm=”http://www.w3.org/TR/2001/REC-xml-c14n-
20010315″/>
[s08] </Transforms>
[s09] <DigestMethod Algorithm=”http://www.w3.org/2000/09/
xmldsig#sha1″/>
[s10] <DigestValue>j6lwx3rvEPO0vKtMup4NbeVu8nk=</DigestValue>
[s11] </Reference>
[s12] </SignedInfo>
[s13] <SignatureValue>MC0CFFrVLtRlk=…</SignatureValue>
[s14] <KeyInfo>
[s15a] <KeyValue>
[s15b] <DSAKeyValue>
[s15c] <p>…</p><Q>…</Q><G>…</G><Y>…</Y>
[s15d] </DSAKeyValue>
[s15e] </KeyValue>
[s16] </KeyInfo>
[s17] </Signature>
实际签名的信息是位于s02行和s12行之间,即SignedInfo元素。在签名的部分中包含用于计算SignatureValue元素的算法的引用,而那个元素本身位于签名部分之外(在s13行上)。s04行上的SignatureMethod引用的是将规范的SignedInfo转换成SignatureValue所用的算法。它是密钥相关的算法和摘要算法(在这里是DSA和SHA-1)的组合,可能还具有象填充这样的操作。KeyInfo元素(在这里位于s14行和s16行之间―该元素是可选的)指出用来验证签名的密钥。
转换
正如前面所提到的,加密、签名、修改和可能进行的更多签名所发生的顺序有很多种可能性。用户可能需要向已经部分加密或部分签名的表单字段中输入更多数据,并且需要能够在不妨碍以后的验证和解密的前提下这样做。为解决这种情况,W3C最近发布了一个有关XML签名的解密转换工作草案。
下面这个示例摘自那个文档,它演示了如何建议文档接收方采用正确的解密和签名验证顺序。第一个代码段显示了要签名的文档部分―order元素;其中,第7行到第11行的cardinfo元素是关于个人和财务方面的详细信息,它是纯文本,但也存在一些加密数据(第12行)。
清单6. XML文档中的order元素
[01] <order Id=”order”>
[02] <item>
[03] <title>XML and Java</title>
[04] <price>100.0</price>
[05] <quantity>1</quantity>
[06] </item>
[07] <cardinfo>
[08] <name>Your Name</name>
[09] <expiration>04/2002</expiration>
[10] <number>5283 8304 6232 0010</number>
[11] </cardinfo>
[12] <EncryptedData Id=”enc1″>…</EncryptedData>
[13] </order>
清单7. 经过签名和进一步加密、且现在显示转换信息的order文档
[01] <Signature >
[02] <SignedInfo>
[03] …
[04] <Reference URI=”#order”>
[05] <Transforms>
[06] <Transform Algorithm=”http://www.w3.org/2001/04/
xmlenc#decryption”>
[07] <DataReference URI=”#enc1″
/>
[08] </Transform>
[09] <Transform Algorithm=”http://www.w3.org/TR/2000/
CR-xml-c14n-20001026″/>
[10] </Transforms>
[11] …
[12] </Reference>
[13] </SignedInfo>
[14] <SignatureValue>…</SignatureValue>
[15] <Object>
[16] <order Id=”order”>
[17] <item>
[18] <title>XML and Java</title>
[19] <price>100.0</price>
[20] <quantity>1</quantity>
[21] </item>
[22] <EncryptedData Id=”enc2″
>…</EncryptedData>
[23] <EncryptedData Id=”enc1″
>…</EncryptedData>
[24] </order>
[25] </Object>
[26] </Signature>
第1行到第26行的Signature元素现在包含前面的order元素(位于第16行到第24行),和以前的加密纯文本cardinfo(显示在第22行这一行中)。有两个转换引用:解密(第6行到第8行)和规范化(第9行)。解密转换指示签名验证器解密除DataRef元素中第7行指定的数据之外的所有加密数据。解密了第22行中的EncryptedData元素之后,规范化order元素并且恰当地验证签名。
其它相关语言和规范
隐藏XML文档中的敏感信息、建立完整性以及认证这些文档的不同部分的来源主要通过遵循加密和签名规范中列出的步骤来处理的,在引用的W3C草案中描述该规范。另外,还有其它紧密相关的领域,例如认证用户或系统、标识授权级别和管理密钥,所有这些都与XML安全性相关。
SAML是一个由OASIS驱动的模型,它尝试融合相互竞争的AuthML和S2ML规范,使认证和授权信息的互换便于进行。“可扩展访问控制标记语言”是与SAML紧密相关的,但它更着重于特定XML文档的上下文中的面向主题特权对象的安全性模型,它也由OASIS指导,又是被称为XACML或XACL(即使在同一些文档中)。通过用XACL编写规则,策略制订者可以定义,对于特定XML文档和前面所述的情况中的相关事情,由谁来实施哪些访问特权。
W3C委员会现在正在考虑XKMS,它打算建立一个位于XML签名标准顶部的密钥管理协议。有了SAML、XACL和其它倡议,XKMS是构成应用于XML文档的安全性这个大框架中的重要元素。有了它,可以立杆见影地极大简化认证和签名密钥的管理;它通过将数字证书处理功能、撤回状态检查和认证路径位置和验证从所涉及的应用程序分离来做到这点 ― 例如,通过把密钥管理委托给因特网Web服务。
在满足使用的便利性、可靠性和强健性方面,XML安全性还有很多路要走。但是目前,正在取得良好的进展。
关于作者
Murdoch Mactaggart是一名自由撰稿作家和商业咨询人员,他编写有关软件开发、安全性和密码术、因特网以及围绕这些领域的商业和管理事项的文章。他首先于1979年购买了一台电脑,运行他当时作为商人所从事的古董书和“早期绘画大师的作品”版画方面以及日本绘画方面的业务。他曾使用汇编、Pascal、MegaBasic、Icon、Revelation、C、VB、C++和各种Web工具进行广泛的编程。自从用Z80机器代码编写了一个文本处理器,他感到,生活中必须有更多的东西,并且因而成为互操作性和使用机制来使重复编码最小化的坚定拥护者。可通过IBMDev@TextBiz.com与他联系。
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号
TechTarget
官方微博
TechTarget中国
相关推荐
-
BEST:SOAP/XML和REST的替代方案
虽然拥有大量的机架服务器,以及大量软件开发人员的组织,基于web和集成服务的SOAP和REST很适合他们,但也会出现问题。
-
Spring 烂!差!
有些人可能对Spring的第一印象不太好,它真的很烂,很差吗,也许这只是你的一种偏见,它也有是自己的优点的。
-
基于SOA架构的业务安全性研究
SOA在提供价值链上企业之间信息共享和业务流程自动化的同时,也给业务信息安全带来了负面影响,且存在安全隐患,这些你知道吗?
-
Java读取配置文件的几种方法
在现实工作中,我们常常需要保存一些系统配置信息,大家一般都会选择配置文件来完成,那么在Java怎样读取配置文件呢?