All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy