XML安全组件:增强电子商务的安全性

日期: 2009-03-10 作者:Doug Tidwell 来源:TechTarget中国 英文

  随着越来越多的公司在通过网络传输结构化数据时采用XML,文档的安全性变得愈加重要。这篇文章介绍有关网络安全的基本知识,对XML安全组件的组成进行说明,并且通过一些示例说明XML安全组件中的技术如何增强网络商务的安全性。

  网络安全概述

  随着越来越多的公司在通过网络传输结构化数据时采用XML,文档的安全性变得愈加重要。世界互联网联盟(W3C)和因特网工程任务组(IETF)正在制定用于数字签名的XML词汇表。东京研究实验室则已开发出XML安全组件,该安全组件是XML签名规范的原型。XML安全组件可以从IBM的alphaWorks获得,包括自动生成XML数字签名的工具。

  在通过网络传输保密数据时,应保证以下四点:

  ·机密性―其他任何人都不能访问或复制该数据。
  ·完整性―该数据从发送者到达接收者的过程中未被更改。
  ·身份验证―该文档确实发自所指的发送者。
  ·无争议―发送者不可否认该文档确由其发送,也不能否认文档的内容。

  SSL能够提供前三项功能,而XML安全组件则能同时提供上述四项功能

  创建安全会话

  创建安全会话包含多个步骤:

  ·安全服务器获得适当的安全认证(CA)。
  ·安全服务器将其公钥发送至客户端。
  ·客户端使用服务器的公钥产生 预置密码(由客户端生成的一个 随机数,但比一般的随机数要复杂得多)。服务器利用私钥对预置密码解密。
  ·服务器在预置密码的基础上生成新的密码。服务器知道该密码,且只能被产生该预置密码的客户端解密与使用。

  此过程将创建一个会话,其在特定客户端与服务器间的所有的数据交换均被加密。只有服务器和特定客户端能够相互进行数据解密。这样,机密性、完整性和身份验证均已包括。然而,SSL不能实现无争议性,如果我的系统中有一个文 件,你可以否认曾发送过这个文件,或者可以否认文件内现有内容是你所发送的。无争议性是由XML安全组件所提供的一项功能。

  XML安全组件

  XML安全组件提供多项重要功能:

  ·XML签名。此项功能的实现基于世界互联网联盟(W3C)和因特网工程任务组(IETF)正在开发的XML签名核心语法和处理规范。
  ·W3C规范XML的工作草案的实现。
  ·元素级加密。

  以下各部分将分别讨论上述功能及其如何增强网络安全。

  XML签名

  W3C和IETF正共同致力于一项基于XML的数字签名的计划。该计划定义一个<signature>元素,其中包含处理数字签名所需的全部信息。 每个数字签名均可归结为以下三类之一:

  ·一个包含在<signature>元素中的XML元素
  ·一个由URI索引的外部XML文档
  ·一个由URI索引得外部非XML资源

  本文例子将向您展示如何创建这些资源。如果您想了解全部细节,请参见XML签名方案的最新草案

  为了说明XML签名的工作原理,我生成了一个关于莎士比亚的十四行诗的名为signature.xml的签名文件,该文件已经应用在我的很多的XML例子中(可以通过HTML格式浏览,也可以下载此文档。)

  在这个签名文件里,带符号的元素是十四行诗,包含在<dsig:Object>元素中。而实际的签名包含在<SignatureValue>元素中,此外该文档的签名人则由<X509Data>元素说明。

  关于示例程序

  通过若干程序范例来说明XML安全组件的不同功能。如果想要深入了解这里所讨论的 程序例子,则需要几个文件。有关如何获得这些文件的信息

  ·XML安全控件将xss4j.jar和/xss4j/samples添加至您的classpath中。

  ·Java 2 Development Kit 1.2版或更高版本。请确认这是您的系统默认的JDK。
