科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道JavaSE 6基于JSR105的XML签名之实践篇

JavaSE 6基于JSR105的XML签名之实践篇

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

我们分析了有关基于JSR-105进行XML签名的基本概念。在本篇中,我们开始分析一个实际的XML签名示例应用程序。

作者:朱先忠编译 来源:天极开发 2007年10月13日

关键字:

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共6页)

三、 XML签名核心校验

  在前面一节中,我们把invoice.xml文档签名成一个在signature.xml文件中捕获的enveloping XML签名。

  为了校验该签名,我们可以使用下列程序-Validate.java:

public class Validate {
 public static void main(String[] args) throws Exception {
  //第一步
  String providerName = System.getProperty("jsr105Provider","org.jcp.XML.dsig.internal.dom.XMLDSigRI");
  XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM",(Provider) Class.forName(providerName).newInstance());
  //第二步
  DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  dbf.setNamespaceAware(true);
  Document doc = dbf.newDocumentBuilder().parse(new FileInputStream(args[0]));
  //第三步
  NodeList nl = doc.getElementsByTagNameNS(XMLSignature.xmlNS,"Signature");
  if (nl.getLength() == 0) {
   throw new Exception("Cannot find Signature element!");
  }
  //第四步,分为情形4.0,4.1,4.2或4.3
  //第4.0种情形
  DOMValidateContext valContext = new DOMValidateContext(new KeyStoreKeySelector(), nl.item(0));
  //第4.1种情形,需要Sign.java中的第6.1种情形
  // DOMValidateContext valContext = new DOMValidateContext(
  // new KeyValueKeySelector(), nl.item(0));
  //第4.2种情形,需要Sign.java中的第6.2种情形
  // KeyStore ks = KeyStore.getInstance("JKS");
  // FileInputStream fis = new FileInputStream("./etc/bizkeystore");
  // ks.load(fis,"sp1234".toCharArray());
  // fis.close();
  // X509KeySelector x509ks = new X509KeySelector(ks);
  // DOMValidateContext valContext = new DOMValidateContext(x509ks, nl.item(0));
  //第4.3中情形
  // PublicKey pKey = KeyStoreInfo.getPublicKey("./etc/bizkeystore",
  // "sp1234", "biz");
  //第五步
  XMLSignature signature = fac.unmarshalXMLSignature(valContext);
  //XMLSignature signature = fac.unmarshalXMLSignature(new DOMStructure(nl.item(0)));
  //第六步
  boolean coreValidity = signature.validate(valContext);
  //检查核心校验状态
  if (coreValidity == false) {
   System.err.println("Signature failed core validation!");
   boolean sv = signature.getSignatureValue().validate(valContext);
   System.out.println("Signature validation status: " + sv);
   //每一个Reference的检查校验状态
   Iterator i = signature.getSignedInfo().getReferences().iterator();
   for (int j = 0; i.hasNext(); j++) {
    boolean refValid = ((Reference) i.next()).validate(valContext);
    System.out.println("Reference (" + j + ") validation status: "+ refValid);
   }
  } else {
   System.out.println("Signature passed core validation!");
  }
 }
}

  要试验这个程序,读者可以运行Ant目标校验。该程序把核心校验状态打印到System.out。如果签名是有效的,将输出"Signature passed core validation!";否则,输出结果中将展示引用和签名的校验状态;而这样以来,我们就可以准确地搞清楚是它们其中的哪一些导致了此次失败。

  校验signature.xml的过程可以分解成六个步骤。

  步骤1-加载一个XMLSignatureFactory实例,这一步与在签名程序中是一样的。

  步骤2-加载要校验的XML签名。在这一步中,我们需要把包含XML签名的XML加载到内存中并且把该XML文档转换成一棵DOM树。

  步骤3-识别DOM树中的签名结点。签名是在命名空间http://www.w3.org/2000/09/XMLdsig#中定义的,它被描述为在JSR-105中的XMLSignature接口的静态变量XMLNS。

  步骤4-创建一个DOMValidateContext实例。

  一个校验上下文中的一项最关键的信息显然是密钥。我们可以使用DOMValidateContext并通过两种不同的方法来注册公共密钥。在第一种方法中,如果校验应用程序已经拥有公共密钥,它可以把该密钥直接通过下列DOMValidateContext的构造器放入上下文中:

