2017-06-29 3 views
2

Je souhaite créer une signature XML à l'aide de apache santuario lib et inclure un élément personnalisé dans le calcul de la signature en référençant cet élément. Voici ce que je suis arrivé à ce jour, et fonctionne très bien:Signature La référence ne peut pas être résolue (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; 
} 

Maintenant, je veux la référence qSigRef se référant à l'élément xml <xades:SignedProperties Id="SignedProperties-"> plutôt que <Object ID="SignatureProperties">. Après avoir changé l'URI de "#SignatureProperties" à "SignedProperties-" (comme indiqué ci-dessous):

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

un XMLSignatureException est jeté stateing:

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

Depuis , Je ne peux pas trouver de solution ni pourquoi l'exception est levée J'ai décidé de poser cette question ici.

Répondre

0

J'ai résolu le problème.

J'ai dû enregistrer l'attribut id de l'élément SignedProperties.

C'est archivé implcitly en appelant setIdAttributeNS() de l'élément connexe:

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