JavaMail包中的mail.jar文件将此文件添加至classpath。

  ·Java密码扩展系统的一个实现在Sun的网站中可以找到密码服务提供者的目录。为避免输出过于复杂,这里的例子采用了OpenJCE,一个免费的开放源码的库。将jce.zip添加至classpath中。

  ·IBM XML语法分析器第2版和Java 3.0.1版文件xml4j.jar必须位于classpath中。

  创建证书

  在生成数字签名前,首先要获得一份证书。尽管可以通过证书授权机构(CA)得到一份证书,但是在这里的例子中,你将充当自己的CA。要创建在signature.xml中使用的X.509认证,可用Java 2的keytool命令:

  清单1、keytool命令
  keytool -genkey -dname “CN=Doug Tidwell, OU=developerWorks, O=IBM,
  L=Research Triangle Park, S=North Carolina, C=US” -keypass openstds
  -storepass security -alias xss4j
 
  在keytool命令中,特异名(dname)由普通名(CN)、组织单元(OU)、组织(O)、区域(L)、州(S)和国家(C)组成。对于整个因特网,特异名被设计为唯一的。密匙库(-storepass)的密码为security,此证书的私钥的密码(-keypass)为openstds,而xss4j则是认证(-alias)的别名。

  对内部XML资源签名

  要创建数字签名,可以使用SampleSign应用程序。这个程序是XML安全组件附带的,可以在xss4j/samples目录中找到。我们的第一个签名将应用于内部XML资源。也就是说数字签名和XML资源都在同一文件中。下面说明如何对sonnet.xml进行签名,以生成signature.xml:

  清单2、SampleSign应用
  java SampleSign xss4j security openstds -embxml
  file:///d:/xss4j/samples/sonnet.xml > signature.xml
 
  请注意,别名、私钥密码、密匙库密码同清单1的keytool命令是相同的。另外还应注意这里用file: URL代替了简单的文件名,而输出内容则送至(用 >操作符)文件signature.xml。这条命令的执行结果是signature.xml中显示的文档。

  对外部XML资源签名

  对外部XML资源签名表明<Signature>文件包含XML资源的URL,而不是资源本身。要创建这种数字签名,应使用-extxml选项:

  清单3、带有-extxml选项的SampleSign应用java SampleSign xss4j security openstds -extxml
file:///d:/xss4j/samples/sonnet.xml > external-signature.xml
 
  这将产生一个同signature.xml相似的文件,只是实际的XML文件未被包含在<Signature>中。

  对非XML资源签名

  最后的这个签名示例将为非XML资源生成一个数字签名。在这个例子中用到一个GIF文件,包含developerWorks的标识:

  要创建数字签名,使用-ext选项:清单4带有-ext选项的SampleSign应用java SampleSign xss4j security openstds -ext
file:///d:/xss4j/samples/dwlogo.gif > external-gif-signature.xml
 
  验证数字签名

  XML安全组件提供了一个实用程序SampleVerify,用于验证数字签名。使用它,可以检查给定的签名,以确认被签名的资源没有改变,此外还能检查该签名是否同发送者的证书信息相符。如果签名有效,清单5会显示出应当得到的结果:

  清单5、SampleVerify应用java SampleVerify -dom < external-signature.xml
Signer: CN=Doug Tidwell, OU=developerWorks, O=IBM, L=Research Triangle
Park, ST=North Carolina, C=US
SignedInfo Bytes: 1069
—————————————-
–> Location: file:///d:/xss4j/samples/sonnet.xml
    Validity: Ok
–> SignedInfo: Ok
–> All: Ok
—————————————-
 
  如果签名的文件被改动,该签名将不再有效。为了说明这种情况,可在<line>元素后面加一个空格,把<line>My mistress’ eyes are nothing like the sun,</line>改成<line>My mistress’ eyes are nothing like the sun,</line>。当再次检查签名,其结果将如清单6所示:清单6、SampleVerify应用(改过的文件)java SampleVerify -dom < external-signature.xml
Signer: CN=Doug Tidwell, OU=developerWorks, O=IBM, L=Research Triangle
Park, ST=North Carolina, C=US
SignedInfo Bytes: 1069
—————————————-
–> Location: file:///d:/xss4j/samples/sonnet.xml
             
        Validity: NG
      Reason: Digests were mismatched.
–> SignedInfo: Ok
–>
     
        All: NG
—————————————-
     
  由于改动过的XML文件同数字签名不符,这样就可以知道不能信任该文件。(如果原始文件签署者以外的其他人试图冒充该数字签名的创建者,在SignedInfo信息中便会显示出来。)

  无争议性的乐趣

  数字签名的最有用之处是能提供无争议性。如果你传送给我一份签署的文件,我能知道你就是发送者,因为签名中包括了你的公钥。另外,由于签名是基于文件内容的,所以对文件的任何改变都会使签名不符。

  规范的XML

  规范形式为计算数字签名,需要一个通用的方法来表示所有的XML文件。可以采用W3C的规范XML事物最简单的形式(韦氏学院字典,在线版)标准来进行。

  即使两个XML文件不完全相同,它们在XML应用中的作用可能是一样的。看一看下面这两个元素:

  清单7、等价但不相同的XML
    <img src=”dwlogo.gif” width=”225″ height=”30″/>
    <img src=”dwlogo.gif” height=”30″ width=”225″/>
                  
  如果对这两个元素进行简单的字符串比较,它们显然是不同的。然而,从XML处理的角度来看,它们是等价的。按照XML 1.0推荐标准,属性的顺序是不重要的。在XML源码文件中,其它非重要差异还包括属性间的空格数量 以及源文件中是否实际包含带默认值的属性。为解决这一问题,W3C正在为XML文档定义一个规范形式。

  XML安全组件提供了一个应用程序—XML Canonicalizer(XML规范器),这是对W3C将要出台的规范XML标准的原型的一个实现。要将XML文件转换为规范形式,可以用下面两个命令之一:

  清单8、XML规范器
 java C14nDOM  sonnet.xml  canonical-sonnet-DOM.xml
