XML安全:XML密钥管理规范

日期: 2009-03-19 作者:Manish Verma 来源:TechTarget中国 英文

  XML密钥管理规范(XML Key Management Specification,XKMS)为访问和集成公钥基础设施(Public Key Infrastructure,PKI)拟出了一种容易的机制。在本文中,Manish Verma解释了XKMS背后的目标,之后还为使用XKMS服务来注册和检索与公钥和/或私钥相关的信息提供了逐步操作指南。

  随着越来越多的个人和企业依赖于Internet来交换机密信息和敏感信息,安全性已经成为一个热门问题。其中有两个与安全性相关的话题得到了极大的重视:

  ·易于管理:使得安全性基础设施的使用及其与应用程序的集成比较容易,以便于广泛采纳。
  ·可移植的信任:在与某个实体建立了信任关系之后,要有一种标准机制来将那种信任转移至另一个协作的实体。单点登录(Single SignOn)就是可移植的信任的一个典型实例。当某个用户经过了一个特定网站的认证之后,就有一种标准机制将那种信息传递给其他需要该用户认证信息的协作站点。这样那些站点就可以透明地共享关于某个实体的信息,而不必一次又一次地请求那个实体的同样的信息。要使单点登录生效,这些实体必须认识彼此的凭证(credential)。

  XML密钥管理规范(XML Key Management Specification,XKMS)使得安全性基础设施易于管理,而安全性断言标记语言(Security Assertion Markup Language,SAML)则使信任可以移植。SAML为在相互协作的各个不同实体之间传输关于实体认证的断言提供了一种机制,这样就不必迫使这些实体失去对信息的所有权。

  本文将讨论XKMS在管理安全性基础设施的过程中所扮演的角色,并为使用XKMS提供一个逐步操作指南。

  可管理性问题

  XML加密和数字签名依赖于公共密钥基础设施(Public Key Infrastructure,PKI)来帮助加密(encrypt)、解密(decrypt)、签名(sign)和验证(verify)各种文档。对于一个要使用XML加密和/或数字签名的应用程序来说,它必须使用或者集成一个PKI解决方案。有很多PKI解决方案可供使用,例如X.509(使用最广泛)、Pretty Good Privacy (PGP)、Simple Public Key Infrastructure(SPKI)和Public Key Infrastructure X.509(PKIX)。问题是,到底该使用或集成哪种解决方案呢?

  不幸的是,答案并不像选择某种可用的PKI并与之集成那么简单。真正的问题是,一个应用程序要想与其他应用程序对话,它必须知道多少PKI以及这些PKI的语法和语义,而其他应用程序又可能使用其他可用的PKI解决方案来发送经过编码或签名的文档,或者期望收到这样的文档。例如,如果组织A使用X.509 PKI解决方案,它要发送加密的文档给组织B,而组织B使用的是SPKI PKI解决方案,那么,组织B就不能解密和使用由组织A发送的文档。要使A和B协同工作,它们当中必须有一方能够理解另一方的PKI解决方案。如果将这种场景再扩展一下,假设牵涉到多方,那么显然所有方都必须知道彼此的PKI解决方案,这样就使应用程序的复杂性增加了很多倍。

  在本文的其余部分,我将演示XKMS如何为这个问题提供答案。

  XML密钥管理规范(XKMS)

  XKMS将管理客户机应用程序的PKI的复杂性抽象到了一个受信任的第三方,从而使PKI易于管理。这个受信任的第三方在提供一个到客户机应用程序的PKI接口的同时驻留了XKMS服务。

  XKMS的目标

  XKMS的主要目标是:

  ·在应用程序与PKI解决方案之间创建一个抽象层。这样就允许应用程序根据需要插入不同的PKI解决方案,而不需要对应用程序本身作任何修改。
  ·提供一种基于XML的简单协议,以便通过XKMS服务处理密钥信息,使应用程序不必理解复杂的PKI语法和语义。
  ·将复杂性从客户机应用程序转移到基础设施层,从而允许应用程序更简单、更小巧。这样一来,即使是占用内存很少(small footprint)的设备也可以利用PKI。
  ·实现XKMS,使其平台无关、供应商无关和传输协议无关。

  XKMS概述

  XKMS是以Web服务的形式实现的,它允许客户机应用程序访问PKI功能,从而减少客户机应用程序的复杂性。客户机应用程序不需要关心底层PKI的语法,底层PKI可以是以下的任何一种:

  ·X.509(最广泛使用)
  ·Pretty Good Privacy (PGP)
  ·Simple Public Key Infrastructure (SPKI)
  ·Public Key Infrastructure X.509 (PKIX)

  XKMS规范由两个规范组成,其中一个规范与公钥的注册有关 ——XML密钥注册服务规范(XML Key Registration Service Specification,XKRSS),另一个规范关心的是基于密钥信息的信息检索 ——XML密钥信息服务规范(XML Key Information Service Specification,XKISS)。

  另一种规范,也就是X-Bulk,是由万维网联盟(Worldwide Web Consortium,W3C)发布的。该规范用于解决批量注册密钥对这一问题。我将在讨论了XKRSS之后解释X-Bulk。

  XML密钥注册服务规范(XKRSS)

  XKMS的这一部分为将密钥对注册到服务提供程序提供机制。可以有两种方式来将密钥注册到一个XKMS服务:

  ·客户机生成一个密钥对,并将公钥和其他信息一起提供给服务提供程序,以便注册。
  ·XKMS服务为客户机生成一个密钥对,将密钥对的公钥注册到它自己,然后将密钥对的私钥发送给客户机,供其使用。客户机还可以告诉XKMS服务,让XKMS服务也保留私钥。在客户机丢失了私钥的情况下,私钥就与XKMS服务保持一致。

  XKRSS服务规范定义了四种操作:

  ·注册(Register):通过密钥绑定将信息与一个密钥对绑定。在注册期间,要么是客户机提供公钥以及其他证明其拥有相应私钥的某些证据,要么是服务提供程序为客户机生成密钥对。服务提供程序在注册公钥(还可能同时包括私钥)之前,可以向客户机请求更多的信息。
  ·重新发行(Reissue):重新绑定之前已经注册的密钥。可以使用该操作生成底层PKI中的新凭证。虽然XKMS使用的密钥绑定信息没有寿命,但是底层PKI颁发的凭证偶尔也会有这么一段时间,过了这段时间之后就要周期性地更新。
  ·撤销(Revoke):该操作允许客户机销毁一个密钥所绑定到的数据对象。例如,当调用这个操作时,绑定到一个XKMS密钥的X.509凭证将被销毁。
  ·恢复(Recover):该操作允许客户机恢复私钥。要使该操作有意义,私钥必须已经注册到了服务提供程序。要想服务提供程序拥有私钥,那么就应该在服务器上而不是在客户机上生成密钥对。

  恢复操作在密钥对的私钥被用来加密数据的情况下添加很多值。如果丢失了私钥,则加密的数据也会丢失。当出现这种情况时,让私钥在服务器上生成并让服务提供程序保留该私钥是明智的。这样就可恢复私钥。

  如果丢失的私钥只是用于数字签名文档,那么就可以生成一个新的密钥,而不会影响对已经签名的文档的有效性。因此,由客户机来生成那种用途的密钥是很安全的,而且完全可以不将私钥注册到XKMS服务。

  实现了XKRSS服务规范的XKMS服务可以选择提供一些、所有或者不提供这些操作。XKRSS服务规范并不强制要求XKMS服务实现上述任何一种操作。

  密钥对的批量注册(X-Bulk)

  X-Bulk处理在一条请求消息内同时注册多个密钥对,这与XKRSS不同,后者只处理一次注册一个密钥对的情况。X-Bulk规范定义了一个批量元素,这种元素可以有多个注册请求或者多个服务器响应,所有这些请求或响应都遵从XKMS消息格式。与XKRSS一样,X-Bulk服务支持所有四种操作 —— 注册(Register)、重新发行(Reissue)、撤销(Revoke)和恢复(Recover)。X-Bulk可以处理客户机和服务器生成的密钥对的批量注册。

  XML密钥信息服务规范(XKISS)

  XKMS的这一部分为允许客户机应用程序认证经过加密/签名的数据提供机制。

  客户机通过将相应的密钥信息传递给服务提供程序来认证经过加密或签名的数据。而服务提供程序则以”true”或”false”响应。”true”表明,用于签名的私钥所对应的公钥的确属于那个宣称对该文档进行了签名的实体。

  XKISS服务规范定义了下面两种操作:

  ·定位(Locate):定位操作解析可能与XML加密或XM 签名有关的<ds:KeyInfo>元素,但是没有证明<ds:KeyInfo>元素中数据绑定的有效性。
  ·确认(Validate):定位操作能做的一切该操作都能做,而且还可以做更多的事情。定位服务根据<ds:KeyInfo>元素发现一个密钥,但是不保证密钥绑定信息是否值得信任。而确认操作不仅可以搜索<ds:KeyInfo>元素所对应的公钥,而且还保证它返回的密钥绑定信息是值得信任的。

  XKMS过程

  在这一节中,我将带您一步一步地经历注册和检索密钥的过程。

  基于XKRSS的注册过程允许注册客户机生成的密钥,也允许注册服务器生成的密钥。在注册客户机生成的密钥时,客户机首先生成密钥,然后通过发送公钥和提供私钥作为所有权的证据来请求XKMS服务注册密钥对的公钥。在注册服务器生成的密钥时,XKMS服务同时生成私钥和公钥,然后将私钥发送给客户机。

  清单1演示了如何注册客户机生成的密钥。为了使用该清单中的代码,必须与某个具有演示或测试XKMS服务运行的XKMS服务提供程序联系。从该服务提供程序获取您在将密钥注册到它们的演示或测试XKMS服务时所需的信息。我使用Verisign作为XKMS提供程序,并且使用共享密钥(shared secret)和密钥名,它们是提供给我用于注册密钥的。

  清单1. XKMS密钥注册

