Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java?rev=1874671&r1=1874670&r2=1874671&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java Sun Mar 1 22:20:38 2020 @@ -31,6 +31,7 @@ import java.io.IOException; import java.io.OutputStream; import java.security.GeneralSecurityException; import java.security.PrivateKey; +import java.security.Provider; import java.util.ArrayList; import java.util.Base64; import java.util.HashMap; @@ -38,6 +39,8 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.stream.Stream; import javax.xml.crypto.MarshalException; import javax.xml.crypto.URIDereferencer; @@ -52,6 +55,7 @@ import javax.xml.crypto.dsig.XMLObject; import javax.xml.crypto.dsig.XMLSignatureException; import javax.xml.crypto.dsig.XMLSignatureFactory; import javax.xml.crypto.dsig.dom.DOMSignContext; +import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; import org.apache.jcp.xml.dsig.internal.dom.DOMReference; @@ -70,7 +74,6 @@ import org.apache.poi.openxml4j.opc.Pack import org.apache.poi.openxml4j.opc.TargetMode; import org.apache.poi.poifs.crypt.CryptoFunctions; import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable; import org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet; import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService; import org.apache.poi.util.POILogFactory; @@ -84,6 +87,7 @@ import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.w3c.dom.events.EventListener; import org.w3c.dom.events.EventTarget; +import org.w3c.dom.events.MutationEvent; /** @@ -153,20 +157,16 @@ import org.w3c.dom.events.EventTarget; * <li>and slf4j-api (tested against 1.7.30)</li> * </ul> */ -public class SignatureInfo implements SignatureConfigurable { +public class SignatureInfo { private static final POILogger LOG = POILogFactory.getLogger(SignatureInfo.class); - private static boolean isInitialized; private SignatureConfig signatureConfig; - - - /** - * Constructor initializes xml signature environment, if it hasn't been initialized before - */ - public SignatureInfo() { - initXmlProvider(); - } + private OPCPackage opcPackage; + private Provider provider; + private XMLSignatureFactory signatureFactory; + private KeyInfoFactory keyInfoFactory; + private URIDereferencer uriDereferencer; /** * @return the signature config @@ -178,30 +178,45 @@ public class SignatureInfo implements Si /** * @param signatureConfig the signature config, needs to be set before a SignatureInfo object is used */ - @Override public void setSignatureConfig(SignatureConfig signatureConfig) { this.signatureConfig = signatureConfig; } + public void setOpcPackage(OPCPackage opcPackage) { + this.opcPackage = opcPackage; + } + + public OPCPackage getOpcPackage() { + return opcPackage; + } + + public URIDereferencer getUriDereferencer() { + return uriDereferencer; + } + + public void setUriDereferencer(URIDereferencer uriDereferencer) { + this.uriDereferencer = uriDereferencer; + } + /** * @return true, if first signature part is valid */ public boolean verifySignature() { + initXmlProvider(); // http://www.oracle.com/technetwork/articles/javase/dig-signature-api-140772.html - for (SignaturePart sp : getSignatureParts()){ - // only validate first part - return sp.validate(); - } - return false; + // only validate first part + Iterator<SignaturePart> iter = getSignatureParts().iterator(); + return iter.hasNext() && iter.next().validate(); } /** * add the xml signature to the document * - * @throws XMLSignatureException - * @throws MarshalException + * @throws XMLSignatureException if the signature can't be calculated + * @throws MarshalException if the document can't be serialized */ public void confirmSignature() throws XMLSignatureException, MarshalException { + initXmlProvider(); final Document document = DocumentHelper.createDocument(); final DOMSignContext xmlSignContext = createXMLSignContext(document); @@ -223,6 +238,7 @@ public class SignatureInfo implements Si * @return the initialized signature context */ public DOMSignContext createXMLSignContext(final Document document) { + initXmlProvider(); return new DOMSignContext(signatureConfig.getKey(), document); } @@ -231,10 +247,10 @@ public class SignatureInfo implements Si * Sign (encrypt) the digest with the private key. * Currently only rsa is supported. * - * @param digest the hashed input * @return the encrypted hash */ public String signDigest(final DOMSignContext xmlSignContext, final DOMSignedInfo signedInfo) { + initXmlProvider(); final PrivateKey key = signatureConfig.getKey(); final HashAlgorithm algo = signatureConfig.getDigestAlgo(); @@ -243,12 +259,12 @@ public class SignatureInfo implements Si if (algo.hashSize*4/3 > BASE64DEFAULTLENGTH && !XMLUtils.ignoreLineBreaks()) { - throw new EncryptedDocumentException("The hash size of the choosen hash algorithm ("+algo+" = "+algo.hashSize+" bytes), "+ + throw new EncryptedDocumentException("The hash size of the chosen hash algorithm ("+algo+" = "+algo.hashSize+" bytes), "+ "will motivate XmlSec to add linebreaks to the generated digest, which results in an invalid signature (... at least "+ "for Office) - please persuade it otherwise by adding '-Dorg.apache.xml.security.ignoreLineBreaks=true' to the JVM "+ "system properties."); } - + try (final DigestOutputStream dos = getDigestStream(algo, key)) { dos.init(); @@ -277,78 +293,61 @@ public class SignatureInfo implements Si * the parts can be validated independently. */ public Iterable<SignaturePart> getSignatureParts() { - signatureConfig.init(true); - return new Iterable<SignaturePart>() { - @Override - public Iterator<SignaturePart> iterator() { - return new Iterator<SignaturePart>() { - OPCPackage pkg = signatureConfig.getOpcPackage(); - Iterator<PackageRelationship> sigOrigRels = - pkg.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN).iterator(); - Iterator<PackageRelationship> sigRels; - PackagePart sigPart; - - @Override - public boolean hasNext() { - while (sigRels == null || !sigRels.hasNext()) { - if (!sigOrigRels.hasNext()) { - return false; - } - sigPart = pkg.getPart(sigOrigRels.next()); - LOG.log(POILogger.DEBUG, "Digital Signature Origin part", sigPart); - try { - sigRels = sigPart.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE).iterator(); - } catch (InvalidFormatException e) { - LOG.log(POILogger.WARN, "Reference to signature is invalid.", e); - } - } - return true; - } + initXmlProvider(); + return SignaturePartIterator::new; + } - @Override - public SignaturePart next() { - PackagePart sigRelPart = null; - do { - try { - if (!hasNext()) { - throw new NoSuchElementException(); - } - sigRelPart = sigPart.getRelatedPart(sigRels.next()); - LOG.log(POILogger.DEBUG, "XML Signature part", sigRelPart); - } catch (InvalidFormatException e) { - LOG.log(POILogger.WARN, "Reference to signature is invalid.", e); - } - } while (sigRelPart == null); - return new SignaturePart(sigRelPart, signatureConfig); - } + private final class SignaturePartIterator implements Iterator<SignaturePart> { + Iterator<PackageRelationship> sigOrigRels; + private Iterator<PackageRelationship> sigRels; + private PackagePart sigPart; - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; + private SignaturePartIterator() { + sigOrigRels = opcPackage.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN).iterator(); + } + + @Override + public boolean hasNext() { + while (sigRels == null || !sigRels.hasNext()) { + if (!sigOrigRels.hasNext()) { + return false; + } + sigPart = opcPackage.getPart(sigOrigRels.next()); + LOG.log(POILogger.DEBUG, "Digital Signature Origin part", sigPart); + try { + sigRels = sigPart.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE).iterator(); + } catch (InvalidFormatException e) { + LOG.log(POILogger.WARN, "Reference to signature is invalid.", e); + } } - }; - } + return true; + } - /** - * Initialize the xml signing environment and the bouncycastle provider - */ - protected static synchronized void initXmlProvider() { - if (isInitialized) { - return; + @Override + public SignaturePart next() { + PackagePart sigRelPart = null; + do { + try { + if (!hasNext()) { + throw new NoSuchElementException(); + } + sigRelPart = sigPart.getRelatedPart(sigRels.next()); + LOG.log(POILogger.DEBUG, "XML Signature part", sigRelPart); + } catch (InvalidFormatException e) { + LOG.log(POILogger.WARN, "Reference to signature is invalid.", e); + } + } while (sigRelPart == null); + return new SignaturePart(sigRelPart, SignatureInfo.this); } - isInitialized = true; - try { - Init.init(); - RelationshipTransformService.registerDsigProvider(); - CryptoFunctions.registerBouncyCastle(); - } catch (Exception e) { - throw new RuntimeException("Xml & BouncyCastle-Provider initialization failed", e); + @Override + public void remove() { + throw new UnsupportedOperationException(); } } + + /** * Helper method for adding informations before the signing. * Normally {@link #confirmSignature()} is sufficient to be used. @@ -356,35 +355,18 @@ public class SignatureInfo implements Si @SuppressWarnings("unchecked") public DOMSignedInfo preSign(final DOMSignContext xmlSignContext) throws XMLSignatureException, MarshalException { - signatureConfig.init(false); - final Document document = (Document)xmlSignContext.getParent(); - // it's necessary to explicitly set the mdssi namespace, but the sign() method has no - // normal way to interfere with, so we need to add the namespace under the hand ... - EventTarget target = (EventTarget)document; - EventListener creationListener = signatureConfig.getSignatureMarshalListener(); - if (creationListener != null) { - if (creationListener instanceof SignatureMarshalListener) { - ((SignatureMarshalListener)creationListener).setEventTarget(target); - } - SignatureMarshalListener.setListener(target, creationListener, true); - } + registerEventListener(document); - /* - * Signature context construction. - */ - URIDereferencer uriDereferencer = signatureConfig.getUriDereferencer(); - if (null != uriDereferencer) { + // Signature context construction. + if (uriDereferencer != null) { xmlSignContext.setURIDereferencer(uriDereferencer); } signatureConfig.getNamespacePrefixes().forEach(xmlSignContext::putNamespacePrefix); xmlSignContext.setDefaultNamespacePrefix(""); - // signatureConfig.getNamespacePrefixes().get(XML_DIGSIG_NS)); - - XMLSignatureFactory signatureFactory = signatureConfig.getSignatureFactory(); /* * Add ds:References that come from signing client local files. @@ -397,7 +379,7 @@ public class SignatureInfo implements Si List<XMLObject> objects = new ArrayList<>(); for (SignatureFacet signatureFacet : signatureConfig.getSignatureFacets()) { LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName()); - signatureFacet.preSign(document, references, objects); + signatureFacet.preSign(this, document, references, objects); } /* @@ -471,6 +453,35 @@ public class SignatureInfo implements Si return (DOMSignedInfo)signedInfo; } + // it's necessary to explicitly set the mdssi namespace, but the sign() method has no + // normal way to interfere with, so we need to add the namespace under the hand ... + protected void registerEventListener(Document document) { + final SignatureMarshalListener sml = signatureConfig.getSignatureMarshalListener(); + if (sml == null) { + return; + } + + EventTarget target = (EventTarget)document; + + final EventListener[] el = { null }; + el[0] = (e) -> { + if (!(e instanceof MutationEvent)) { + return; + } + + MutationEvent mutEvt = (MutationEvent) e; + EventTarget et = mutEvt.getTarget(); + if (!(et instanceof Element)) { + return; + } + + sml.handleElement(this, (Element) et, target, el[0]); + }; + + SignatureMarshalListener.setListener(target, el[0], true); + } + + /** * Helper method for adding informations after the signing. * Normally {@link #confirmSignature()} is sufficient to be used. @@ -492,7 +503,7 @@ public class SignatureInfo implements Si /* * Insert signature value into the ds:SignatureValue element */ - final Element signatureNode = getDsigElement(document, "SignatureValue"); + final Element signatureNode = getDsigElement(document, "SignatureValue"); if (signatureNode == null) { throw new RuntimeException("preSign has to be called before postSign"); } @@ -502,7 +513,7 @@ public class SignatureInfo implements Si * Allow signature facets to inject their own stuff. */ for (SignatureFacet signatureFacet : signatureConfig.getSignatureFacets()) { - signatureFacet.postSign(document); + signatureFacet.postSign(this, document); } writeDocument(document); @@ -512,7 +523,7 @@ public class SignatureInfo implements Si * Write XML signature into the OPC package * * @param document the xml signature document - * @throws MarshalException + * @throws MarshalException if the document can't be serialized */ protected void writeDocument(Document document) throws MarshalException { XmlOptions xo = new XmlOptions(); @@ -527,23 +538,21 @@ public class SignatureInfo implements Si * Copy the original OOXML content to the signed OOXML package. During * copying some files need to changed. */ - OPCPackage pkg = signatureConfig.getOpcPackage(); - try { // <Default Extension="sigs" ContentType="application/vnd.openxmlformats-package.digital-signature-origin"/> final DSigRelation originDesc = DSigRelation.ORIGIN_SIGS; PackagePartName originPartName = PackagingURIHelper.createPartName(originDesc.getFileName(0)); - PackagePart originPart = pkg.getPart(originPartName); + PackagePart originPart = opcPackage.getPart(originPartName); if (originPart == null) { // touch empty marker file - originPart = pkg.createPart(originPartName, originDesc.getContentType()); - pkg.addRelationship(originPartName, TargetMode.INTERNAL, originDesc.getRelation()); + originPart = opcPackage.createPart(originPartName, originDesc.getContentType()); + opcPackage.addRelationship(originPartName, TargetMode.INTERNAL, originDesc.getRelation()); } // <Override PartName="/_xmlsignatures/sig1.xml" ContentType="application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"/> final DSigRelation sigDesc = DSigRelation.SIG; - int nextSigIdx = pkg.getUnusedPartIndex(sigDesc.getDefaultFileName()); + int nextSigIdx = opcPackage.getUnusedPartIndex(sigDesc.getDefaultFileName()); if (!signatureConfig.isAllowMultipleSignatures()) { PackageRelationshipCollection prc = originPart.getRelationshipsByType(sigDesc.getRelation()); @@ -558,16 +567,16 @@ public class SignatureInfo implements Si } } - pkg.removePart(pkg.getPart(pn)); + opcPackage.removePart(opcPackage.getPart(pn)); } nextSigIdx = 1; } PackagePartName sigPartName = PackagingURIHelper.createPartName(sigDesc.getFileName(nextSigIdx)); - PackagePart sigPart = pkg.getPart(sigPartName); + PackagePart sigPart = opcPackage.getPart(sigPartName); if (sigPart == null) { - sigPart = pkg.createPart(sigPartName, sigDesc.getContentType()); + sigPart = opcPackage.createPart(sigPartName, sigDesc.getContentType()); originPart.addRelationship(sigPartName, TargetMode.INTERNAL, sigDesc.getRelation()); } else { sigPart.clear(); @@ -590,7 +599,123 @@ public class SignatureInfo implements Si } LOG.log(POILogger.WARN, "Signature element '"+localName+"' was "+(sigValNl.getLength() == 0 ? "not found" : "multiple times")); - + return null; } + + public void setProvider(Provider provider) { + this.provider = provider; + } + + public void setSignatureFactory(XMLSignatureFactory signatureFactory) { + this.signatureFactory = signatureFactory; + } + + public XMLSignatureFactory getSignatureFactory() { + return signatureFactory; + } + + public void setKeyInfoFactory(KeyInfoFactory keyInfoFactory) { + this.keyInfoFactory = keyInfoFactory; + } + + public KeyInfoFactory getKeyInfoFactory() { + return keyInfoFactory; + } + + + + /** + * Initialize the xml signing environment and the bouncycastle provider + */ + @SuppressWarnings("deprecation") + protected void initXmlProvider() { + if (opcPackage == null) { + opcPackage = signatureConfig.getOpcPackage(); + } + if (provider == null) { + provider = signatureConfig.getProvider(); + if (provider == null) { + provider = XmlProviderInitSingleton.getInstance().findProvider(); + } + } + if (signatureFactory == null) { + signatureFactory = signatureConfig.getSignatureFactory(); + if (signatureFactory == null) { + signatureFactory = XMLSignatureFactory.getInstance("DOM", provider); + } + } + if (keyInfoFactory == null) { + keyInfoFactory = signatureConfig.getKeyInfoFactory(); + if (keyInfoFactory == null) { + keyInfoFactory = KeyInfoFactory.getInstance("DOM", provider); + } + } + if (uriDereferencer == null) { + uriDereferencer = signatureConfig.getUriDereferencer(); + if (uriDereferencer == null) { + uriDereferencer = new OOXMLURIDereferencer(); + } + } + if (uriDereferencer instanceof OOXMLURIDereferencer) { + ((OOXMLURIDereferencer)uriDereferencer).setSignatureInfo(this); + } + } + + private static final class XmlProviderInitSingleton { + + // Bill Pugh Singleton + private static class SingletonHelper { + private static final XmlProviderInitSingleton INSTANCE = new XmlProviderInitSingleton(); + } + + public static XmlProviderInitSingleton getInstance(){ + return SingletonHelper.INSTANCE; + } + + private XmlProviderInitSingleton() { + try { + Init.init(); + RelationshipTransformService.registerDsigProvider(); + CryptoFunctions.registerBouncyCastle(); + } catch (Exception e) { + throw new RuntimeException("Xml & BouncyCastle-Provider initialization failed", e); + } + } + + /** + * This method tests the existence of xml signature provider in the following order: + * <ul> + * <li>the class pointed to by the system property "jsr105Provider"</li> + * <li>the Santuario xmlsec provider</li> + * <li>the JDK xmlsec provider</li> + * </ul> + * + * For signing the classes are linked against the Santuario xmlsec, so this might + * only work for validation (not tested). + * + * @return the xml dsig provider + */ + public Provider findProvider() { + return + Stream.of(SignatureConfig.getProviderNames()) + .map(this::getProvider) + .filter(Objects::nonNull).findFirst() + .orElseThrow(this::providerNotFound); + } + + private Provider getProvider(String className) { + try { + return (Provider)Class.forName(className).newInstance(); + } catch (Exception e) { + LOG.log(POILogger.DEBUG, "XMLDsig-Provider '"+className+"' can't be found - trying next."); + return null; + } + } + + private RuntimeException providerNotFound() { + return new RuntimeException("JRE doesn't support default xml signature provider - set jsr105Provider system property!"); + } + } + }
Added: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureMarshalDefaultListener.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureMarshalDefaultListener.java?rev=1874671&view=auto ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureMarshalDefaultListener.java (added) +++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureMarshalDefaultListener.java Sun Mar 1 22:20:38 2020 @@ -0,0 +1,63 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt.dsig; + +import static org.apache.poi.poifs.crypt.dsig.SignatureMarshalListener.setListener; +import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.OO_DIGSIG_NS; +import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.XML_NS; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.events.EventListener; +import org.w3c.dom.events.EventTarget; + +/** + * This listener class is used, to modify the to be digested xml document, + * e.g. to register id attributes or set prefixes for registered namespaces + */ +public class SignatureMarshalDefaultListener implements SignatureMarshalListener { + @Override + public void handleElement(SignatureInfo signatureInfo, Element el, EventTarget target, EventListener parentListener) { + if (el.hasAttribute("Id")) { + el.setIdAttribute("Id", true); + } + + setListener(target, parentListener, false); + if (OO_DIGSIG_NS.equals(el.getNamespaceURI())) { + String parentNS = el.getParentNode().getNamespaceURI(); + if (!OO_DIGSIG_NS.equals(parentNS) && !el.hasAttributeNS(XML_NS, "mdssi")) { + el.setAttributeNS(XML_NS, "xmlns:mdssi", OO_DIGSIG_NS); + } + } + setPrefix(signatureInfo, el); + setListener(target, parentListener, true); + } + + protected static void setPrefix(SignatureInfo signatureInfo, Node el) { + String prefix = signatureInfo.getSignatureConfig().getNamespacePrefixes().get(el.getNamespaceURI()); + if (prefix != null && el.getPrefix() == null) { + el.setPrefix(prefix); + } + + NodeList nl = el.getChildNodes(); + for (int i=0; i<nl.getLength(); i++) { + setPrefix(signatureInfo, nl.item(i)); + } + } +} Propchange: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureMarshalDefaultListener.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureMarshalListener.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureMarshalListener.java?rev=1874671&r1=1874670&r2=1874671&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureMarshalListener.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureMarshalListener.java Sun Mar 1 22:20:38 2020 @@ -17,85 +17,25 @@ package org.apache.poi.poifs.crypt.dsig; -import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.OO_DIGSIG_NS; -import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet.XML_NS; - -import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable; import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.events.Event; import org.w3c.dom.events.EventListener; import org.w3c.dom.events.EventTarget; -import org.w3c.dom.events.MutationEvent; /** - * This listener class is used, to modify the to be digested xml document, + * This listener interface is used, to modify the to be digested xml document, * e.g. to register id attributes or set prefixes for registered namespaces */ -public class SignatureMarshalListener implements EventListener, SignatureConfigurable { - ThreadLocal<EventTarget> target = new ThreadLocal<>(); - SignatureConfig signatureConfig; - public void setEventTarget(EventTarget target) { - this.target.set(target); - } - - @Override - public void handleEvent(Event e) { - if (!(e instanceof MutationEvent)) { - return; - } - MutationEvent mutEvt = (MutationEvent)e; - EventTarget et = mutEvt.getTarget(); - if (!(et instanceof Element)) { - return; - } - handleElement((Element)et); - } - - public void handleElement(Element el) { - EventTarget target = this.target.get(); - - if (el.hasAttribute("Id")) { - el.setIdAttribute("Id", true); - } - - setListener(target, this, false); - if (OO_DIGSIG_NS.equals(el.getNamespaceURI())) { - String parentNS = el.getParentNode().getNamespaceURI(); - if (!OO_DIGSIG_NS.equals(parentNS) && !el.hasAttributeNS(XML_NS, "mdssi")) { - el.setAttributeNS(XML_NS, "xmlns:mdssi", OO_DIGSIG_NS); - } - } - setPrefix(el); - setListener(target, this, true); - } +public interface SignatureMarshalListener { + void handleElement(SignatureInfo signatureInfo, Element el, EventTarget target, EventListener parentListener); // helper method to keep it in one place - public static void setListener(EventTarget target, EventListener listener, boolean enabled) { - String type = "DOMSubtreeModified"; - boolean useCapture = false; + static void setListener(EventTarget target, EventListener listener, boolean enabled) { + final String type = "DOMSubtreeModified"; + final boolean DONT_USE_CAPTURE = false; if (enabled) { - target.addEventListener(type, listener, useCapture); + target.addEventListener(type, listener, DONT_USE_CAPTURE); } else { - target.removeEventListener(type, listener, useCapture); + target.removeEventListener(type, listener, DONT_USE_CAPTURE); } } - - protected void setPrefix(Node el) { - String prefix = signatureConfig.getNamespacePrefixes().get(el.getNamespaceURI()); - if (prefix != null && el.getPrefix() == null) { - el.setPrefix(prefix); - } - - NodeList nl = el.getChildNodes(); - for (int i=0; i<nl.getLength(); i++) { - setPrefix(nl.item(i)); - } - } - - @Override - public void setSignatureConfig(SignatureConfig signatureConfig) { - this.signatureConfig = signatureConfig; - } } \ No newline at end of file Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignaturePart.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignaturePart.java?rev=1874671&r1=1874670&r2=1874671&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignaturePart.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignaturePart.java Sun Mar 1 22:20:38 2020 @@ -30,6 +30,7 @@ import java.util.Map; import java.util.function.Consumer; import javax.xml.crypto.MarshalException; +import javax.xml.crypto.URIDereferencer; import javax.xml.crypto.dsig.XMLSignature; import javax.xml.crypto.dsig.XMLSignatureException; import javax.xml.crypto.dsig.XMLSignatureFactory; @@ -54,40 +55,40 @@ import org.xml.sax.SAXException; public class SignaturePart { private static final POILogger LOG = POILogFactory.getLogger(SignaturePart.class); - private static final String XMLSEC_VALIDATE_MANIFEST = "org.jcp.xml.dsig.validateManifests"; + private static final String XMLSEC_VALIDATE_MANIFEST = "org.jcp.xml.dsig.validateManifests"; + - private final PackagePart signaturePart; - private final SignatureConfig signatureConfig; + private final SignatureInfo signatureInfo; private X509Certificate signer; private List<X509Certificate> certChain; - - /* package */ SignaturePart(final PackagePart signaturePart, final SignatureConfig signatureConfig) { + + /* package */ SignaturePart(final PackagePart signaturePart, final SignatureInfo signatureInfo) { this.signaturePart = signaturePart; - this.signatureConfig = signatureConfig; + this.signatureInfo = signatureInfo; } - + /** * @return the package part containing the signature */ public PackagePart getPackagePart() { return signaturePart; } - + /** * @return the signer certificate */ public X509Certificate getSigner() { return signer; } - + /** * @return the certificate chain of the signer */ public List<X509Certificate> getCertChain() { return certChain; } - + /** * Helper method for examining the xml signature * @@ -102,7 +103,7 @@ public class SignaturePart { /** * @return true, when the xml signature is valid, false otherwise - * + * * @throws EncryptedDocumentException if the signature can't be extracted or if its malformed */ public boolean validate() { @@ -117,14 +118,16 @@ public class SignaturePart { for (int i=0; i<length; i++) { ((Element)nl.item(i)).setIdAttribute("Id", true); } - + DOMValidateContext domValidateContext = new DOMValidateContext(keySelector, doc); domValidateContext.setProperty(XMLSEC_VALIDATE_MANIFEST, Boolean.TRUE); - domValidateContext.setURIDereferencer(signatureConfig.getUriDereferencer()); - XMLSignatureFactory xmlSignatureFactory = signatureConfig.getSignatureFactory(); + URIDereferencer uriDereferencer = signatureInfo.getUriDereferencer(); + domValidateContext.setURIDereferencer(uriDereferencer); + + XMLSignatureFactory xmlSignatureFactory = signatureInfo.getSignatureFactory(); XMLSignature xmlSignature = xmlSignatureFactory.unmarshalXMLSignature(domValidateContext); - + boolean valid = xmlSignature.validate(domValidateContext); if (valid) { @@ -132,7 +135,7 @@ public class SignaturePart { certChain = keySelector.getCertChain(); extractConfig(doc, xmlSignature); } - + return valid; } catch (IOException e) { String s = "error in reading document"; @@ -158,6 +161,7 @@ public class SignaturePart { } private void extractConfig(final Document doc, final XMLSignature xmlSignature) throws XPathExpressionException { + SignatureConfig signatureConfig = signatureInfo.getSignatureConfig(); if (!signatureConfig.isUpdateConfigOnValidate()) { return; } @@ -168,7 +172,7 @@ public class SignaturePart { final XPath xpath = XPathHelper.getFactory().newXPath(); xpath.setNamespaceContext(new XPathNSContext()); - final Map<String,Consumer<String>> m = new HashMap(); + final Map<String,Consumer<String>> m = new HashMap<>(); m.put("//mdssi:SignatureTime/mdssi:Value", signatureConfig::setExecutionTime); m.put("//xd:ClaimedRole", signatureConfig::setXadesRole); m.put("//dsss:SignatureComments", signatureConfig::setSignatureDescription); @@ -185,7 +189,7 @@ public class SignaturePart { final Map<String,String> nsMap = new HashMap<>(); { - signatureConfig.getNamespacePrefixes().forEach((k,v) -> nsMap.put(v,k)); + signatureInfo.getSignatureConfig().getNamespacePrefixes().forEach((k,v) -> nsMap.put(v,k)); nsMap.put("dsss", MS_DIGSIG_NS); nsMap.put("ds", XML_DIGSIG_NS); } @@ -193,6 +197,8 @@ public class SignaturePart { public String getNamespaceURI(String prefix) { return nsMap.get(prefix); } + @SuppressWarnings("rawtypes") + @Override public Iterator getPrefixes(String val) { return null; } Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java?rev=1874671&r1=1874670&r2=1874671&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java Sun Mar 1 22:20:38 2020 @@ -18,12 +18,15 @@ /* ==================================================================== This product contains an ASLv2 licensed version of the OOXML signer package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt Copyright (C) 2008-2014 FedICT. - ================================================================= */ + ================================================================= */ package org.apache.poi.poifs.crypt.dsig.facets; +import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacetHelper.newReference; +import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacetHelper.newTransform; + import java.util.ArrayList; import java.util.List; @@ -33,28 +36,29 @@ import javax.xml.crypto.dsig.Transform; import javax.xml.crypto.dsig.XMLObject; import javax.xml.crypto.dsig.XMLSignatureException; +import org.apache.poi.poifs.crypt.dsig.SignatureInfo; import org.w3c.dom.Document; /** * Signature Facet implementation to create enveloped signatures. - * + * * @author Frank Cornelis - * */ -public class EnvelopedSignatureFacet extends SignatureFacet { +public class EnvelopedSignatureFacet implements SignatureFacet { @Override - public void preSign(Document document + public void preSign(SignatureInfo signatureInfo + , Document document , List<Reference> references , List<XMLObject> objects) throws XMLSignatureException { List<Transform> transforms = new ArrayList<>(); - Transform envelopedTransform = newTransform(CanonicalizationMethod.ENVELOPED); + Transform envelopedTransform = newTransform(signatureInfo, CanonicalizationMethod.ENVELOPED); transforms.add(envelopedTransform); - Transform exclusiveTransform = newTransform(CanonicalizationMethod.EXCLUSIVE); + Transform exclusiveTransform = newTransform(signatureInfo, CanonicalizationMethod.EXCLUSIVE); transforms.add(exclusiveTransform); - Reference reference = newReference("", transforms, null, null, null); + Reference reference = newReference(signatureInfo, "", transforms, null, null, null); references.add(reference); } } Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java?rev=1874671&r1=1874670&r2=1874671&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java Sun Mar 1 22:20:38 2020 @@ -18,9 +18,9 @@ /* ==================================================================== This product contains an ASLv2 licensed version of the OOXML signer package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt Copyright (C) 2008-2014 FedICT. - ================================================================= */ + ================================================================= */ package org.apache.poi.poifs.crypt.dsig.facets; @@ -29,7 +29,6 @@ import java.security.KeyException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; -import java.util.Map; import javax.xml.crypto.MarshalException; import javax.xml.crypto.XMLStructure; @@ -41,6 +40,8 @@ import javax.xml.crypto.dsig.keyinfo.Key import javax.xml.crypto.dsig.keyinfo.X509Data; import org.apache.jcp.xml.dsig.internal.dom.DOMKeyInfo; +import org.apache.poi.poifs.crypt.dsig.SignatureConfig; +import org.apache.poi.poifs.crypt.dsig.SignatureInfo; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.w3c.dom.Document; @@ -50,21 +51,20 @@ import org.w3c.dom.NodeList; /** * Signature Facet implementation that adds ds:KeyInfo to the XML signature. - * + * * @author Frank Cornelis - * */ -public class KeyInfoSignatureFacet extends SignatureFacet { +public class KeyInfoSignatureFacet implements SignatureFacet { private static final POILogger LOG = POILogFactory.getLogger(KeyInfoSignatureFacet.class); - + @Override - public void postSign(Document document) + public void postSign(SignatureInfo signatureInfo, Document document) throws MarshalException { LOG.log(POILogger.DEBUG, "postSign"); NodeList nl = document.getElementsByTagNameNS(XML_DIGSIG_NS, "Object"); - + /* * Make sure we insert right after the ds:SignatureValue element, just * before the first ds:Object element. @@ -74,8 +74,9 @@ public class KeyInfoSignatureFacet exten /* * Construct the ds:KeyInfo element using JSR 105. */ - KeyInfoFactory keyInfoFactory = signatureConfig.getKeyInfoFactory(); + KeyInfoFactory keyInfoFactory = signatureInfo.getKeyInfoFactory(); List<Object> x509DataObjects = new ArrayList<>(); + SignatureConfig signatureConfig = signatureInfo.getSignatureConfig(); X509Certificate signingCertificate = signatureConfig.getSigningCertificateChain().get(0); List<XMLStructure> keyInfoContent = new ArrayList<>(); @@ -107,7 +108,7 @@ public class KeyInfoSignatureFacet exten keyInfoContent.add(x509Data); } KeyInfo keyInfo = keyInfoFactory.newKeyInfo(keyInfoContent); - DOMKeyInfo domKeyInfo = (DOMKeyInfo)keyInfo; + DOMKeyInfo domKeyInfo = (DOMKeyInfo)keyInfo; Key key = new Key() { private static final long serialVersionUID = 1L; @@ -133,7 +134,7 @@ public class KeyInfoSignatureFacet exten DOMStructure domStructure = new DOMStructure(n); domKeyInfo.marshal(domStructure, domSignContext); - + // move keyinfo into the right place if (nextSibling != null) { NodeList kiNl = document.getElementsByTagNameNS(XML_DIGSIG_NS, "KeyInfo"); Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java?rev=1874671&r1=1874670&r2=1874671&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java Sun Mar 1 22:20:38 2020 @@ -24,20 +24,21 @@ package org.apache.poi.poifs.crypt.dsig.facets; +import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacetHelper.newReference; +import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacetHelper.newTransform; + import java.net.URI; import java.net.URISyntaxException; -import java.text.DateFormat; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; -import java.util.Locale; import java.util.Set; import javax.xml.XMLConstants; +import javax.xml.crypto.URIReference; import javax.xml.crypto.XMLStructure; import javax.xml.crypto.dom.DOMStructure; import javax.xml.crypto.dsig.CanonicalizationMethod; @@ -48,7 +49,10 @@ import javax.xml.crypto.dsig.SignaturePr import javax.xml.crypto.dsig.Transform; import javax.xml.crypto.dsig.XMLObject; import javax.xml.crypto.dsig.XMLSignatureException; +import javax.xml.crypto.dsig.XMLSignatureFactory; +import com.microsoft.schemas.office.x2006.digsig.CTSignatureInfoV1; +import com.microsoft.schemas.office.x2006.digsig.SignatureInfoV1Document; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.opc.ContentTypes; import org.apache.poi.openxml4j.opc.OPCPackage; @@ -58,9 +62,10 @@ import org.apache.poi.openxml4j.opc.Pack import org.apache.poi.openxml4j.opc.PackageRelationshipCollection; import org.apache.poi.openxml4j.opc.PackagingURIHelper; import org.apache.poi.openxml4j.opc.TargetMode; +import org.apache.poi.poifs.crypt.dsig.SignatureConfig; +import org.apache.poi.poifs.crypt.dsig.SignatureInfo; import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService; import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService.RelationshipTransformParameterSpec; -import org.apache.poi.util.LocaleUtil; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.CTSignatureTime; @@ -68,58 +73,58 @@ import org.openxmlformats.schemas.xpacka import org.w3c.dom.Document; import org.w3c.dom.Element; -import com.microsoft.schemas.office.x2006.digsig.CTSignatureInfoV1; -import com.microsoft.schemas.office.x2006.digsig.SignatureInfoV1Document; - /** * Office OpenXML Signature Facet implementation. * * @see <a href="http://msdn.microsoft.com/en-us/library/cc313071.aspx">[MS-OFFCRYPTO]: Office Document Cryptography Structure</a> */ -public class OOXMLSignatureFacet extends SignatureFacet { +public class OOXMLSignatureFacet implements SignatureFacet { private static final POILogger LOG = POILogFactory.getLogger(OOXMLSignatureFacet.class); private static final String ID_PACKAGE_OBJECT = "idPackageObject"; @Override public void preSign( - Document document + SignatureInfo signatureInfo + , Document document , List<Reference> references , List<XMLObject> objects) throws XMLSignatureException { LOG.log(POILogger.DEBUG, "pre sign"); - addManifestObject(document, references, objects); - addSignatureInfo(document, references, objects); + addManifestObject(signatureInfo, document, references, objects); + addSignatureInfo(signatureInfo, document, references, objects); } protected void addManifestObject( - Document document + SignatureInfo signatureInfo + , Document document , List<Reference> references , List<XMLObject> objects) throws XMLSignatureException { + final XMLSignatureFactory sigFac = signatureInfo.getSignatureFactory(); + List<Reference> manifestReferences = new ArrayList<>(); - addManifestReferences(manifestReferences); - Manifest manifest = getSignatureFactory().newManifest(manifestReferences); + addManifestReferences(signatureInfo, manifestReferences); + Manifest manifest = sigFac.newManifest(manifestReferences); List<XMLStructure> objectContent = new ArrayList<>(); objectContent.add(manifest); - addSignatureTime(document, objectContent); + addSignatureTime(signatureInfo, document, objectContent); - XMLObject xo = getSignatureFactory().newXMLObject(objectContent, ID_PACKAGE_OBJECT, null, null); + XMLObject xo = sigFac.newXMLObject(objectContent, ID_PACKAGE_OBJECT, null, null); objects.add(xo); - Reference reference = newReference("#"+ID_PACKAGE_OBJECT, null, XML_DIGSIG_NS+"Object", null, null); + Reference reference = newReference(signatureInfo, "#"+ID_PACKAGE_OBJECT, null, XML_DIGSIG_NS+"Object", null, null); references.add(reference); } @SuppressWarnings("resource") - protected void addManifestReferences(List<Reference> manifestReferences) + protected void addManifestReferences(SignatureInfo signatureInfo, List<Reference> manifestReferences) throws XMLSignatureException { - - OPCPackage ooxml = signatureConfig.getOpcPackage(); - List<PackagePart> relsEntryNames = ooxml.getPartsByContentType(ContentTypes.RELATIONSHIPS_PART); + OPCPackage opcPackage = signatureInfo.getOpcPackage(); + List<PackagePart> relsEntryNames = opcPackage.getPartsByContentType(ContentTypes.RELATIONSHIPS_PART); Set<String> digestedPartNames = new HashSet<>(); for (PackagePart pp : relsEntryNames) { @@ -127,7 +132,7 @@ public class OOXMLSignatureFacet extends PackageRelationshipCollection prc; try { - prc = new PackageRelationshipCollection(ooxml); + prc = new PackageRelationshipCollection(opcPackage); prc.parseRelationshipsPart(pp); } catch (InvalidFormatException e) { throw new XMLSignatureException("Invalid relationship descriptor: "+pp.getPartName().getName(), e); @@ -163,7 +168,7 @@ public class OOXMLSignatureFacet extends String contentType; try { PackagePartName relName = PackagingURIHelper.createPartName(partName); - PackagePart pp2 = ooxml.getPart(relName); + PackagePart pp2 = opcPackage.getPart(relName); contentType = pp2.getContentType(); } catch (InvalidFormatException e) { throw new XMLSignatureException(e); @@ -176,26 +181,22 @@ public class OOXMLSignatureFacet extends } String uri = partName + "?ContentType=" + contentType; - Reference reference = newReference(uri, null, null, null, null); + Reference reference = newReference(signatureInfo, uri, null, null, null, null); manifestReferences.add(reference); } if (parameterSpec.hasSourceIds()) { List<Transform> transforms = new ArrayList<>(); - transforms.add(newTransform(RelationshipTransformService.TRANSFORM_URI, parameterSpec)); - transforms.add(newTransform(CanonicalizationMethod.INCLUSIVE)); + transforms.add(newTransform(signatureInfo, RelationshipTransformService.TRANSFORM_URI, parameterSpec)); + transforms.add(newTransform(signatureInfo, CanonicalizationMethod.INCLUSIVE)); String uri = normalizePartName(pp.getPartName().getURI(), baseUri) + "?ContentType=application/vnd.openxmlformats-package.relationships+xml"; - Reference reference = newReference(uri, transforms, null, null, null); + Reference reference = newReference(signatureInfo, uri, transforms, null, null, null); manifestReferences.add(reference); } } - - manifestReferences.sort(new Comparator<Reference>() { - public int compare(Reference o1, Reference o2) { - return o1.getURI().compareTo(o2.getURI()); - } - }); + + manifestReferences.sort(Comparator.comparing(URIReference::getURI)); } /** @@ -217,7 +218,9 @@ public class OOXMLSignatureFacet extends } - protected void addSignatureTime(Document document, List<XMLStructure> objectContent) { + protected void addSignatureTime(SignatureInfo signatureInfo, Document document, List<XMLStructure> objectContent) { + SignatureConfig signatureConfig = signatureInfo.getSignatureConfig(); + XMLSignatureFactory sigFac = signatureInfo.getSignatureFactory(); /* * SignatureTime */ @@ -230,20 +233,25 @@ public class OOXMLSignatureFacet extends Element n = (Element)document.importNode(ctTime.getDomNode(),true); List<XMLStructure> signatureTimeContent = new ArrayList<>(); signatureTimeContent.add(new DOMStructure(n)); - SignatureProperty signatureTimeSignatureProperty = getSignatureFactory() + SignatureProperty signatureTimeSignatureProperty = sigFac .newSignatureProperty(signatureTimeContent, "#" + signatureConfig.getPackageSignatureId(), "idSignatureTime"); List<SignatureProperty> signaturePropertyContent = new ArrayList<>(); signaturePropertyContent.add(signatureTimeSignatureProperty); - SignatureProperties signatureProperties = getSignatureFactory() + SignatureProperties signatureProperties = sigFac .newSignatureProperties(signaturePropertyContent, null); objectContent.add(signatureProperties); } - protected void addSignatureInfo(Document document, - List<Reference> references, - List<XMLObject> objects) + protected void addSignatureInfo( + SignatureInfo signatureInfo + , Document document + , List<Reference> references + , List<XMLObject> objects) throws XMLSignatureException { + SignatureConfig signatureConfig = signatureInfo.getSignatureConfig(); + XMLSignatureFactory sigFac = signatureInfo.getSignatureFactory(); + List<XMLStructure> objectContent = new ArrayList<>(); SignatureInfoV1Document sigV1 = SignatureInfoV1Document.Factory.newInstance(); @@ -259,20 +267,20 @@ public class OOXMLSignatureFacet extends List<XMLStructure> signatureInfoContent = new ArrayList<>(); signatureInfoContent.add(new DOMStructure(n)); - SignatureProperty signatureInfoSignatureProperty = getSignatureFactory() + SignatureProperty signatureInfoSignatureProperty = sigFac .newSignatureProperty(signatureInfoContent, "#" + signatureConfig.getPackageSignatureId(), "idOfficeV1Details"); List<SignatureProperty> signaturePropertyContent = new ArrayList<>(); signaturePropertyContent.add(signatureInfoSignatureProperty); - SignatureProperties signatureProperties = getSignatureFactory() + SignatureProperties signatureProperties = sigFac .newSignatureProperties(signaturePropertyContent, null); objectContent.add(signatureProperties); String objectId = "idOfficeObject"; - objects.add(getSignatureFactory().newXMLObject(objectContent, objectId, null, null)); + objects.add(sigFac.newXMLObject(objectContent, objectId, null, null)); - Reference reference = newReference("#" + objectId, null, XML_DIGSIG_NS+"Object", null, null); + Reference reference = newReference(signatureInfo, "#" + objectId, null, XML_DIGSIG_NS+"Object", null, null); references.add(reference); } Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java?rev=1874671&r1=1874670&r2=1874671&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java Sun Mar 1 22:20:38 2020 @@ -18,9 +18,9 @@ /* ==================================================================== This product contains an ASLv2 licensed version of the OOXML signer package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt Copyright (C) 2008-2014 FedICT. - ================================================================= */ + ================================================================= */ package org.apache.poi.poifs.crypt.dsig.facets; @@ -28,6 +28,7 @@ import static org.apache.poi.ooxml.POIXM import javax.xml.crypto.MarshalException; +import org.apache.poi.poifs.crypt.dsig.SignatureInfo; import org.apache.xmlbeans.XmlException; import org.etsi.uri.x01903.v13.QualifyingPropertiesType; import org.etsi.uri.x01903.v13.UnsignedPropertiesType; @@ -38,17 +39,15 @@ import org.w3c.dom.NodeList; /** * Work-around for Office2010 to accept the XAdES-BES/EPES signature. - * - * xades:UnsignedProperties/xades:UnsignedSignatureProperties needs to be - * present. - * + * + * xades:UnsignedProperties/xades:UnsignedSignatureProperties needs to be present. + * * @author Frank Cornelis - * */ -public class Office2010SignatureFacet extends SignatureFacet { +public class Office2010SignatureFacet implements SignatureFacet { @Override - public void postSign(Document document) + public void postSign(SignatureInfo signatureInfo, Document document) throws MarshalException { // check for XAdES-BES NodeList nl = document.getElementsByTagNameNS(XADES_132_NS, "QualifyingProperties"); @@ -62,7 +61,7 @@ public class Office2010SignatureFacet ex } catch (XmlException e) { throw new MarshalException(e); } - + // create basic XML container structure UnsignedPropertiesType unsignedProps = qualProps.getUnsignedProperties(); if (unsignedProps == null) { @@ -72,7 +71,7 @@ public class Office2010SignatureFacet ex if (unsignedSigProps == null) { /* unsignedSigProps = */ unsignedProps.addNewUnsignedSignatureProperties(); } - + Node n = document.importNode(qualProps.getDomNode().getFirstChild(), true); nl.item(0).getParentNode().replaceChild(n, nl.item(0)); } Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java?rev=1874671&r1=1874670&r2=1874671&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java Sun Mar 1 22:20:38 2020 @@ -18,70 +18,57 @@ /* ==================================================================== This product contains an ASLv2 licensed version of the OOXML signer package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt Copyright (C) 2008-2014 FedICT. - ================================================================= */ + ================================================================= */ package org.apache.poi.poifs.crypt.dsig.facets; -import java.security.GeneralSecurityException; import java.util.List; import javax.xml.XMLConstants; import javax.xml.crypto.MarshalException; -import javax.xml.crypto.dsig.DigestMethod; import javax.xml.crypto.dsig.Reference; -import javax.xml.crypto.dsig.Transform; import javax.xml.crypto.dsig.XMLObject; import javax.xml.crypto.dsig.XMLSignature; import javax.xml.crypto.dsig.XMLSignatureException; -import javax.xml.crypto.dsig.XMLSignatureFactory; -import javax.xml.crypto.dsig.spec.TransformParameterSpec; import org.apache.poi.openxml4j.opc.PackageNamespaces; -import org.apache.poi.poifs.crypt.dsig.SignatureConfig; -import org.apache.poi.poifs.crypt.dsig.SignatureConfig.SignatureConfigurable; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; +import org.apache.poi.poifs.crypt.dsig.SignatureInfo; +import org.apache.poi.util.Internal; import org.w3c.dom.Document; /** * JSR105 Signature Facet base class. */ -public abstract class SignatureFacet implements SignatureConfigurable { +@Internal +public interface SignatureFacet { - private static final POILogger LOG = POILogFactory.getLogger(SignatureFacet.class); - - public static final String XML_NS = XMLConstants.XMLNS_ATTRIBUTE_NS_URI; - public static final String XML_DIGSIG_NS = XMLSignature.XMLNS; - public static final String OO_DIGSIG_NS = PackageNamespaces.DIGITAL_SIGNATURE; - public static final String MS_DIGSIG_NS = "http://schemas.microsoft.com/office/2006/digsig"; - public static final String XADES_132_NS = "http://uri.etsi.org/01903/v1.3.2#"; - public static final String XADES_141_NS = "http://uri.etsi.org/01903/v1.4.1#"; - - protected SignatureConfig signatureConfig; - - @Override - public void setSignatureConfig(SignatureConfig signatureConfig) { - this.signatureConfig = signatureConfig; - } + String XML_NS = XMLConstants.XMLNS_ATTRIBUTE_NS_URI; + String XML_DIGSIG_NS = XMLSignature.XMLNS; + String OO_DIGSIG_NS = PackageNamespaces.DIGITAL_SIGNATURE; + String MS_DIGSIG_NS = "http://schemas.microsoft.com/office/2006/digsig"; + String XADES_132_NS = "http://uri.etsi.org/01903/v1.3.2#"; + String XADES_141_NS = "http://uri.etsi.org/01903/v1.4.1#"; /** * This method is being invoked by the XML signature service engine during * pre-sign phase. Via this method a signature facet implementation can add * signature facets to an XML signature. - * + * + * @param signatureInfo the signature info object holding the OPCPackage and other document related data * @param document the signature document to be used for imports * @param references list of reference definitions * @param objects objects to be signed/included in the signature document * @throws XMLSignatureException */ - public void preSign( - Document document + default void preSign( + SignatureInfo signatureInfo + , Document document , List<Reference> references , List<XMLObject> objects ) throws XMLSignatureException { - // empty + } /** @@ -89,62 +76,12 @@ public abstract class SignatureFacet imp * the post-sign phase. Via this method a signature facet can extend the XML * signatures with for example key information. * + * @param signatureInfo the signature info object holding the OPCPackage and other document related data * @param document the signature document to be modified * @throws MarshalException */ - public void postSign(Document document) throws MarshalException { - // empty - } + default void postSign(SignatureInfo signatureInfo, Document document) throws MarshalException { - protected XMLSignatureFactory getSignatureFactory() { - return signatureConfig.getSignatureFactory(); - } - - protected Transform newTransform(String canonicalizationMethod) throws XMLSignatureException { - return newTransform(canonicalizationMethod, null); - } - - protected Transform newTransform(String canonicalizationMethod, TransformParameterSpec paramSpec) - throws XMLSignatureException { - try { - return getSignatureFactory().newTransform(canonicalizationMethod, paramSpec); - } catch (GeneralSecurityException e) { - throw new XMLSignatureException("unknown canonicalization method: "+canonicalizationMethod, e); - } - } - - protected Reference newReference(String uri, List<Transform> transforms, String type, String id, byte[] digestValue) - throws XMLSignatureException { - return newReference(uri, transforms, type, id, digestValue, signatureConfig); } - public static Reference newReference( - String uri - , List<Transform> transforms - , String type - , String id - , byte[] digestValue - , SignatureConfig signatureConfig) - throws XMLSignatureException { - // the references appear in the package signature or the package object - // so we can use the default digest algorithm - String digestMethodUri = signatureConfig.getDigestMethodUri(); - XMLSignatureFactory sigFac = signatureConfig.getSignatureFactory(); - DigestMethod digestMethod; - try { - digestMethod = sigFac.newDigestMethod(digestMethodUri, null); - } catch (GeneralSecurityException e) { - throw new XMLSignatureException("unknown digest method uri: "+digestMethodUri, e); - } - - Reference reference; - if (digestValue == null) { - reference = sigFac.newReference(uri, digestMethod, transforms, type, id); - } else { - reference = sigFac.newReference(uri, digestMethod, transforms, type, id, digestValue); - } - - - return reference; - } } \ No newline at end of file Added: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacetHelper.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacetHelper.java?rev=1874671&view=auto ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacetHelper.java (added) +++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacetHelper.java Sun Mar 1 22:20:38 2020 @@ -0,0 +1,75 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.poifs.crypt.dsig.facets; + +import java.security.GeneralSecurityException; +import java.util.List; + +import javax.xml.crypto.dsig.DigestMethod; +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.Transform; +import javax.xml.crypto.dsig.XMLSignatureException; +import javax.xml.crypto.dsig.XMLSignatureFactory; +import javax.xml.crypto.dsig.spec.TransformParameterSpec; + +import org.apache.poi.poifs.crypt.dsig.SignatureConfig; +import org.apache.poi.poifs.crypt.dsig.SignatureInfo; +import org.apache.poi.util.Internal; + +@Internal +final class SignatureFacetHelper { + private SignatureFacetHelper() {} + + static Transform newTransform(SignatureInfo signatureInfo, String canonicalizationMethod) throws XMLSignatureException { + return newTransform(signatureInfo, canonicalizationMethod, null); + } + + static Transform newTransform(SignatureInfo signatureInfo, String canonicalizationMethod, TransformParameterSpec paramSpec) + throws XMLSignatureException { + try { + return signatureInfo.getSignatureFactory().newTransform(canonicalizationMethod, paramSpec); + } catch (GeneralSecurityException e) { + throw new XMLSignatureException("unknown canonicalization method: "+canonicalizationMethod, e); + } + } + + static Reference newReference( + SignatureInfo signatureInfo + , String uri + , List<Transform> transforms + , String type + , String id + , byte[] digestValue) + throws XMLSignatureException { + // the references appear in the package signature or the package object + // so we can use the default digest algorithm + SignatureConfig signatureConfig = signatureInfo.getSignatureConfig(); + String digestMethodUri = signatureConfig.getDigestMethodUri(); + XMLSignatureFactory sigFac = signatureInfo.getSignatureFactory(); + DigestMethod digestMethod; + try { + digestMethod = sigFac.newDigestMethod(digestMethodUri, null); + } catch (GeneralSecurityException e) { + throw new XMLSignatureException("unknown digest method uri: "+digestMethodUri, e); + } + + return (digestValue == null) + ? sigFac.newReference(uri, digestMethod, transforms, type, id) + : sigFac.newReference(uri, digestMethod, transforms, type, id, digestValue); + } +} Propchange: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacetHelper.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java?rev=1874671&r1=1874670&r2=1874671&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java Sun Mar 1 22:20:38 2020 @@ -18,13 +18,15 @@ /* ==================================================================== This product contains an ASLv2 licensed version of the OOXML signer package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt Copyright (C) 2008-2014 FedICT. - ================================================================= */ + ================================================================= */ package org.apache.poi.poifs.crypt.dsig.facets; import static java.util.Collections.singletonList; +import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacetHelper.newReference; +import static org.apache.poi.poifs.crypt.dsig.facets.SignatureFacetHelper.newTransform; import java.security.MessageDigest; import java.security.cert.CertificateEncodingException; @@ -48,6 +50,7 @@ import javax.xml.crypto.dsig.XMLSignatur import org.apache.poi.poifs.crypt.CryptoFunctions; import org.apache.poi.poifs.crypt.HashAlgorithm; import org.apache.poi.poifs.crypt.dsig.SignatureConfig; +import org.apache.poi.poifs.crypt.dsig.SignatureInfo; import org.apache.poi.poifs.crypt.dsig.services.SignaturePolicyService; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; @@ -77,36 +80,39 @@ import org.w3c.dom.Node; * XAdES Signature Facet. Implements XAdES v1.4.1 which is compatible with XAdES * v1.3.2. The implemented XAdES format is XAdES-BES/EPES. It's up to another * part of the signature service to upgrade the XAdES-BES to a XAdES-X-L. - * + * * This implementation has been tested against an implementation that * participated multiple ETSI XAdES plugtests. - * + * * @author Frank Cornelis * @see <a href="http://en.wikipedia.org/wiki/XAdES">XAdES</a> - * + * */ -public class XAdESSignatureFacet extends SignatureFacet { +public class XAdESSignatureFacet implements SignatureFacet { private static final POILogger LOG = POILogFactory.getLogger(XAdESSignatureFacet.class); private static final String XADES_TYPE = "http://uri.etsi.org/01903#SignedProperties"; - + private final Map<String, String> dataObjectFormatMimeTypes = new HashMap<>(); @Override public void preSign( - Document document + SignatureInfo signatureInfo + , Document document , List<Reference> references , List<XMLObject> objects) throws XMLSignatureException { LOG.log(POILogger.DEBUG, "preSign"); + SignatureConfig signatureConfig = signatureInfo.getSignatureConfig(); + // QualifyingProperties QualifyingPropertiesDocument qualDoc = QualifyingPropertiesDocument.Factory.newInstance(); QualifyingPropertiesType qualifyingProperties = qualDoc.addNewQualifyingProperties(); qualifyingProperties.setTarget("#" + signatureConfig.getPackageSignatureId()); - + // SignedProperties SignedPropertiesType signedProperties = qualifyingProperties.addNewSignedProperties(); signedProperties.setId(signatureConfig.getXadesSignatureId()); @@ -115,35 +121,37 @@ public class XAdESSignatureFacet extends SignedSignaturePropertiesType signedSignatureProperties = signedProperties.addNewSignedSignatureProperties(); // SigningTime - addSigningTime(signedSignatureProperties); + addSigningTime(signatureInfo, signedSignatureProperties); // SigningCertificate - addCertificate(signedSignatureProperties); + addCertificate(signatureInfo, signedSignatureProperties); // ClaimedRole - addXadesRole(signedSignatureProperties); + addXadesRole(signatureInfo, signedSignatureProperties); // XAdES-EPES - addPolicy(signedSignatureProperties); + addPolicy(signatureInfo, signedSignatureProperties); // DataObjectFormat addMimeTypes(signedProperties); // add XAdES ds:Object - objects.add(addXadesObject(document, qualifyingProperties)); + objects.add(addXadesObject(signatureInfo, document, qualifyingProperties)); // add XAdES ds:Reference - references.add(addXadesReference()); + references.add(addXadesReference(signatureInfo)); } - private void addSigningTime(SignedSignaturePropertiesType signedSignatureProperties) { + private void addSigningTime(SignatureInfo signatureInfo, SignedSignaturePropertiesType signedSignatureProperties) { + SignatureConfig signatureConfig = signatureInfo.getSignatureConfig(); Calendar xmlGregorianCalendar = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT); xmlGregorianCalendar.setTime(signatureConfig.getExecutionTime()); xmlGregorianCalendar.clear(Calendar.MILLISECOND); signedSignatureProperties.setSigningTime(xmlGregorianCalendar); } - private void addCertificate(SignedSignaturePropertiesType signedSignatureProperties) { + private void addCertificate(SignatureInfo signatureInfo, SignedSignaturePropertiesType signedSignatureProperties) { + SignatureConfig signatureConfig = signatureInfo.getSignatureConfig(); List<X509Certificate> chain = signatureConfig.getSigningCertificateChain(); if (chain == null || chain.isEmpty()) { throw new RuntimeException("no signing certificate chain available"); @@ -153,7 +161,8 @@ public class XAdESSignatureFacet extends setCertID(certId, signatureConfig, signatureConfig.isXadesIssuerNameNoReverseOrder(), chain.get(0)); } - private void addXadesRole(SignedSignaturePropertiesType signedSignatureProperties) { + private void addXadesRole(SignatureInfo signatureInfo, SignedSignaturePropertiesType signedSignatureProperties) { + SignatureConfig signatureConfig = signatureInfo.getSignatureConfig(); String role = signatureConfig.getXadesRole(); if (role == null || role.isEmpty()) { return; @@ -168,7 +177,8 @@ public class XAdESSignatureFacet extends insertXChild(claimedRole, roleString); } - private void addPolicy(SignedSignaturePropertiesType signedSignatureProperties) { + private void addPolicy(SignatureInfo signatureInfo, SignedSignaturePropertiesType signedSignatureProperties) { + SignatureConfig signatureConfig = signatureInfo.getSignatureConfig(); SignaturePolicyService policyService = signatureConfig.getSignaturePolicyService(); if (policyService == null) { if (signatureConfig.isXadesSignaturePolicyImplied()) { @@ -221,22 +231,23 @@ public class XAdESSignatureFacet extends }); } - private XMLObject addXadesObject(Document document, QualifyingPropertiesType qualifyingProperties) { + private XMLObject addXadesObject(SignatureInfo signatureInfo, Document document, QualifyingPropertiesType qualifyingProperties) { Node qualDocElSrc = qualifyingProperties.getDomNode(); Node qualDocEl = document.importNode(qualDocElSrc, true); List<XMLStructure> xadesObjectContent = Arrays.asList(new DOMStructure(qualDocEl)); - return getSignatureFactory().newXMLObject(xadesObjectContent, null, null, null); + return signatureInfo.getSignatureFactory().newXMLObject(xadesObjectContent, null, null, null); } - private Reference addXadesReference() throws XMLSignatureException { - List<Transform> transforms = singletonList(newTransform(CanonicalizationMethod.INCLUSIVE)); - return newReference("#"+signatureConfig.getXadesSignatureId(), transforms, XADES_TYPE, null, null); + private Reference addXadesReference(SignatureInfo signatureInfo) throws XMLSignatureException { + SignatureConfig signatureConfig = signatureInfo.getSignatureConfig(); + List<Transform> transforms = singletonList(newTransform(signatureInfo, CanonicalizationMethod.INCLUSIVE)); + return newReference(signatureInfo, "#"+signatureConfig.getXadesSignatureId(), transforms, XADES_TYPE, null, null); } /** * Gives back the JAXB DigestAlgAndValue data structure. * - * @param digestAlgAndValue the parent for the new digest element + * @param digestAlgAndValue the parent for the new digest element * @param data the data to be digested * @param digestAlgo the digest algorithm */ @@ -246,7 +257,7 @@ public class XAdESSignatureFacet extends HashAlgorithm digestAlgo) { DigestMethodType digestMethod = digestAlgAndValue.addNewDigestMethod(); digestMethod.setAlgorithm(SignatureConfig.getDigestMethodUri(digestAlgo)); - + MessageDigest messageDigest = CryptoFunctions.getMessageDigest(digestAlgo); byte[] digestValue = messageDigest.digest(data); digestAlgAndValue.setDigestValue(digestValue); @@ -264,7 +275,7 @@ public class XAdESSignatureFacet extends * Make sure the DN is encoded using the same order as present * within the certificate. This is an Office2010 work-around. * Should be reverted back. - * + * * XXX: not correct according to RFC 4514. */ // TODO: check if issuerName is different on getTBSCertificate @@ -283,14 +294,14 @@ public class XAdESSignatureFacet extends throw new RuntimeException("certificate encoding error: " + e.getMessage(), e); } - DigestAlgAndValueType certDigest = certId.addNewCertDigest(); + DigestAlgAndValueType certDigest = certId.addNewCertDigest(); setDigestAlgAndValue(certDigest, encodedCertificate, signatureConfig.getXadesDigestAlgo()); } /** * Adds a mime-type for the given ds:Reference (referred via its @URI). This * information is added via the xades:DataObjectFormat element. - * + * * @param dsReferenceUri * @param mimetype */ Modified: poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java?rev=1874671&r1=1874670&r2=1874671&view=diff ============================================================================== --- poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java (original) +++ poi/trunk/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java Sun Mar 1 22:20:38 2020 @@ -18,9 +18,9 @@ /* ==================================================================== This product contains an ASLv2 licensed version of the OOXML signer package from the eID Applet project - http://code.google.com/p/eid-applet/source/browse/trunk/README.txt + http://code.google.com/p/eid-applet/source/browse/trunk/README.txt Copyright (C) 2008-2014 FedICT. - ================================================================= */ + ================================================================= */ package org.apache.poi.poifs.crypt.dsig.facets; @@ -47,6 +47,8 @@ import java.util.UUID; import javax.xml.crypto.MarshalException; +import org.apache.poi.poifs.crypt.dsig.SignatureConfig; +import org.apache.poi.poifs.crypt.dsig.SignatureInfo; import org.apache.poi.poifs.crypt.dsig.services.RevocationData; import org.apache.poi.util.IOUtils; import org.apache.poi.util.POILogFactory; @@ -73,18 +75,18 @@ import org.w3c.dom.NodeList; /** * XAdES-X-L v1.4.1 signature facet. This signature facet implementation will * upgrade a given XAdES-BES/EPES signature to XAdES-X-L. - * + * * We don't inherit from XAdESSignatureFacet as we also want to be able to use * this facet out of the context of a signature creation. This signature facet * assumes that the signature is already XAdES-BES/EPES compliant. - * + * * This implementation has been tested against an implementation that * participated multiple ETSI XAdES plugtests. - * + * * @author Frank Cornelis * @see XAdESSignatureFacet */ -public class XAdESXLSignatureFacet extends SignatureFacet { +public class XAdESXLSignatureFacet implements SignatureFacet { private static final POILogger LOG = POILogFactory.getLogger(XAdESXLSignatureFacet.class); @@ -99,9 +101,11 @@ public class XAdESXLSignatureFacet exten } @Override - public void postSign(Document document) throws MarshalException { + public void postSign(SignatureInfo signatureInfo, Document document) throws MarshalException { LOG.log(POILogger.DEBUG, "XAdES-X-L post sign phase"); + SignatureConfig signatureConfig = signatureInfo.getSignatureConfig(); + QualifyingPropertiesDocument qualDoc = null; QualifyingPropertiesType qualProps = null; @@ -127,18 +131,18 @@ public class XAdESXLSignatureFacet exten if (unsignedSigProps == null) { unsignedSigProps = unsignedProps.addNewUnsignedSignatureProperties(); } - + // create the XAdES-T time-stamp NodeList nlSigVal = document.getElementsByTagNameNS(XML_DIGSIG_NS, "SignatureValue"); if (nlSigVal.getLength() != 1) { throw new IllegalArgumentException("SignatureValue is not set."); } - + RevocationData tsaRevocationDataXadesT = new RevocationData(); LOG.log(POILogger.DEBUG, "creating XAdES-T time-stamp"); XAdESTimeStampType signatureTimeStamp = createXAdESTimeStamp - (Collections.singletonList(nlSigVal.item(0)), tsaRevocationDataXadesT); + (signatureInfo, Collections.singletonList(nlSigVal.item(0)), tsaRevocationDataXadesT); // marshal the XAdES-T extension unsignedSigProps.addNewSignatureTimeStamp().set(signatureTimeStamp); @@ -158,7 +162,7 @@ public class XAdESXLSignatureFacet exten } // XAdES-C: complete certificate refs - CompleteCertificateRefsType completeCertificateRefs = + CompleteCertificateRefsType completeCertificateRefs = unsignedSigProps.addNewCompleteCertificateRefs(); CertIDListType certIdList = completeCertificateRefs.addNewCertRefs(); @@ -176,7 +180,7 @@ public class XAdESXLSignatureFacet exten } // XAdES-C: complete revocation refs - CompleteRevocationRefsType completeRevocationRefs = + CompleteRevocationRefsType completeRevocationRefs = unsignedSigProps.addNewCompleteRevocationRefs(); RevocationData revocationData = signatureConfig.getRevocationDataService() .getRevocationData(certChain); @@ -212,22 +216,22 @@ public class XAdESXLSignatureFacet exten for (byte[] ocsp : revocationData.getOCSPs()) { try { OCSPRefType ocspRef = ocspRefs.addNewOCSPRef(); - + DigestAlgAndValueType digestAlgAndValue = ocspRef.addNewDigestAlgAndValue(); XAdESSignatureFacet.setDigestAlgAndValue(digestAlgAndValue, ocsp, signatureConfig.getDigestAlgo()); - + OCSPIdentifierType ocspIdentifier = ocspRef.addNewOCSPIdentifier(); - + OCSPResp ocspResp = new OCSPResp(ocsp); - + BasicOCSPResp basicOcspResp = (BasicOCSPResp)ocspResp.getResponseObject(); - + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("Z"), Locale.ROOT); cal.setTime(basicOcspResp.getProducedAt()); ocspIdentifier.setProducedAt(cal); - + ResponderIDType responderId = ocspIdentifier.addNewResponderID(); - + RespID respId = basicOcspResp.getResponderId(); ResponderID ocspResponderId = respId.toASN1Primitive(); DERTaggedObject derTaggedObject = (DERTaggedObject)ocspResponderId.toASN1Primitive(); @@ -247,7 +251,7 @@ public class XAdESXLSignatureFacet exten } // marshal XAdES-C - + // XAdES-X Type 1 timestamp List<Node> timeStampNodesXadesX1 = new ArrayList<>(); timeStampNodesXadesX1.add(nlSigVal.item(0)); @@ -258,7 +262,7 @@ public class XAdESXLSignatureFacet exten RevocationData tsaRevocationDataXadesX1 = new RevocationData(); LOG.log(POILogger.DEBUG, "creating XAdES-X time-stamp"); XAdESTimeStampType timeStampXadesX1 = createXAdESTimeStamp - (timeStampNodesXadesX1, tsaRevocationDataXadesX1); + (signatureInfo, timeStampNodesXadesX1, tsaRevocationDataXadesX1); if (tsaRevocationDataXadesX1.hasRevocationDataEntries()) { ValidationDataType timeStampXadesX1ValidationData = createValidationData(tsaRevocationDataXadesX1); insertXChild(unsignedSigProps, timeStampXadesX1ValidationData); @@ -277,7 +281,7 @@ public class XAdESXLSignatureFacet exten throw new RuntimeException("certificate encoding error: " + e.getMessage(), e); } } - + RevocationValuesType revocationValues = unsignedSigProps.addNewRevocationValues(); createRevocationValues(revocationValues, revocationData); @@ -330,18 +334,21 @@ public class XAdESXLSignatureFacet exten } private XAdESTimeStampType createXAdESTimeStamp( + SignatureInfo signatureInfo, List<Node> nodeList, RevocationData revocationData) { + SignatureConfig signatureConfig = signatureInfo.getSignatureConfig(); byte[] c14nSignatureValueElement = getC14nValue(nodeList, signatureConfig.getXadesCanonicalizationMethod()); - return createXAdESTimeStamp(c14nSignatureValueElement, revocationData); + return createXAdESTimeStamp(signatureInfo, c14nSignatureValueElement, revocationData); } - private XAdESTimeStampType createXAdESTimeStamp(byte[] data, RevocationData revocationData) { + private XAdESTimeStampType createXAdESTimeStamp(SignatureInfo signatureInfo, byte[] data, RevocationData revocationData) { + SignatureConfig signatureConfig = signatureInfo.getSignatureConfig(); // create the time-stamp byte[] timeStampToken; try { - timeStampToken = signatureConfig.getTspService().timeStamp(data, revocationData); + timeStampToken = signatureConfig.getTspService().timeStamp(signatureInfo, data, revocationData); } catch (Exception e) { throw new RuntimeException("error while creating a time-stamp: " + e.getMessage(), e); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