public DOMValidateContext(Key validatingKey,Node node)

  这正是在我们的示例中的情形4.3。

  第二个方法将使用DOMValidateContext注册一个KeySelector,并且让该KeySelector选择公共密钥-基于在要校验的XMLSignature对象中可用的信息。在JSR-105中,KeySelector是一个定义了两个操作的抽象类:

public abstract KeySelectorResult select(KeyInfo keyInfo, Purpose purpose,
AlgorithmMethod method, XMLCryptoContext context)
throws KeySelectorException
public static KeySelector singletonKeySelector(Key key)

  第二个操作创建一个总是返回相同密钥的KeySelector。第一个操作试图选择一个密钥-它能够满足作为输出传递的要求。

  KeySelectorResult是JSR-105中的一个接口-该规范中要求这个接口包含一个使用KeySelector选择的Key值。在我们的示例中,我们使用SimpleKeySelectorResult类实现这个接口-简单地包装选择的公共密钥。

  在我们的示例中,我们实现并利用三个不同的KeySelectors来说明一个校验应用程序工作的一些情形。

  在情形4.0中,KeyStoreKeySelector基于输入参数从一个Key存储中检索公共密钥。

  在情形4.1中,KeyValueKeySelector基于在输入KeyInfo对象(它应该包含一个KeyValue对象作为它的内容的一部分;请参考Sign.java中的情形6.1)中的KeyValue信息选择一个键值。

  在情形4.2中,X509KeySelector基于包含在KeyInfo对象(它应该包含一个X509Data对象作为它的内容的一部分;请参考Sign.java中的情形6.2)中的X509Data及其它信息选择一个键。我们使用的是JSR-105中的X509KeySelector-其原作者是Sean Mullan。在此,我们稍微修改了一下其中的私有certSelect()方法以便它可以适合于我们使用keytool生成的证书。

  既然签名中的KeyInfo可能包含各种信息,显然,一个应用程序必须选择一个KeySelector实现-由它来使用包含在它将处理的KeyInfos中的信息。

  步骤5-把签名结点反编排成一个XMLSiganture对象。在上一步骤中,我们把signature.xml文件加载进一棵DOM树-由相应于树中的Signature元素的结点所标识,并且使用一个DOMValidateContext和KeySelector(或私有密钥)注册该结点。为了校验该XML签名,我们需要把Signature结点反编排为一个XMLSignature对象。这是通过调用下列XMLSignatureFactory操作实现的:

public abstract XMLSignature unmarshalXMLSignature(XMLValidateContext context)
throws MarshalException

  步骤6-校验XML签名。这是通过调用XMLSignature实例的validate()方法实现的-以DOMValidateContext作为唯一的输入参数。

  该validate()方法根据在W3C建议中定义的核心校验过程校验XML签名。如前面所提及,这个过程包括两个部分。其一是校验所有的参考。在JSR-105中,这可以通过调用Reference接口的validate()操作来实现-以相关的校验上下文作为输入参数。

  该核心校验的第二部分是签名校验-校验规范的SignedInfo元素的签名值。借助于JSR-105,我们可以显式地完成这一部分-通过调用与XMLSignature实例相关联的SignatureValue对象的validate()方法实现,并以相关的校验上下文作为输入参数。

  在我们的示例中,我们使用这样的知识来输出每一个Reference和SigantureValue的校验状态-当XML签名(核心)校验失败时;这样以来,我们就可以得到导致失败的更为详细的信息。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章