String sharedSecret = “passcode”;
String passPhrase = “passPhrase”;
KeyPair rsakey = getKeyPair();
String keyName =
“http://xkms.verisign.com/keyname?jurisdiction=d7ea68c518b2602ca4bbca895826a7dd&”+
“mail_email=mverma2@xkms.org&corp_company=Nano”;
XKMSKeyData data = new XKMSKeyData(rsakey, new XKMSKeyName(keyName));
XKMSAuthInfo authInfo = new XKMSAuthInfo(passPhrase, sharedSecret);
XKMSRegister register = new XKMSRegister(data, authInfo);
XKMSRegisterResponse resp = null;
String serviceurl = “http://interop-xkms.verisign.com/xkms/Acceptor.nano”;
URL url = new URL(serviceurl);
XmlTransportSOAP transport = new XmlTransportSOAP(url);
resp = register.send(transport);
System.out.println(“Response status is ” + resp.getStatus());
if (resp.getStatus()) {
      System.out.println(“The key name is ” + resp.getKeyName());
      System.out.println(“The public key is ” + resp.getPublicKey());
}
 
  步骤1:从要注册密钥对的服务提供程序那里获得密码(共享密钥)。服务提供程序还可以提供与密码一起使用的密钥名。

  步骤2: 使用getKeyPair()在客户机上生成密钥对。getKeyPair()的代码是您可以利用本文下载的源代码的一部分。

  步骤3: 指定XKMS密钥注册所需的密钥数据。创建XKMSKeyData对象。提供密钥对和密钥名作为输入。在密钥对中,公钥是已注册的,私钥用于作为所有权的证明。XKMSKeyData中使用的密钥名必须遵从由提供程序指定的特定格式。

  步骤4:指定XKMS密钥注册所需的注册授权数据。有两种方式可以用来提供授权信息:

  ·共享密钥:注册请求伴随着共享密钥,共享密钥由带外(out-of-band)客户机的注册中心给出。
  ·注册中心(registration authority,RA)认证:使用RA的X.509证书和RA的私钥。在清单1中,我演示了共享密钥认证机制的使用。

  步骤5: 通过提供XKMS密钥数据和授权信息,创建XKMSRegister对象的一个实例。

  步骤6: 创建一个XmlTransportSOAP对象。提供运行注册服务时所在的URL作为输入。

  步骤7: 使用send方法发送请求给XKMSRegister对象,将XmlTransportSoap实例传递给这个方法。

  send方法首先注册密钥,然后返回一个XKMSRegisterResponse对象。可以通过查询这个对象来获得密钥名和其他密钥信息。通过查询XKMSRegisterResponse对象而得到的密钥名不同于您在步骤3中创建XKMSKeyData对象时提供的密钥名。以后您将使用这个密钥名来定位密钥。

  接下来,我将演示如何定位一个已经注册到服务提供程序的密钥。(用于定位密钥的清单2中所演示的机制使用了这个密钥名。在清单2的后面我将更详细地加以解释。)

  清单2. 定位密钥

// The key name that you got from the XKMSRegisterResponse
// Object
String keyNameToLocate =
“http://xkms.verisign.com/key?company=VeriSign&department=XKMS Test&”+
“CN=MANISH VERMA6&issuer_serial=73efeeea87e159e6d7fc790ef01c6fe7”; 
// An array of response strings to indicate what key
// information is requested
String[] xkmsResponse =   
{XKMSLocate.KeyName,XKMSLocate.KeyValue,XKMSLocate.X509Cert,XKMSLocate.X509Chain };
XKMSLocateResponse locateResponse = null;
XKMSLocate xkmsLocate = new XKMSLocate(keyName,xkmsResponse); 
String serviceurl = “http://interop-xkms.verisign.com/xkms/Acceptor.nano”; 
URL url = null; 
url = new URL(serviceurl);
XmlTransportSOAP transport = new XmlTransportSOAP(url);
locateResponse = xkmsLocate.sendRequest(transport);
List keyInfoList = locateResponse.getXKMSKeyInfos();
Iterator itr = keyInfoList.iterator();
XKMSKeyInfo xkmsKeyInfo = null;
while (itr.hasNext()){
      xkmsKeyInfo = (XKMSKeyInfo)itr.next();
}
 
  步骤1:为了定位一个密钥,您可以使用以下任何信息进行查询:

  ·密钥名(这应该是先前在一个XKMSRegisterResponse对象中返回的密钥名)。注册时与XKMSKeyData一起使用的那个密钥名这里不能使用。
  ·公钥值。
  ·X.509证书。

  在清单2中,我使用密钥名来查询密钥。

  步骤2:指定一个响应字符串数组,这些字符串的值都是我们感兴趣的。

  步骤3: 用密钥名和响应字符串数组创建XKMSLocate对象。

  步骤4: 创建一个XmlTransportSOAP对象。提供运行注册服务时所在的URL作为输入。

  步骤5: 使用sendRequest方法发送请求给XKMSLocate对象,将XmlTransportSoap实例传递给该方法。

  步骤6: 获取XKMSLocateResponse对象。从这个对象中,您可以获得一个XKMSKeyInfo对象列表。迭代这些对象,以获得与响应字符串对应的信息。

  XKMS服务本身的安全性

  您还没完全了解XKMS。您还应该了解一些事情,然后才可以把文档和应用程序的安全性托付给XKMS服务。在这一节中我大致谈到的问题与所有基于Web的服务有关,但是应该确保XKMS可靠和可用,这一点很重要。

  ·防止重复攻击(replay attack):确保XKMS服务为某请求发送的回复不被未经授权的第三方捕获到。这个捕获到的响应可以被第三方作为对其他请求的响应再次发送,并假装它就是XKMS服务本身。您可以通过各种标准方式来处理这种情况,例如给响应加时间戳。
  ·防止服务的抵赖攻击(denial of service attack):使用XKMS来获取密钥信息比较有用,前提是XKMS在需要的时候可用,并且这一过程能在合理的时间内完成。实现服务时,必须使其能够承受服务的抵赖攻击,从而保持高度可用。
  ·验证一个良好的、健壮的密钥恢复策略:确保XKMS服务提供程序具有一个良好的、健壮的密钥恢复策略,因为这直接影响着签名文档的否认和加密文档的可靠性。

  结束语

  通常,好的技术之所以不能坚持到底,是因为它们使用起来过于笨重。在这种情况下,只有一小撮忠实的开发人员会继续使用这种技术,而一般的IT部门不再采纳这种技术。PKI问世已经有多年了,但是它还没有走进一般的IT部门。现在,XKMS为使用PKI和将PKI与应用程序集成提供了一种容易的机制。在本文中,我解释了在各种PKI解决方案上使用一个XKMS抽象层的目的,并演示了使用XKMS服务来注册和定位密钥是多么的容易。在我的下一篇文章中,我将重点解释如何通过SAML使这种信任可移植。

  关于作者

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

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

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

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

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