How to add the XPATH Transform Algorithm (http://www.w3.org/TR/1999/REC-xpath-19991116) to digital signature in Java

134 views Asked by At

I'm trying to add XPATH transform in signature. I already add envelope transform and it's ok.

        List<Transform> transforms = new LinkedList<>();
        Transform envelopedTransform = xmlSignatureFactory.newTransform(CanonicalizationMethod.ENVELOPED,
                                                                        (TransformParameterSpec) null);
        transforms.add(envelopedTransform);

How to add XPATH tag using Java?

I tried XPATH transform add like this

        Transform xpath = xmlSignatureFactory.newTransform(CanonicalizationMethod.XPATH,
                                                                        (TransformParameterSpec) null);
        transforms.add(xpath);

I expected to create like below transform

<ds:Transforms>
     <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
     <ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
         <ds:XPath>not(ancestor-or-self::eb:TraceHeaderList or ancestor-or-self::eb:Via)</ds:XPath>
     </ds:Transform>
</ds:Transforms>

But when add XPATH transform it gave me the below exception. Exception Image

What want to do add XPATH transform Algorithm using Java?

I used this complete code

JSONObject jsonObject = new JSONObject();
    // Create a DOM XMLSignatureFactory that will be used to generate the enveloped signature.
    XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance("DOM");

    // Create a Reference to the enveloped document (in this case, you are signing the whole document,
    // so a URI of "" signifies that, and also specify the SHA1 digest algorithm and the ENVELOPED Transform.
    Reference envelopReference = xmlSignatureFactory.newReference("", xmlSignatureFactory.newDigestMethod(DigestMethod.SHA1, null),
                                                                  Collections.singletonList
                                                                      (xmlSignatureFactory.newTransform
                                                                          (Transform.ENVELOPED, (TransformParameterSpec) null)),
                                                                  null, null);

    List<Reference> referenceList = new ArrayList<>();
    referenceList.add(envelopReference);

    List<Reference> references = new ArrayList<>();

    DigestMethod digestMethod = xmlSignatureFactory.newDigestMethod(DigestMethod.SHA1, null);

    List<Transform> transforms = new LinkedList<>();
    Transform envelopedTransform = xmlSignatureFactory.newTransform(CanonicalizationMethod.ENVELOPED,
                                                                    (TransformParameterSpec) null);
    transforms.add(envelopedTransform);

    Reference reference = xmlSignatureFactory.newReference("", digestMethod, transforms, null, null);

    references.add(reference);

    // Create the SignedInfo.
    SignedInfo signedInfo = xmlSignatureFactory.newSignedInfo(xmlSignatureFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
                                                                                                            (C14NMethodParameterSpec) null),
                                                              xmlSignatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null),
                                                              references);

    // Load the KeyStore and get the signing key and certificate.
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    keyStore.load(new FileInputStream("keyStore.p12"), "123456".toCharArray());
    KeyStore.PrivateKeyEntry keyEntry =
        (KeyStore.PrivateKeyEntry) keyStore.getEntry
            ("alias", new KeyStore.PasswordProtection("123456".toCharArray()));
    X509Certificate cert = (X509Certificate) keyEntry.getCertificate();

    // Create the KeyInfo containing the X509Data.
    KeyInfoFactory keyInfoFactory = xmlSignatureFactory.getKeyInfoFactory();
    List x509Content = new ArrayList();
    x509Content.add(cert.getSubjectX500Principal().getName());
    x509Content.add(cert);
    X509Data x509Data = keyInfoFactory.newX509Data(x509Content);
    KeyInfo keyInfo = keyInfoFactory.newKeyInfo(Collections.singletonList(x509Data));

    // Instantiate the document to be signed.
    DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
    // process XML securely, avoid attacks like XML External Entities (XXE)
    documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
    documentBuilderFactory.setNamespaceAware(true);

    Resource resource = new FileSystemResource(resourceFileLocation.concat("ase.xml"));
    Document document = documentBuilderFactory.newDocumentBuilder().parse(resource.getFile());

    // Create a DOMSignContext and specify the RSA PrivateKey and
    // location of the resulting XMLSignature's parent element.
    DOMSignContext dsc = new DOMSignContext(keyEntry.getPrivateKey(), document.getDocumentElement());

    // Create the XMLSignature, but don't sign it yet.
    XMLSignature signature = xmlSignatureFactory.newXMLSignature(signedInfo, keyInfo);

    // Marshal, generate, and sign the enveloped signature.
    signature.sign(dsc);

    OutputStream os = new FileOutputStream("signedEbXml.xml");
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer trans = tf.newTransformer();
    trans.transform(new DOMSource(document), new StreamResult(os));
    os.flush();
    os.close();

    jsonObject.put("response", CommonConstants.RESPONSE);
    return jsonObject;
1

There are 1 answers

2
Lukas Voigt On

The XPath Filtering Transform needs your XPath expression passed as an argument:

String xpathExpr = "not(ancestor-or-self::eb:TraceHeaderList or ancestor-or-self::eb:Via)";
XPathFilterParameterSpec xpathSpec = new XPathFilterParameterSpec(xpathExpr);

Transform xpathTransform = xmlSignatureFactory.newTransform(CanonicalizationMethod.XPATH, xpathSpec);
transforms.add(xpathTransform);