2017-06-29 3 views
2

Ich möchte eine XML-Signatur mithilfe von Apache santuario lib erstellen und ein benutzerdefiniertes Element in die Signaturberechnung einbeziehen, indem ich auf dieses Element verweise. Hier ist, was ich so weit gekommen, und funktioniert gut:Signaturreferenz kann nicht aufgelöst werden (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; 
} 

Jetzt möchte ich den Verweis qSigRef Bezug auf das XML-Element <xades:SignedProperties Id="SignedProperties-"> statt <Object ID="SignatureProperties">. Auf den URI Wechsel von "#SignatureProperties" bis "SignedProperties-" (siehe unten):

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"); 

zu

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"); 

ein XMLSignatureException wird stateing geworfen:

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

Seit Ich kann weder eine Lösung noch einen Grund finden, warum die Ausnahme ausgelöst wird. Ich habe beschlossen, diese Frage hier zu stellen.

Antwort

0

Ich löste das Problem.

Ich musste das ID-Attribut des SignedProperties-Elements registrieren.

Dies wird implcitly archiviert durch setIdAttributeNS() aufrufen des zugehörigen Element:

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 
Verwandte Themen