/** * 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.signature; import java.util.Arrays; import java.util.List; import javax.xml.crypto.dsig.CanonicalizationMethod; import javax.xml.crypto.dsig.XMLSignature; import org.apache.xml.security.c14n.Canonicalizer; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.Text; import eu.europa.esig.dss.DSSDocument; import eu.europa.esig.dss.DSSException; import eu.europa.esig.dss.DSSUtils; import eu.europa.esig.dss.DomUtils; import eu.europa.esig.dss.EncryptionAlgorithm; import eu.europa.esig.dss.InMemoryDocument; import eu.europa.esig.dss.MimeType; import eu.europa.esig.dss.utils.Utils; import eu.europa.esig.dss.validation.CertificateVerifier; import eu.europa.esig.dss.xades.DSSReference; import eu.europa.esig.dss.xades.DSSTransform; import eu.europa.esig.dss.xades.DSSXMLUtils; import eu.europa.esig.dss.xades.XAdESSignatureParameters; /** * This class handles the specifics of the enveloping XML signature * */ class EnvelopingSignatureBuilder extends XAdESSignatureBuilder { /** * The default constructor for EnvelopingSignatureBuilder. The enveloped signature uses by default the inclusive * method of canonicalization. * * @param params * The set of parameters relating to the structure and process of the creation or extension of the * electronic signature. * @param origDoc * The original document to sign. * @param certificateVerifier */ public EnvelopingSignatureBuilder(final XAdESSignatureParameters params, final DSSDocument origDoc, final CertificateVerifier certificateVerifier) { super(params, origDoc, certificateVerifier); setCanonicalizationMethods(params, CanonicalizationMethod.INCLUSIVE); } @Override protected DSSReference createReference(DSSDocument document, int referenceIndex) { // <ds:Reference Id="signed-data-ref" Type="http://www.w3.org/2000/09/xmldsig#Object" // URI="#signed-data-idfc5ff27ee49763d9ba88ba5bbc49f732"> final DSSReference reference = new DSSReference(); reference.setId("r-id-" + referenceIndex); reference.setType(HTTP_WWW_W3_ORG_2000_09_XMLDSIG_OBJECT); reference.setUri("#o-id-" + referenceIndex); reference.setContents(document); reference.setDigestMethodAlgorithm(params.getDigestAlgorithm()); if (reference.getContents().getMimeType() == MimeType.XML && params.isEmbedXML()) { DSSTransform xmlTransform = new DSSTransform(); xmlTransform.setAlgorithm(Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS); reference.setTransforms(Arrays.asList(xmlTransform)); } else { DSSTransform base64Transform = new DSSTransform(); base64Transform.setAlgorithm(CanonicalizationMethod.BASE64); reference.setTransforms(Arrays.asList(base64Transform)); } return reference; } @Override protected DSSDocument transformReference(final DSSReference reference) { return reference.getContents(); } /** * Adds signature value to the signature and returns XML signature (InMemoryDocument) * * @param signatureValue * @return * @throws DSSException */ @Override public DSSDocument signDocument(final byte[] signatureValue) throws DSSException { if (!built) { build(); } final EncryptionAlgorithm encryptionAlgorithm = params.getEncryptionAlgorithm(); final byte[] signatureValueBytes = DSSSignatureUtils.convertToXmlDSig(encryptionAlgorithm, signatureValue); final String signatureValueBase64Encoded = Utils.toBase64(signatureValueBytes); final Text signatureValueNode = documentDom.createTextNode(signatureValueBase64Encoded); signatureValueDom.appendChild(signatureValueNode); final List<DSSReference> references = params.getReferences(); for (final DSSReference reference : references) { final String id = reference.getUri().substring(1); // <ds:Object> DSSDocument tbsDoc = reference.getContents(); if (tbsDoc.getMimeType() == MimeType.XML && params.isEmbedXML()) { try { Document doc = DomUtils.buildDOM(reference.getContents().openStream()); Element root = doc.getDocumentElement(); Node adopted = documentDom.adoptNode(root); final Element dom = documentDom.createElementNS(XMLSignature.XMLNS, DS_OBJECT); dom.appendChild(adopted); signatureDom.appendChild(dom); dom.setAttribute(ID, id); } catch (Exception e) { throw new DSSException(e); } } else { final String base64EncodedOriginalDocument = Utils.toBase64(DSSUtils.toByteArray(reference.getContents())); final Element objectDom = DomUtils.addTextElement(documentDom, signatureDom, XMLSignature.XMLNS, DS_OBJECT, base64EncodedOriginalDocument); objectDom.setAttribute(ID, id); } } byte[] documentBytes = DSSXMLUtils.serializeNode(documentDom); final InMemoryDocument inMemoryDocument = new InMemoryDocument(documentBytes); inMemoryDocument.setMimeType(MimeType.XML); return inMemoryDocument; } }