eu.europa.esig.dss.xades.validation.XAdESSignatureScopeFinder Maven / Gradle / Ivy
/**
* DSS - Digital Signature Services
* Copyright (C) 2015 European Commission, provided under the CEF programme
*
* This file is part of the "DSS - Digital Signature Services" project.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package eu.europa.esig.dss.xades.validation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.crypto.dsig.XMLSignature;
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.transforms.Transforms;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import eu.europa.esig.dss.DSSUtils;
import eu.europa.esig.dss.DomUtils;
import eu.europa.esig.dss.XAdESNamespaces;
import eu.europa.esig.dss.utils.Utils;
import eu.europa.esig.dss.validation.FullSignatureScope;
import eu.europa.esig.dss.validation.SignatureScope;
import eu.europa.esig.dss.validation.SignatureScopeFinder;
import eu.europa.esig.dss.xades.DSSXMLUtils;
import eu.europa.esig.dss.xades.XPathQueryHolder;
/**
*
*/
public class XAdESSignatureScopeFinder implements SignatureScopeFinder {
private final List transformationToIgnore = new ArrayList();
private final Map presentableTransformationNames = new HashMap();
public XAdESSignatureScopeFinder() {
// @see http://www.w3.org/TR/xmldsig-core/#sec-TransformAlg
// those transformations don't change the content of the document
transformationToIgnore.add(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
transformationToIgnore.add(Transforms.TRANSFORM_BASE64_DECODE);
transformationToIgnore.add(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS);
transformationToIgnore.add(Canonicalizer.ALGO_ID_C14N11_WITH_COMMENTS);
transformationToIgnore.add(Canonicalizer.ALGO_ID_C14N_EXCL_WITH_COMMENTS);
// those transformations change the document and must be reported
presentableTransformationNames.put(Transforms.TRANSFORM_XPATH2FILTER, "XPath filtering");
presentableTransformationNames.put(Transforms.TRANSFORM_XPATH, "XPath filtering");
presentableTransformationNames.put(Transforms.TRANSFORM_XSLT, "XSLT Transform");
presentableTransformationNames.put(Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS, "Canonical XML 1.0 (omits comments)");
presentableTransformationNames.put(Canonicalizer.ALGO_ID_C14N11_OMIT_COMMENTS, "Canonical XML 1.1 (omits comments)");
presentableTransformationNames.put(Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS, "Exclusive Canonical XML (omits comments)");
}
@Override
public List findSignatureScope(final XAdESSignature xadesSignature) {
final List result = new ArrayList();
final Set unsignedObjects = new HashSet();
unsignedObjects.addAll(xadesSignature.getSignatureObjects());
final Set signedObjects = new HashSet();
final List signatureReferences = xadesSignature.getSignatureReferences();
for (final Element signatureReference : signatureReferences) {
final String type = DomUtils.getValue(signatureReference, "@Type");
if (xadesSignature.getXPathQueryHolder().XADES_SIGNED_PROPERTIES.equals(type)) {
continue;
}
final String uri = DomUtils.getValue(signatureReference, "@URI");
final List transformations = getTransformationNames(signatureReference);
if (Utils.isStringBlank(uri)) {
// self contained document
result.add(new XmlRootSignatureScope(transformations));
} else if (uri.startsWith("#")) {
// internal reference
final boolean xPointerQuery = XPointerResourceResolver.isXPointerQuery(uri, true);
if (xPointerQuery) {
final String id = DSSXMLUtils.getIDIdentifier(signatureReference);
final XPointerSignatureScope xPointerSignatureScope = new XPointerSignatureScope(id, uri);
result.add(xPointerSignatureScope);
continue;
}
final String xmlIdOfSignedElement = uri.substring(1);
final String xPathString = XPathQueryHolder.XPATH_OBJECT + "[@Id='" + xmlIdOfSignedElement + "']";
Element signedElement = DomUtils.getElement(xadesSignature.getSignatureElement(), xPathString);
if (signedElement != null) {
if (unsignedObjects.remove(signedElement)) {
signedObjects.add(signedElement);
result.add(new XmlElementSignatureScope(xmlIdOfSignedElement, transformations));
}
} else {
signedElement = DomUtils.getElement(xadesSignature.getSignatureElement().getOwnerDocument().getDocumentElement(),
"//*" + "[@Id='" + xmlIdOfSignedElement + "']");
if (signedElement != null) {
final String namespaceURI = signedElement.getNamespaceURI();
if ((namespaceURI == null) || (!XAdESNamespaces.exists(namespaceURI) && !namespaceURI.equals(XMLSignature.XMLNS))) {
signedObjects.add(signedElement);
result.add(new XmlElementSignatureScope(xmlIdOfSignedElement, transformations));
}
}
}
} else {
// detached file
result.add(new FullSignatureScope(DSSUtils.decodeUrl(uri)));
}
}
return result;
}
private List getTransformationNames(final Element signatureReference) {
final NodeList nodeList = DomUtils.getNodeList(signatureReference, "./ds:Transforms/ds:Transform");
final List algorithms = new ArrayList(nodeList.getLength());
for (int ii = 0; ii < nodeList.getLength(); ii++) {
final Element transformation = (Element) nodeList.item(ii);
final String algorithm = DomUtils.getValue(transformation, "@Algorithm");
if (transformationToIgnore.contains(algorithm)) {
continue;
}
if (presentableTransformationNames.containsKey(algorithm)) {
algorithms.add(presentableTransformationNames.get(algorithm));
} else {
algorithms.add(algorithm);
}
}
return algorithms;
}
}