java C14nSAX sonnet.xml canonical-sonnet-SAX.xml
     
  C14nDOM应用程序使用DOM语法分析器,而C14nSAX应用程序则使用SAX语法分析器。虽然可以使用这些应用程序来生成XML文件的规范形式,但是它们仍主要用于XML签名代码。

  因为XML签名代码使用规范形式产生数字签名,所以可以对原始文件进行适当改动而不影响数字签名的有效性。例如,在标记中添加一些空格。将下行:

  sonnet type=”Shakespearean”
     
  更改为sonnet
type=”Shakespearean”
     
  进行这一更改后,再次运行SampleVerify应用程序,以确认数字签名仍然有效:
  
  清单9、SampleVerify应用程序(文件的规范形式)
     
java SampleVerify -dom  external-signature.xml
Signer: CN=Doug Tidwell, OU=developerWorks, O=IBM, L=Research Triangle
Park, ST=North Carolina, C=US
SignedInfo Bytes: 1069
—————————————-
–> Location: file:///d:/xss4j/samples/sonnet.xml
    Validity: Ok
–> SignedInfo: Ok
–> All: Ok
—————————————-
  
  尽管文件不同,然而其差异没有语义重要性。因为XML安全组件使用XML文件的规范形式,语义上不重要的差异被忽略。

  元素级加密

  XML的一个长处在于可以选择元素名,从而使标记文件更具可读性。作为一个例子,参见清单10中用XML编写的客户订单。

  清单10、 custorder.xml
<?xml version=”1.0″?>
<!DOCTYPE customer_order SYSTEM “custord.dtd”>
<customer_order>
  <items>
    <item>
      <name>Turnip Twaddler</name>
      <qty>3</qty>
      <price>9.95</price>
    </item>
    <item>
      <name>Snipe Curdler</name>
      <qty>1</qty>
      <price>19.95</price>
    </item>
  </items>
  <customer>
    <name>Doug Tidwell</name>
    <street>1234 Main Street</street>
    <city state=”NC”>Raleigh</city>
    <zip>11111</zip>
  </customer>
  <credit_payment>
    <card_issuer>American Express</card_issuer>
    <card_number>1234 567890 12345</card_number>
    <expiration_date month=”10″ year=”2004″/>
  </credit_payment>
</customer_order>
 
  这个文件包括三部分,<items>元素列出顾客定购的各项内容,<customer>元素包含了客户的信息,而<credit_payment>部分描述了用于支付该订单的的信用卡信息。

  早期的因特网用户不愿意使用信用卡进行在线购物。这时,许多电子商务支持者指出无论如何信用卡支付总是要冒一定风险的。通常我把信用卡交给饭店的服务员,我相信我的信用卡不会被用来支付我的餐费以外的其它东西。同样,当我在线购买时,我相信商家不会用我的信用卡支付未经我认可的款项。

  利用XML安全组件的元素级加密功能,可以对敏感信息进行加密。这样,商家也不能看见这些信息。商家可以把加密信息传给信用卡处理机构,这些机构拥有正确的密匙,可对敏感信息解密。这样将能极大地提高现行的典型处理方式的安全性。

  为了说明元素级加密,我对XML安全组件所带的CipherTest.java文件稍做更改。我将对所做的更改进行说明,以对元素级加密的工作原理进行解释。

  对CipherTest.java的第一项改变是导入OpenJCE库,然后将ABAProvider类定义为密码提供者:

  清单11、CipherTest.java更改(导入OpenJCE类)
    
       
        import au.net.aba.crypto.*;
import au.net.aba.crypto.provider.*;
import au.net.aba.crypto.spec.*;…
public class CipherTest {
  public static void main(String[] args) {
    if (args.length < 3) {
      System.err.println(“Usage: CipherTest -e|-d passphrase infile outfile”);
      return;
    }
           
        java.security.Security.
         addProvider(new au.net.aba.crypto.provider.ABAProvider());
   
  替代调用java.security.Security.addProvider方法,可以修改java.security文件(见JavaHome/lib/security),将下面一行:

“security.provider.1=sun.security.provider.Sun”
 
  替换为:

  ”security.provider.1=au.net.aba.crypto.provider.ABAProvider”
 
  其它更改只剩下修改代码,使之能够对任何<credit_payment>元素进行加密:

  清单12、CipherTest.java更改(加密元素)
if (n.getNodeType() == Node.ELEMENT_NODE) {
    //System.out.println(((Element)n).getTagName());
    if ((ne != null &&
        ((Element)n).getTagName().equals(   
       
        “credit_payment”))
        ||
        (nd != null &&
        ((Element)n).getTagName().equals(“EncryptedElement”))) {
        child = n;
        break;
     
  要演示这一功能,可以运行CipherTest,同原始的XML文件进行对比。应用程序CipherTest在命令行中使用了一个密码:

  清单13、CipherTest应用程序
  java CipherTest -e security custorder.xml encrypted-custorder.xml

  这将创建encrypted-custorder.xml文件,如清单14所示。

  清单14、 encrypted-custorder.xml
<?xml version=”1.0″?><customer_order>
  <items>
    <item>
      <name>Turnip Twaddler</name>
      <qty>3</qty>
      <price>9.95</price>
    </item>
    <item>
      <name>Snipe Curdler</name>
      <qty>1</qty>
      <price>19.95</price>
    </item>
  </items>
  <customer>
    <name>Doug Tidwell</name>
    <street>1234 Main Street</street>
    <city state=”NC”>Raleigh</city>
    <zip>11111</zip>
  </customer>
    
        <EncryptedElement algorithm=”DES/CBC/PKCS5Padding” contentType=”text/xml”
  encoding=”base64″ iv=”S5Rirg//pNQ=”> vJqNpDrQT1vmCVbyGJfIwdIDBYoGXGmutgz6TVGoPuKVG7I
  xNEN50iKw8pmtxFixz5hOChOXgTtPqktQhEHO5+vLOLAFgIioDIRQGHHmHng3CLd+8tvrT8wxPBCRSMUpx4
  d2TGXW2tqSepam0ZxdmwUXwNSAgaR8hmiromD+bh+tDomPv7eFZ4no5ft3JG3t0trLlwVupF/5vaIJimUSm
  uUkkgyG8x9AcS/kXJxHpmM=peqGzIMf+8A=
              
        </EncryptedElement>
</customer_order>
     
  在这个加密的XML文件中,元素<credit_payment>被替换为<EncryptedElement>元素。文件中没有任何参数指示共对多少个元素进行加密、加密元素名称、加密元素的结构或顺序等。为保证加密文件的保密性,我们在源文件中没有使用<!DOCTYPE声明。加密文件不能使用DTD,也不能包括任何可能显示加密元素结构的索引。如果对带有<!DOCTYPE声明的XML文件进行加密,解密过程不能工作。(得到的错误信息没有什么帮助;将显示java.lang.NullPointerException at CipherTest.main(CipherTest.java:83),或其它同样没用的提示信息。)

  要恢复原始文件,使用-d(decrypt/解密)选项代替-e(encrypt/加密)选项。确认你用的密码是相同的。

  清单15、CipherTest应用程序(-d选项)
java CipherTest -d security encrypted-custorder.xml restored-custorder.xml
 
  这会将加密文件恢复为原始状态。注意,元素级加密使用规范的XML,所以恢复后的文件同原始文件的语法可能并不完全一样。然而,然而,这些差异在语义上都不是特别重要。

  其它工具

  XML安全组件另外还提供了两种工具,包括一个ASN.1到XML的翻译器和多种DOMHASH工具。ASN.1到XML的翻译器自动在ASN.1数据(如X.509认证和LDAP数据)和XML间进行翻译。DOMHASH是一种算法,为XML文件树中一个给定节点生成唯一的哈希数。XML安全组件中所包括的DOMHASH工具计算给定节点的哈希数,另外还提供了一套DOMHASH测试工具。alphaWorks包含一个DOMHASH应用程序,叫做XMLTreeDiff;它使用DOMHASH 来确定两个DOM树的差异。

  总结

  XML安全组件提供了多项功能,以增强XML文件的安全性。所有这些技术都能为现有的网络安全体系所应用。随着XML文件交换日益重要,XML安全组件中的技术将提供重要的安全功能。最重要的是,这些技术建立在开放的新兴标准下,而且能在任何支持Java的平台上进行工作。如果你对这种即将被全世界所采用的安全技术感兴趣,XML安全组件确实值得一看。

  关于作者

  Doug Tidwell是IBM高级程序员。他具有16年以上的编程经验,同基于标记的应用程序打交道也已经愈10年。正如IBM的Simon Phipps所说,他作为一名“数码福音传道者”,其工作就是“化繁为简”。在其雇主的特殊安排下,他正致力于巧克力软糖的研究。他拥有Vanderbilt大学计算机科学硕士学位和Georgia大学英语学士学位。可以通过电子邮件dtidwell@us.ibm.com同他联系。 

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