2017-06-29 71 views
2

我想通过使用apache santuario lib创建xml签名,并通过引用该元素将自定义元素包含到签名计算中。以下是我走到这一步,并且是工作的罚款:无法解析签名参考(Apache Santuario)

public void signXmlNode(Node n) { 
    try { 
     Reference qSigRef = sigFactory.newReference(
       "#SignatureProperties", sigFactory.newDigestMethod(
         this.refAlgo, null), Collections 
         .singletonList(sigFactory.newTransform(
           CanonicalizationMethod.EXCLUSIVE, 
           (TransformParameterSpec) null)), 
       "http://uri.etsi.org/01903#SignedProperties", 
       "Reference-SignedProperties-1497606229690"); 

     SignedInfo signedInfo = sigFactory.newSignedInfo(sigFactory 
       .newCanonicalizationMethod(
         CanonicalizationMethod.EXCLUSIVE, 
         (C14NMethodParameterSpec) null), sigFactory 
       .newSignatureMethod(this.sigAlgo, null), Arrays.asList(
       qSigRef)); 
     Element qSig = createXades(n.getOwnerDocument()); 
     XMLObject xmlObject = sigFactory.newXMLObject(
       Collections.singletonList(new DOMStructure(qSig)), 
       "SignatureProperties", null, null); 

     KeyInfoFactory keyInfoFactory = sigFactory.getKeyInfoFactory(); 
     List<Object> x509Content = new ArrayList<>(); 
     x509Content.add(signerCert); 
     X509Data xd = keyInfoFactory.newX509Data(x509Content); 
     KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Collections 
       .singletonList(xd)); 

     XMLSignature xmlSignature = sigFactory.newXMLSignature(signedInfo, 
       keyInfo, Collections.singletonList(xmlObject), "Signature-" 
         + SIGNATURE_ID, null); 
     DOMSignContext signContext = new DOMSignContext(signerKey, n); 
     signContext.setDefaultNamespacePrefix("ds"); 
     xmlSignature.sign(signContext); 
     final Transformer t = TransformerFactory.newInstance() 
       .newTransformer(); 
     t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 
     t.setOutputProperty(OutputKeys.INDENT, "yes"); 
     final StringWriter w = new StringWriter(); 
     t.transform(new DOMSource(n), new StreamResult(w)); 
     System.out.println(w.toString()); 
    } catch (MarshalException ex) { 
     log.log(Level.WARNING, "MarshalException in handler!", ex); 
    } catch (XMLSignatureException ex) { 
     log.log(Level.WARNING, "XMLSignatureException in handler!", ex); 
    } catch (InvalidAlgorithmParameterException ex) { 
     log.log(Level.SEVERE, "InvalidAlgorithmParameterException " 
       + "while signing message!", ex); 
     logSecurityProviders(); 
    } catch (NoSuchAlgorithmException ex) { 
     log.log(Level.SEVERE, "NoSuchAlgorithmException " 
       + "while signing message!", ex); 
     logSecurityProviders(); 
    } catch (TransformerConfigurationException e) { 
     e.printStackTrace(); 
    } catch (TransformerFactoryConfigurationError e) { 
     e.printStackTrace(); 
    } catch (TransformerException e) { 
     e.printStackTrace(); 
    } 
} 

private Element createXades(Document doc) { 
    Element qualifyingProperties = doc.createElementNS(
      "http://uri.etsi.org/01903/v1.3.2#", 
      "xades:QualifyingProperties"); 
    qualifyingProperties.setAttribute("Target", "#Signature-" 
      + SIGNATURE_ID); 
    Element signedProperties = qualifyingProperties.getOwnerDocument() 
      .createElementNS("http://uri.etsi.org/01903/v1.3.2#", 
        "xades:SignedProperties"); 
    signedProperties.setAttribute("Id", "SignedProperties-" + SIGNATURE_ID); 
    Element signedSignatureProperties = signedProperties.getOwnerDocument() 
      .createElementNS("http://uri.etsi.org/01903/v1.3.2#", 
        "xades:SignedSignatureProperties"); 


    signedProperties.appendChild(signedSignatureProperties); 
    qualifyingProperties.appendChild(signedProperties); 
    return qualifyingProperties; 
} 

现在,我想引用qSigRef指XML元素<xades:SignedProperties Id="SignedProperties-">而非<Object ID="SignatureProperties">。当从 “#SignatureProperties” 改变URI为 “SignedProperties-”(如下所示):

Reference qSigRef = sigFactory.newReference(
       "#SignatureProperties", sigFactory.newDigestMethod(
         this.refAlgo, null), Collections 
         .singletonList(sigFactory.newTransform(
           CanonicalizationMethod.EXCLUSIVE, 
           (TransformParameterSpec) null)), 
       "http://uri.etsi.org/01903#SignedProperties", 
       "Reference-SignedProperties-1497606229690"); 

Reference qSigRef = sigFactory.newReference(
       "#SignedProperties-", sigFactory.newDigestMethod(
         this.refAlgo, null), Collections 
         .singletonList(sigFactory.newTransform(
           CanonicalizationMethod.EXCLUSIVE, 
           (TransformParameterSpec) null)), 
       "http://uri.etsi.org/01903#SignedProperties", 
       "Reference-SignedProperties-1497606229690"); 

一个XMLSignatureException抛出stateing:

javax.xml.crypto.dsig.XMLSignatureException: javax.xml.crypto.URIReferenceException: org.apache.xml.security.utils.resolver.ResourceResolverException: Cannot resolve element with ID SignedProperties-

由于,我找不到任何解决方案,也没有理由抛出异常。我决定在这里提出这个问题。

回答

0

我解决了这个问题。我不得不注册SignedProperties元素的id属性。

Element signedProperties = qualifyingProperties.getOwnerDocument() 
       .createElementNS("http://uri.etsi.org/01903/v1.3.2#", 
         "xades:SignedProperties"); 
     signedProperties.setAttributeNS("", "Id", "SignedProperties-" 
       + SIGNATURE_ID);//Set ID attribute 

     signedProperties.setIdAttributeNS("", "Id", true);//register attribute as id 

这是通过调用setIdAttributeNS()的相关元素的implcitly存档

相关问题