From 3d81d013a363dac6bfebb59dddaae035d59e86bb Mon Sep 17 00:00:00 2001 From: Andreas Beeker Date: Sun, 24 Aug 2014 23:06:05 +0000 Subject: [PATCH] removed HorribleProxy added current version of BouncyCastle and xmlsec (using xmlsec instead of jdk internal classes, because of interoperabiltiy with e.g. IBM JDK) heaps of changes because of above git-svn-id: https://svn.apache.org/repos/asf/poi/branches/xml_signature@1620230 13f79535-47bb-0310-9956-ffa450edef68 --- .../dsig/facets/EnvelopedSignatureFacet.java | 12 +- .../dsig/facets/KeyInfoSignatureFacet.java | 78 +++--- .../dsig/facets/OOXMLSignatureFacet.java | 92 ++++--- .../dsig/facets/Office2010SignatureFacet.java | 34 +-- .../crypt/dsig/facets/SignatureFacet.java | 16 +- .../dsig/facets/XAdESSignatureFacet.java | 32 +-- .../dsig/facets/XAdESXLSignatureFacet.java | 118 +++++---- .../RelationshipTransformService.java | 6 +- .../crypt/dsig/services/RevocationData.java | 6 +- .../crypt/dsig/services/SignatureService.java | 20 +- .../dsig/services/TSPTimeStampService.java | 152 ++++++------ .../dsig/services/XmlSignatureService.java | 229 +++++++----------- .../poi/poifs/crypt/dsig/spi/Constants.java | 30 --- 13 files changed, 366 insertions(+), 459 deletions(-) delete mode 100644 src/ooxml/java/org/apache/poi/poifs/crypt/dsig/spi/Constants.java diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java index 4f4f9af7ad..6360d4a7e0 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java @@ -3,7 +3,7 @@ package org.apache.poi.poifs.crypt.dsig.facets; import java.security.InvalidAlgorithmParameterException; import java.security.NoSuchAlgorithmException; import java.security.cert.X509Certificate; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -16,7 +16,7 @@ import javax.xml.crypto.dsig.XMLSignatureFactory; import javax.xml.crypto.dsig.spec.TransformParameterSpec; import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.w3.x2000.x09.xmldsig.SignatureType; +import org.w3c.dom.Document; /** * Signature Facet implementation to create enveloped signatures. @@ -47,13 +47,13 @@ public class EnvelopedSignatureFacet implements SignatureFacet { } @Override - public void postSign(SignatureType signatureElement - , List signingCertificateChain) { + public void postSign(Document document, List signingCertificateChain) { // empty } @Override - public void preSign(XMLSignatureFactory signatureFactory, + public void preSign(Document document, + XMLSignatureFactory signatureFactory, String signatureId, List signingCertificateChain, List references, List objects) @@ -61,7 +61,7 @@ public class EnvelopedSignatureFacet implements SignatureFacet { DigestMethod digestMethod = signatureFactory.newDigestMethod( this.hashAlgo.xmlSignUri, null); - List transforms = new LinkedList(); + List transforms = new ArrayList(); Transform envelopedTransform = signatureFactory .newTransform(CanonicalizationMethod.ENVELOPED, (TransformParameterSpec) null); diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java index 4cbcdcc54b..3768f58f93 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java @@ -24,19 +24,21 @@ package org.apache.poi.poifs.crypt.dsig.facets; +import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlDSigNS; + import java.security.InvalidAlgorithmParameterException; import java.security.Key; import java.security.KeyException; import java.security.NoSuchAlgorithmException; -import java.security.Provider; import java.security.cert.X509Certificate; +import java.util.ArrayList; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.xml.crypto.MarshalException; import javax.xml.crypto.dom.DOMCryptoContext; +import javax.xml.crypto.dom.DOMStructure; import javax.xml.crypto.dsig.Reference; import javax.xml.crypto.dsig.XMLObject; import javax.xml.crypto.dsig.XMLSignatureFactory; @@ -46,13 +48,14 @@ import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; import javax.xml.crypto.dsig.keyinfo.KeyValue; import javax.xml.crypto.dsig.keyinfo.X509Data; -import org.apache.poi.poifs.crypt.dsig.HorribleProxy; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DOMKeyInfoIf; +import org.apache.jcp.xml.dsig.internal.dom.DOMKeyInfo; +import org.apache.poi.poifs.crypt.dsig.SignatureInfo; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; -import org.w3.x2000.x09.xmldsig.ObjectType; -import org.w3.x2000.x09.xmldsig.SignatureType; +import org.w3c.dom.Document; +import org.w3c.dom.Element; import org.w3c.dom.Node; +import org.w3c.dom.NodeList; /** * Signature Facet implementation that adds ds:KeyInfo to the XML signature. @@ -84,34 +87,27 @@ public class KeyInfoSignatureFacet implements SignatureFacet { this.includeKeyValue = includeKeyValue; } - public void postSign(SignatureType signatureElement, - List signingCertificateChain) { + @Override + public void postSign(Document document, List signingCertificateChain) + throws MarshalException { LOG.log(POILogger.DEBUG, "postSign"); - List objList = signatureElement.getObjectList(); + NodeList nl = document.getElementsByTagNameNS(XmlDSigNS, "Object"); /* * Make sure we insert right after the ds:SignatureValue element, just * before the first ds:Object element. */ - Node nextSibling = (objList.isEmpty()) ? null : objList.get(0).getDomNode(); + Node nextSibling = (nl.getLength() == 0) ? null : nl.item(0); /* * Construct the ds:KeyInfo element using JSR 105. */ - String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI"); - Provider xmlDSigProv; - try { - xmlDSigProv = (Provider) Class.forName(providerName).newInstance(); - } catch (Exception e) { - throw new RuntimeException("JRE doesn't support default xml signature provider - set jsr105Provider system property!", e); - } - - KeyInfoFactory keyInfoFactory = KeyInfoFactory.getInstance("DOM", xmlDSigProv); - List x509DataObjects = new LinkedList(); + KeyInfoFactory keyInfoFactory = SignatureInfo.getKeyInfoFactory(); + List x509DataObjects = new ArrayList(); X509Certificate signingCertificate = signingCertificateChain.get(0); - List keyInfoContent = new LinkedList(); + List keyInfoContent = new ArrayList(); if (this.includeKeyValue) { KeyValue keyValue; @@ -130,24 +126,17 @@ public class KeyInfoSignatureFacet implements SignatureFacet { } if (this.includeEntireCertificateChain) { - for (X509Certificate certificate : signingCertificateChain) { - x509DataObjects.add(certificate); - } + x509DataObjects.addAll(signingCertificateChain); } else { x509DataObjects.add(signingCertificate); } - if (false == x509DataObjects.isEmpty()) { + if (!x509DataObjects.isEmpty()) { X509Data x509Data = keyInfoFactory.newX509Data(x509DataObjects); keyInfoContent.add(x509Data); } KeyInfo keyInfo = keyInfoFactory.newKeyInfo(keyInfoContent); - DOMKeyInfoIf domKeyInfo; - try { - domKeyInfo = HorribleProxy.newProxy(DOMKeyInfoIf.class, keyInfo); - } catch (Exception e) { - throw new RuntimeException("DOMKeyInfo instance error: " + e.getMessage(), e); - } + DOMKeyInfo domKeyInfo = (DOMKeyInfo)keyInfo; Key key = new Key() { private static final long serialVersionUID = 1L; @@ -165,18 +154,27 @@ public class KeyInfoSignatureFacet implements SignatureFacet { } }; - DOMSignContext domSignContext = new DOMSignContext(key, signatureElement.getDomNode()); + Element n = document.getDocumentElement(); + DOMSignContext domSignContext = new DOMSignContext(key, n, nextSibling); DOMCryptoContext domCryptoContext = domSignContext; - String signatureNamespacePrefix = "xd"; - try { - domKeyInfo.marshal(signatureElement.getDomNode(), nextSibling, - signatureNamespacePrefix, domCryptoContext); - } catch (MarshalException e) { - throw new RuntimeException("marshall error: " + e.getMessage(), e); + domCryptoContext.putNamespacePrefix(XmlDSigNS, "xd"); + DOMStructure domStructure = new DOMStructure(n); + // how to set nextSibling??? - marshal is ignoring nextSibling in DOMSignContext + domKeyInfo.marshal(domStructure, domCryptoContext); + + // move keyinfo into the right place + if (nextSibling != null) { + NodeList kiNl = document.getElementsByTagNameNS(XmlDSigNS, "KeyInfo"); + if (kiNl.getLength() != 1) { + throw new RuntimeException("KeyInfo wasn't set"); + } + nextSibling.getParentNode().insertBefore(kiNl.item(0), nextSibling); } } - public void preSign(XMLSignatureFactory signatureFactory, + @Override + public void preSign(Document document, + XMLSignatureFactory signatureFactory, String signatureId, List signingCertificateChain, List references, @@ -187,7 +185,7 @@ public class KeyInfoSignatureFacet implements SignatureFacet { public Map getNamespacePrefixMapping() { Map map = new HashMap(); - // map.put("xd", "http://www.w3.org/2000/09/xmldsig#"); + // map.put("xd", XmlDSigNS); return map; } diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java index cae3e72d0d..751328f3d0 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java @@ -24,6 +24,8 @@ package org.apache.poi.poifs.crypt.dsig.facets; +import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlDSigNS; +import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlNS; import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.setPrefix; import java.io.IOException; @@ -38,7 +40,6 @@ import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @@ -71,15 +72,13 @@ import org.apache.poi.poifs.crypt.HashAlgorithm; import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService; import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService.RelationshipTransformParameterSpec; import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService; -import org.apache.poi.poifs.crypt.dsig.spi.Constants; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.xmlbeans.XmlException; import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.CTSignatureTime; import org.openxmlformats.schemas.xpackage.x2006.digitalSignature.SignatureTimeDocument; -import org.w3.x2000.x09.xmldsig.SignatureType; +import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.w3c.dom.Node; import com.microsoft.schemas.office.x2006.digsig.CTSignatureInfoV1; import com.microsoft.schemas.office.x2006.digsig.SignatureInfoV1Document; @@ -112,50 +111,43 @@ public class OOXMLSignatureFacet implements SignatureFacet { this.hashAlgo = (hashAlgo == null ? HashAlgorithm.sha1 : hashAlgo); } - public void preSign(XMLSignatureFactory signatureFactory, + @Override + public void preSign(Document document, + XMLSignatureFactory signatureFactory, String signatureId, List signingCertificateChain, List references, List objects) - throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { + throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException { LOG.log(POILogger.DEBUG, "pre sign"); - addManifestObject(signatureFactory, signatureId, references, objects); - addSignatureInfo(signatureFactory, signatureId, references, objects); + addManifestObject(document, signatureFactory, signatureId, references, objects); + addSignatureInfo(document, signatureFactory, signatureId, references, objects); } - private void addManifestObject(XMLSignatureFactory signatureFactory, + private void addManifestObject(Document document, + XMLSignatureFactory signatureFactory, String signatureId, List references, List objects) throws NoSuchAlgorithmException, - InvalidAlgorithmParameterException { - Manifest manifest = constructManifest(signatureFactory); + InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException { + + List manifestReferences = new ArrayList(); + addManifestReferences(signatureFactory, manifestReferences); + Manifest manifest = signatureFactory.newManifest(manifestReferences); + String objectId = "idPackageObject"; // really has to be this value. - List objectContent = new LinkedList(); + List objectContent = new ArrayList(); objectContent.add(manifest); - addSignatureTime(signatureFactory, signatureId, objectContent); + addSignatureTime(document, signatureFactory, signatureId, objectContent); - objects.add(signatureFactory.newXMLObject(objectContent, objectId, - null, null)); + XMLObject xo = signatureFactory.newXMLObject(objectContent, objectId, null, null); + objects.add(xo); DigestMethod digestMethod = signatureFactory.newDigestMethod(this.hashAlgo.xmlSignUri, null); - Reference reference = signatureFactory.newReference("#" + objectId, - digestMethod, null, "http://www.w3.org/2000/09/xmldsig#Object", - null); + Reference reference = signatureFactory.newReference + ("#" + objectId, digestMethod, null, XmlDSigNS+"Object", null); references.add(reference); } - private Manifest constructManifest(XMLSignatureFactory signatureFactory) - throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { - List manifestReferences = new ArrayList(); - - try { - addManifestReferences(signatureFactory, manifestReferences); - } catch (Exception e) { - throw new RuntimeException("error: " + e.getMessage(), e); - } - - return signatureFactory.newManifest(manifestReferences); - } - private void addManifestReferences(XMLSignatureFactory signatureFactory, List manifestReferences) throws IOException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, URISyntaxException, XmlException { @@ -223,7 +215,7 @@ public class OOXMLSignatureFacet implements SignatureFacet { } if (parameterSpec.hasSourceIds()) { - List transforms = new LinkedList(); + List transforms = new ArrayList(); transforms.add(signatureFactory.newTransform( RelationshipTransformService.TRANSFORM_URI, parameterSpec)); @@ -239,7 +231,8 @@ public class OOXMLSignatureFacet implements SignatureFacet { } - private void addSignatureTime(XMLSignatureFactory signatureFactory, + private void addSignatureTime(Document document, + XMLSignatureFactory signatureFactory, String signatureId, List objectContent) { /* @@ -256,15 +249,15 @@ public class OOXMLSignatureFacet implements SignatureFacet { ctTime.setValue(nowStr); // TODO: find better method to have xmlbeans + export the prefix - Node n = ctTime.getDomNode(); - setPrefix(ctTime, PackageNamespaces.DIGITAL_SIGNATURE, "mdssi"); + Element n = (Element)document.importNode(ctTime.getDomNode(),true); + setPrefix(n, PackageNamespaces.DIGITAL_SIGNATURE, "mdssi"); - List signatureTimeContent = new LinkedList(); + List signatureTimeContent = new ArrayList(); signatureTimeContent.add(new DOMStructure(n)); SignatureProperty signatureTimeSignatureProperty = signatureFactory .newSignatureProperty(signatureTimeContent, "#" + signatureId, "idSignatureTime"); - List signaturePropertyContent = new LinkedList(); + List signaturePropertyContent = new ArrayList(); signaturePropertyContent.add(signatureTimeSignatureProperty); SignatureProperties signatureProperties = signatureFactory .newSignatureProperties(signaturePropertyContent, @@ -272,43 +265,42 @@ public class OOXMLSignatureFacet implements SignatureFacet { objectContent.add(signatureProperties); } - private void addSignatureInfo(XMLSignatureFactory signatureFactory, + private void addSignatureInfo(Document document, + XMLSignatureFactory signatureFactory, String signatureId, List references, List objects) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { - List objectContent = new LinkedList(); + List objectContent = new ArrayList(); SignatureInfoV1Document sigV1 = SignatureInfoV1Document.Factory.newInstance(); CTSignatureInfoV1 ctSigV1 = sigV1.addNewSignatureInfoV1(); ctSigV1.setManifestHashAlgorithm(hashAlgo.xmlSignUri); - Node n = ctSigV1.getDomNode(); - ((Element)n).setAttributeNS(Constants.NamespaceSpecNS, "xmlns", "http://schemas.microsoft.com/office/2006/digsig"); + Element n = (Element)document.importNode(ctSigV1.getDomNode(), true); + n.setAttributeNS(XmlNS, "xmlns", "http://schemas.microsoft.com/office/2006/digsig"); - List signatureInfoContent = new LinkedList(); + List signatureInfoContent = new ArrayList(); signatureInfoContent.add(new DOMStructure(n)); SignatureProperty signatureInfoSignatureProperty = signatureFactory .newSignatureProperty(signatureInfoContent, "#" + signatureId, "idOfficeV1Details"); - List signaturePropertyContent = new LinkedList(); + List signaturePropertyContent = new ArrayList(); signaturePropertyContent.add(signatureInfoSignatureProperty); SignatureProperties signatureProperties = signatureFactory .newSignatureProperties(signaturePropertyContent, null); objectContent.add(signatureProperties); String objectId = "idOfficeObject"; - objects.add(signatureFactory.newXMLObject(objectContent, objectId, - null, null)); + objects.add(signatureFactory.newXMLObject(objectContent, objectId, null, null)); DigestMethod digestMethod = signatureFactory.newDigestMethod(this.hashAlgo.xmlSignUri, null); - Reference reference = signatureFactory.newReference("#" + objectId, - digestMethod, null, "http://www.w3.org/2000/09/xmldsig#Object", - null); + Reference reference = signatureFactory.newReference + ("#" + objectId, digestMethod, null, XmlDSigNS+"Object", null); references.add(reference); } - public void postSign(SignatureType signatureElement, - List signingCertificateChain) { + @Override + public void postSign(Document document, List signingCertificateChain) { // empty } diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java index a5527eeb18..420f575bd5 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java @@ -34,11 +34,13 @@ import javax.xml.crypto.dsig.Reference; import javax.xml.crypto.dsig.XMLObject; import javax.xml.crypto.dsig.XMLSignatureFactory; -import org.apache.xmlbeans.XmlObject; +import org.apache.xmlbeans.XmlException; import org.etsi.uri.x01903.v13.QualifyingPropertiesType; import org.etsi.uri.x01903.v13.UnsignedPropertiesType; import org.etsi.uri.x01903.v13.UnsignedSignaturePropertiesType; -import org.w3.x2000.x09.xmldsig.SignatureType; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; /** * Work-around for Office2010 to accept the XAdES-BES/EPES signature. @@ -51,7 +53,9 @@ import org.w3.x2000.x09.xmldsig.SignatureType; */ public class Office2010SignatureFacet implements SignatureFacet { - public void preSign(XMLSignatureFactory signatureFactory, + @Override + public void preSign(Document document, + XMLSignatureFactory signatureFactory, String signatureId, List signingCertificateChain, List references, @@ -59,23 +63,18 @@ public class Office2010SignatureFacet implements SignatureFacet { ) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { } - public void postSign(SignatureType signatureElement, List signingCertificateChain) { - QualifyingPropertiesType qualProps = null; - + @Override + public void postSign(Document document, List signingCertificateChain) + throws XmlException { // check for XAdES-BES - String qualPropXQuery = - "declare namespace xades='http://uri.etsi.org/01903/v1.3.2#'; " - + "declare namespace ds='http://www.w3.org/2000/09/xmldsig#'; " - + "$this/ds:Object/xades:QualifyingProperties"; - XmlObject xoList[] = signatureElement.selectPath(qualPropXQuery); - if (xoList.length == 1) { - qualProps = (QualifyingPropertiesType)xoList[0]; - } - - if (qualProps == null) { + NodeList nl = document.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "QualifyingProperties"); + if (nl.getLength() != 1) { throw new IllegalArgumentException("no XAdES-BES extension present"); } + QualifyingPropertiesType qualProps = + QualifyingPropertiesType.Factory.parse(nl.item(0)); + // create basic XML container structure UnsignedPropertiesType unsignedProps = qualProps.getUnsignedProperties(); if (unsignedProps == null) { @@ -85,6 +84,9 @@ public class Office2010SignatureFacet implements SignatureFacet { if (unsignedSigProps == null) { unsignedSigProps = unsignedProps.addNewUnsignedSignatureProperties(); } + + Node n = document.importNode(qualProps.getDomNode().getFirstChild(), true); + nl.item(0).getParentNode().replaceChild(n, nl.item(0)); } public Map getNamespacePrefixMapping() { diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java index 70f7d911a6..eafa3cd461 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java @@ -24,17 +24,21 @@ package org.apache.poi.poifs.crypt.dsig.facets; +import java.io.IOException; +import java.net.URISyntaxException; import java.security.InvalidAlgorithmParameterException; import java.security.NoSuchAlgorithmException; import java.security.cert.X509Certificate; import java.util.List; import java.util.Map; +import javax.xml.crypto.MarshalException; import javax.xml.crypto.dsig.Reference; import javax.xml.crypto.dsig.XMLObject; import javax.xml.crypto.dsig.XMLSignatureFactory; -import org.w3.x2000.x09.xmldsig.SignatureType; +import org.apache.xmlbeans.XmlException; +import org.w3c.dom.Document; /** * JSR105 Signature Facet interface. @@ -60,12 +64,13 @@ public interface SignatureFacet { * @throws NoSuchAlgorithmException */ void preSign( - XMLSignatureFactory signatureFactory + Document document + , XMLSignatureFactory signatureFactory , String signatureId , List signingCertificateChain , List references , List objects - ) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException; + ) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException; /** * This method is being invoked by the XML signature service engine during @@ -76,8 +81,9 @@ public interface SignatureFacet { * @param signingCertificateChain */ void postSign( - SignatureType signatureElement - , List signingCertificateChain); + Document document + , List signingCertificateChain + ) throws MarshalException, XmlException; Map getNamespacePrefixMapping(); } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java index 9a197aa6ee..a85ed33cb8 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java @@ -24,6 +24,7 @@ package org.apache.poi.poifs.crypt.dsig.facets; +import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlNS; import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.setPrefix; import java.security.InvalidAlgorithmParameterException; @@ -31,10 +32,10 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; +import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TimeZone; @@ -52,7 +53,7 @@ import javax.xml.crypto.dsig.spec.TransformParameterSpec; import org.apache.poi.poifs.crypt.CryptoFunctions; import org.apache.poi.poifs.crypt.HashAlgorithm; import org.apache.poi.poifs.crypt.dsig.SignatureInfo; -import org.apache.poi.poifs.crypt.dsig.spi.Constants; +import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.xmlbeans.XmlString; @@ -74,8 +75,8 @@ import org.etsi.uri.x01903.v13.SignedPropertiesType; import org.etsi.uri.x01903.v13.SignedSignaturePropertiesType; import org.etsi.uri.x01903.v13.SignerRoleType; import org.w3.x2000.x09.xmldsig.DigestMethodType; -import org.w3.x2000.x09.xmldsig.SignatureType; import org.w3.x2000.x09.xmldsig.X509IssuerSerialType; +import org.w3c.dom.Document; import org.w3c.dom.Element; /** @@ -133,12 +134,14 @@ public class XAdESSignatureFacet implements SignatureFacet { this.dataObjectFormatMimeTypes = new HashMap(); } - public void postSign(SignatureType signatureElement, - List signingCertificateChain) { + @Override + public void postSign(Document document, List signingCertificateChain) { LOG.log(POILogger.DEBUG, "postSign"); } - public void preSign(XMLSignatureFactory signatureFactory, + @Override + public void preSign(Document document, + XMLSignatureFactory signatureFactory, String signatureId, List signingCertificateChain, List references, List objects) @@ -152,10 +155,8 @@ public class XAdESSignatureFacet implements SignatureFacet { // SignedProperties SignedPropertiesType signedProperties = qualifyingProperties.addNewSignedProperties(); - String signedPropertiesId; - if (null != this.idSignedProperties) { - signedPropertiesId = this.idSignedProperties; - } else { + String signedPropertiesId = this.idSignedProperties; + if (this.idSignedProperties == null) { signedPropertiesId = signatureId + "-xades"; } signedProperties.setId(signedPropertiesId); @@ -243,17 +244,18 @@ public class XAdESSignatureFacet implements SignatureFacet { // ((Element)qualifyingProperties.getSignedProperties().getDomNode()).setIdAttribute("Id", true); // add XAdES ds:Object - List xadesObjectContent = new LinkedList(); - Element qualDocEl = (Element)qualifyingProperties.getDomNode(); - qualDocEl.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:xd", "http://uri.etsi.org/01903/v1.3.2#"); - setPrefix(qualifyingProperties, "http://uri.etsi.org/01903/v1.3.2#", "xd"); + List xadesObjectContent = new ArrayList(); + Element qualDocEl = (Element)document.importNode(qualifyingProperties.getDomNode(), true); + XmlSignatureService.registerIdAttribute(qualDocEl.getElementsByTagName("SignedProperties")); + qualDocEl.setAttributeNS(XmlNS, "xmlns:xd", "http://uri.etsi.org/01903/v1.3.2#"); + setPrefix(qualDocEl, "http://uri.etsi.org/01903/v1.3.2#", "xd"); xadesObjectContent.add(new DOMStructure(qualDocEl)); XMLObject xadesObject = signatureFactory.newXMLObject(xadesObjectContent, null, null, null); objects.add(xadesObject); // add XAdES ds:Reference DigestMethod digestMethod = signatureFactory.newDigestMethod(hashAlgo.xmlSignUri, null); - List transforms = new LinkedList(); + List transforms = new ArrayList(); Transform exclusiveTransform = signatureFactory .newTransform(CanonicalizationMethod.INCLUSIVE, (TransformParameterSpec) null); diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java index 2d7946e777..9d1cf3a064 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java @@ -24,7 +24,7 @@ package org.apache.poi.poifs.crypt.dsig.facets; -import static org.apache.poi.poifs.crypt.dsig.HorribleProxy.newProxy; +import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlDSigNS; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -37,9 +37,9 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509CRL; import java.security.cert.X509Certificate; +import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.UUID; @@ -50,26 +50,24 @@ import javax.xml.crypto.dsig.XMLObject; import javax.xml.crypto.dsig.XMLSignatureFactory; import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1InputStreamIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1IntegerIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1OctetStringIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.BasicOCSPRespIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.CanonicalizerIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DERTaggedObjectIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.InitIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.OCSPRespIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.RespIDIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ResponderIDIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.X509ExtensionsIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.X509NameIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxy; import org.apache.poi.poifs.crypt.dsig.SignatureInfo; import org.apache.poi.poifs.crypt.dsig.services.RevocationData; import org.apache.poi.poifs.crypt.dsig.services.RevocationDataService; import org.apache.poi.poifs.crypt.dsig.services.TimeStampService; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; -import org.apache.xmlbeans.XmlObject; +import org.apache.xml.security.c14n.Canonicalizer; +import org.apache.xmlbeans.XmlException; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.ocsp.ResponderID; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.asn1.x509.Extension; +import org.bouncycastle.cert.ocsp.BasicOCSPResp; +import org.bouncycastle.cert.ocsp.OCSPResp; +import org.bouncycastle.cert.ocsp.RespID; import org.etsi.uri.x01903.v13.CRLIdentifierType; import org.etsi.uri.x01903.v13.CRLRefType; import org.etsi.uri.x01903.v13.CRLRefsType; @@ -93,9 +91,9 @@ import org.etsi.uri.x01903.v13.UnsignedSignaturePropertiesType; import org.etsi.uri.x01903.v13.XAdESTimeStampType; import org.etsi.uri.x01903.v14.ValidationDataType; import org.w3.x2000.x09.xmldsig.CanonicalizationMethodType; -import org.w3.x2000.x09.xmldsig.SignatureType; -import org.w3.x2000.x09.xmldsig.SignatureValueType; +import org.w3c.dom.Document; import org.w3c.dom.Node; +import org.w3c.dom.NodeList; /** * XAdES-X-L v1.4.1 signature facet. This signature facet implementation will @@ -129,14 +127,6 @@ public class XAdESXLSignatureFacet implements SignatureFacet { private final HashAlgorithm hashAlgo; - static { - try { - HorribleProxy.createProxy(InitIf.class, "init"); - } catch (Exception e) { - throw new RuntimeException("Can't initialize JDK xml signature classes - feature unsupported by the this JDK?!", e); - } - } - /** * Convenience constructor. * @@ -184,21 +174,19 @@ public class XAdESXLSignatureFacet implements SignatureFacet { this.c14nAlgoId = c14nAlgoId; } - public void postSign(SignatureType signatureElement, - List signingCertificateChain) { + @Override + public void postSign(Document document, + List signingCertificateChain + ) throws XmlException { LOG.log(POILogger.DEBUG, "XAdES-X-L post sign phase"); QualifyingPropertiesType qualProps = null; - String qualPropXQuery = - "declare namespace xades='http://uri.etsi.org/01903/v1.3.2#'; " - + "declare namespace ds='http://www.w3.org/2000/09/xmldsig#'; " - + "$this/ds:Object/xades:QualifyingProperties"; - XmlObject xoList[] = signatureElement.selectPath(qualPropXQuery); - if (xoList.length == 1) { - qualProps = (QualifyingPropertiesType)xoList[0]; - } - - if (qualProps == null) { + + // check for XAdES-BES + NodeList qualNl = document.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "QualifyingProperties"); + if (qualNl.getLength() == 1) { + qualProps = QualifyingPropertiesType.Factory.parse(qualNl.item(0)); + } else { throw new IllegalArgumentException("no XAdES-BES extension present"); } @@ -214,14 +202,15 @@ public class XAdESXLSignatureFacet implements SignatureFacet { // create the XAdES-T time-stamp - SignatureValueType svt = signatureElement.getSignatureValue(); + NodeList nlSigVal = document.getElementsByTagNameNS(XmlDSigNS, "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(svt.getDomNode()), - tsaRevocationDataXadesT, this.c14nAlgoId, - this.timeStampService); + Collections.singletonList(nlSigVal.item(0)), tsaRevocationDataXadesT, this.c14nAlgoId, this.timeStampService); // marshal the XAdES-T extension unsignedSigProps.addNewSignatureTimeStamp().set(signatureTimeStamp); @@ -298,9 +287,9 @@ public class XAdESXLSignatureFacet implements SignatureFacet { OCSPIdentifierType ocspIdentifier = ocspRef.addNewOCSPIdentifier(); - OCSPRespIf ocspResp = HorribleProxy.newProxy(OCSPRespIf.class, ocsp); + OCSPResp ocspResp = new OCSPResp(ocsp); - BasicOCSPRespIf basicOcspResp = ocspResp.getResponseObject(); + BasicOCSPResp basicOcspResp = (BasicOCSPResp)ocspResp.getResponseObject(); Calendar cal = Calendar.getInstance(); cal.setTime(basicOcspResp.getProducedAt()); @@ -308,16 +297,16 @@ public class XAdESXLSignatureFacet implements SignatureFacet { ResponderIDType responderId = ocspIdentifier.addNewResponderID(); - RespIDIf respId = basicOcspResp.getResponderId(); - ResponderIDIf ocspResponderId = respId.toASN1Object(); - DERTaggedObjectIf derTaggedObject = ocspResponderId.toASN1Object(); + RespID respId = basicOcspResp.getResponderId(); + ResponderID ocspResponderId = respId.toASN1Object(); + DERTaggedObject derTaggedObject = (DERTaggedObject)ocspResponderId.toASN1Primitive(); if (2 == derTaggedObject.getTagNo()) { - ASN1OctetStringIf keyHashOctetString = derTaggedObject.getObject$String(); + ASN1OctetString keyHashOctetString = (ASN1OctetString)derTaggedObject.getObject(); byte key[] = keyHashOctetString.getOctets(); responderId.setByKey(key); } else { - X509NameIf name = HorribleProxy.createProxy(X509NameIf.class, "getInstance", derTaggedObject.getObject$Object()); - String nameStr = name.toString$delegate(); + X500Name name = X500Name.getInstance(derTaggedObject.getObject()); + String nameStr = name.toString(); responderId.setByName(nameStr); } } catch (Exception e) { @@ -327,13 +316,10 @@ public class XAdESXLSignatureFacet implements SignatureFacet { } // marshal XAdES-C - - // XAdES-X Type 1 timestamp - - - List timeStampNodesXadesX1 = new LinkedList(); - timeStampNodesXadesX1.add(signatureElement.getDomNode()); + // XAdES-X Type 1 timestamp + List timeStampNodesXadesX1 = new ArrayList(); + timeStampNodesXadesX1.add(nlSigVal.item(0)); timeStampNodesXadesX1.add(signatureTimeStamp.getDomNode()); timeStampNodesXadesX1.add(completeCertificateRefs.getDomNode()); timeStampNodesXadesX1.add(completeRevocationRefs.getDomNode()); @@ -365,6 +351,8 @@ public class XAdESXLSignatureFacet implements SignatureFacet { createRevocationValues(revocationValues, revocationData); // marshal XAdES-X-L + Node n = document.importNode(qualProps.getDomNode().getFirstChild(), true); + qualNl.item(0).getParentNode().replaceChild(n, qualNl.item(0)); } public static byte[] getC14nValue(List nodeList, String c14nAlgoId) { @@ -375,7 +363,7 @@ public class XAdESXLSignatureFacet implements SignatureFacet { * Re-initialize the c14n else the namespaces will get cached * and will be missing from the c14n resulting nodes. */ - CanonicalizerIf c14n = HorribleProxy.createProxy(CanonicalizerIf.class, "getInstance", c14nAlgoId); + Canonicalizer c14n = Canonicalizer.getInstance(c14nAlgoId); c14nValue.write(c14n.canonicalizeSubtree(node)); } } catch (RuntimeException e) { @@ -386,7 +374,9 @@ public class XAdESXLSignatureFacet implements SignatureFacet { return c14nValue.toByteArray(); } - public void preSign(XMLSignatureFactory signatureFactory, + @Override + public void preSign(Document document, + XMLSignatureFactory signatureFactory, String signatureId, List signingCertificateChain, List references, List objects) @@ -396,17 +386,17 @@ public class XAdESXLSignatureFacet implements SignatureFacet { private BigInteger getCrlNumber(X509CRL crl) { try { - X509ExtensionsIf x509ext = newProxy(X509ExtensionsIf.class); - byte[] crlNumberExtensionValue = crl.getExtensionValue(x509ext.CRLNumber().getId()); + byte[] crlNumberExtensionValue = crl.getExtensionValue(Extension.cRLNumber.getId()); if (null == crlNumberExtensionValue) { return null; } - ASN1InputStreamIf asn1InputStream = HorribleProxy.newProxy(ASN1InputStreamIf.class, crlNumberExtensionValue); - ASN1OctetStringIf octetString = asn1InputStream.readObject$ASNString(); + @SuppressWarnings("resource") + ASN1InputStream asn1InputStream = new ASN1InputStream(crlNumberExtensionValue); + ASN1OctetString octetString = (ASN1OctetString)asn1InputStream.readObject(); byte[] octets = octetString.getOctets(); - asn1InputStream = HorribleProxy.newProxy(ASN1InputStreamIf.class, octets); - ASN1IntegerIf integer = asn1InputStream.readObject$Integer(); + asn1InputStream = new ASN1InputStream(octets); + ASN1Integer integer = (ASN1Integer)asn1InputStream.readObject(); BigInteger crlNumber = integer.getPositiveValue(); return crlNumber; } catch (Exception e) { diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RelationshipTransformService.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RelationshipTransformService.java index e67356224e..8377fa24d3 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RelationshipTransformService.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RelationshipTransformService.java @@ -33,9 +33,9 @@ import java.security.InvalidAlgorithmParameterException; import java.security.Provider; import java.security.Security; import java.security.spec.AlgorithmParameterSpec; +import java.util.ArrayList; import java.util.Comparator; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import javax.xml.crypto.Data; @@ -85,7 +85,7 @@ public class RelationshipTransformService extends TransformService { * Relationship Transform parameter specification class. */ public static class RelationshipTransformParameterSpec implements TransformParameterSpec { - List sourceIds = new LinkedList(); + List sourceIds = new ArrayList(); public void addRelationshipReference(String relationshipId) { sourceIds.add(relationshipId); } @@ -98,7 +98,7 @@ public class RelationshipTransformService extends TransformService { public RelationshipTransformService() { super(); LOG.log(POILogger.DEBUG, "constructor"); - this.sourceIds = new LinkedList(); + this.sourceIds = new ArrayList(); } /** diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RevocationData.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RevocationData.java index 31595c39e3..5f0089a53c 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RevocationData.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/RevocationData.java @@ -26,7 +26,7 @@ package org.apache.poi.poifs.crypt.dsig.services; import java.security.cert.CRLException; import java.security.cert.X509CRL; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; /** @@ -45,8 +45,8 @@ public class RevocationData { * Default constructor. */ public RevocationData() { - this.crls = new LinkedList(); - this.ocsps = new LinkedList(); + this.crls = new ArrayList(); + this.ocsps = new ArrayList(); } /** diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/SignatureService.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/SignatureService.java index 4057807634..e35c0d0de0 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/SignatureService.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/SignatureService.java @@ -26,16 +26,18 @@ package org.apache.poi.poifs.crypt.dsig.services; import java.io.IOException; import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.util.List; -import org.apache.poi.poifs.crypt.dsig.CertificateSecurityException; -import org.apache.poi.poifs.crypt.dsig.ExpiredCertificateSecurityException; -import org.apache.poi.poifs.crypt.dsig.RevokedCertificateSecurityException; -import org.apache.poi.poifs.crypt.dsig.TrustCertificateSecurityException; +import javax.xml.crypto.MarshalException; +import javax.xml.parsers.ParserConfigurationException; + import org.apache.poi.poifs.crypt.dsig.spi.AddressDTO; import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo; import org.apache.poi.poifs.crypt.dsig.spi.IdentityDTO; +import org.apache.xmlbeans.XmlException; +import org.w3c.dom.Document; /** * Interface for signature service component. @@ -79,7 +81,8 @@ public interface SignatureService { * @return the digest to be signed. * @throws NoSuchAlgorithmException */ - DigestInfo preSign(List digestInfos, + DigestInfo preSign(Document document, List digestInfos, + PrivateKey privateKey, List signingCertificateChain, IdentityDTO identity, AddressDTO address, byte[] photo) throws NoSuchAlgorithmException; @@ -92,10 +95,7 @@ public interface SignatureService { * @param signingCertificateChain * the optional chain of signing certificates. */ - void postSign(byte[] signatureValue, + void postSign(Document document, byte[] signatureValue, List signingCertificateChain) - throws ExpiredCertificateSecurityException, - RevokedCertificateSecurityException, - TrustCertificateSecurityException, CertificateSecurityException, - SecurityException, IOException; + throws IOException, MarshalException, ParserConfigurationException, XmlException; } diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TSPTimeStampService.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TSPTimeStampService.java index 100c0f7f3f..ff4beb41ce 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TSPTimeStampService.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TSPTimeStampService.java @@ -24,10 +24,6 @@ package org.apache.poi.poifs.crypt.dsig.services; -import static org.apache.poi.poifs.crypt.dsig.HorribleProxy.createProxy; -import static org.apache.poi.poifs.crypt.dsig.HorribleProxy.newProxy; - -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.math.BigInteger; @@ -38,39 +34,37 @@ import java.net.URL; import java.nio.charset.Charset; import java.security.MessageDigest; import java.security.SecureRandom; -import java.security.cert.Certificate; import java.security.cert.X509Certificate; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; -import javax.security.auth.x500.X500Principal; import javax.xml.bind.DatatypeConverter; import org.apache.commons.codec.binary.Hex; import org.apache.poi.poifs.crypt.CryptoFunctions; import org.apache.poi.poifs.crypt.HashAlgorithm; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1InputStreamIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.ASN1OctetStringIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.AuthorityKeyIdentifierIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.BcDigestCalculatorProviderIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.BcRSASignerInfoVerifierBuilderIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DEROctetStringIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DefaultDigestAlgorithmIdentifierFinderIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.PKIFailureInfoIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.SignerIdIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.SignerInformationVerifierIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.SubjectKeyIdentifierIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.TimeStampRequestGeneratorIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.TimeStampRequestIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.TimeStampResponseIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.TimeStampTokenIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.X509CertificateHolderIf; import org.apache.poi.util.IOUtils; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; +import org.bouncycastle.asn1.cmp.PKIFailureInfo; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils; +import org.bouncycastle.cms.DefaultCMSSignatureAlgorithmNameGenerator; +import org.bouncycastle.cms.SignerId; +import org.bouncycastle.cms.SignerInformationVerifier; +import org.bouncycastle.cms.bc.BcRSASignerInfoVerifierBuilder; +import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder; +import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder; +import org.bouncycastle.operator.bc.BcDigestCalculatorProvider; +import org.bouncycastle.tsp.TimeStampRequest; +import org.bouncycastle.tsp.TimeStampRequestGenerator; +import org.bouncycastle.tsp.TimeStampResponse; +import org.bouncycastle.tsp.TimeStampToken; /** * A TSP time-stamp service implementation. @@ -108,6 +102,10 @@ public class TSPTimeStampService implements TimeStampService { private String digestAlgoOid; + private String requestContentType = "application/timestamp-query;charset=ISO-8859-1"; + + private String responseContentType = "application/timestamp-reply"; + public TSPTimeStampService(String tspServiceUrl, TimeStampServiceValidator validator) { this(tspServiceUrl, validator, null, null); @@ -234,12 +232,12 @@ public class TSPTimeStampService implements TimeStampService { // generate the TSP request BigInteger nonce = new BigInteger(128, new SecureRandom()); - TimeStampRequestGeneratorIf requestGenerator = newProxy(TimeStampRequestGeneratorIf.class); + TimeStampRequestGenerator requestGenerator = new TimeStampRequestGenerator(); requestGenerator.setCertReq(true); if (null != this.requestPolicy) { requestGenerator.setReqPolicy(this.requestPolicy); } - TimeStampRequestIf request = requestGenerator.generate(this.digestAlgoOid, digest, nonce); + TimeStampRequest request = requestGenerator.generate(this.digestAlgoOid, digest, nonce); byte[] encodedRequest = request.getEncoded(); // create the HTTP POST request @@ -256,8 +254,7 @@ public class TSPTimeStampService implements TimeStampService { huc.setDoOutput(true); // also sets method to POST. huc.setRequestProperty("User-Agent", this.userAgent); - // "application/timestamp-query;charset=ISO-8859-1" - huc.setRequestProperty("Content-Type", "application/timestamp-request"); + huc.setRequestProperty("Content-Type", requestContentType); OutputStream hucOut = huc.getOutputStream(); hucOut.write(encodedRequest); @@ -281,8 +278,7 @@ public class TSPTimeStampService implements TimeStampService { IOUtils.copy(huc.getInputStream(), bos); LOG.log(POILogger.DEBUG, "response content: ", bos.toString()); - // "application/timestamp-reply" - if (!contentType.startsWith("application/timestamp-response")) { + if (!contentType.startsWith(responseContentType)) { throw new RuntimeException("invalid Content-Type: " + contentType); } @@ -291,13 +287,13 @@ public class TSPTimeStampService implements TimeStampService { } // TSP response parsing and validation - TimeStampResponseIf timeStampResponse = newProxy(TimeStampResponseIf.class, bos.toByteArray()); + TimeStampResponse timeStampResponse = new TimeStampResponse(bos.toByteArray()); timeStampResponse.validate(request); if (0 != timeStampResponse.getStatus()) { LOG.log(POILogger.DEBUG, "status: " + timeStampResponse.getStatus()); LOG.log(POILogger.DEBUG, "status string: " + timeStampResponse.getStatusString()); - PKIFailureInfoIf failInfo = timeStampResponse.getFailInfo(); + PKIFailureInfo failInfo = timeStampResponse.getFailInfo(); if (null != failInfo) { LOG.log(POILogger.DEBUG, "fail info int value: " + failInfo.intValue()); if (/*PKIFailureInfo.unacceptedPolicy*/(1 << 8) == failInfo.intValue()) { @@ -307,30 +303,29 @@ public class TSPTimeStampService implements TimeStampService { throw new RuntimeException("timestamp response status != 0: " + timeStampResponse.getStatus()); } - TimeStampTokenIf timeStampToken = timeStampResponse.getTimeStampToken(); - SignerIdIf signerId = timeStampToken.getSID(); + TimeStampToken timeStampToken = timeStampResponse.getTimeStampToken(); + SignerId signerId = timeStampToken.getSID(); BigInteger signerCertSerialNumber = signerId.getSerialNumber(); - X500Principal signerCertIssuer = signerId.getIssuer(); + X500Name signerCertIssuer = signerId.getIssuer(); LOG.log(POILogger.DEBUG, "signer cert serial number: " + signerCertSerialNumber); LOG.log(POILogger.DEBUG, "signer cert issuer: " + signerCertIssuer); // TSP signer certificates retrieval - Collection certificates = timeStampToken.getCertificates().getMatches(null); + Collection certificates = timeStampToken.getCertificates().getMatches(null); + JcaX509ExtensionUtils utils = new JcaX509ExtensionUtils(); - X509Certificate signerCert = null; - Map certificateMap = new HashMap(); - for (Certificate certificate : certificates) { - X509Certificate x509Certificate = (X509Certificate) certificate; - if (signerCertIssuer.equals(x509Certificate - .getIssuerX500Principal()) - && signerCertSerialNumber.equals(x509Certificate - .getSerialNumber())) { - signerCert = x509Certificate; + X509CertificateHolder signerCert = null; + Map certificateMap = new HashMap(); + for (X509CertificateHolder certificate : certificates) { + if (signerCertIssuer.equals(certificate.getIssuer()) + && signerCertSerialNumber.equals(certificate.getSerialNumber())) { + signerCert = certificate; } - String ski = Hex.encodeHexString(getSubjectKeyId(x509Certificate)); - certificateMap.put(ski, x509Certificate); + byte skiBytes[] = utils.createSubjectKeyIdentifier(certificate.getSubjectPublicKeyInfo()).getKeyIdentifier(); + String ski = Hex.encodeHexString(skiBytes); + certificateMap.put(ski, certificate); LOG.log(POILogger.DEBUG, "embedded certificate: " - + x509Certificate.getSubjectX500Principal() + "; SKI=" + + certificate.getSubject() + "; SKI=" + ski); } @@ -339,26 +334,29 @@ public class TSPTimeStampService implements TimeStampService { throw new RuntimeException( "TSP response token has no signer certificate"); } - List tspCertificateChain = new LinkedList(); - X509Certificate certificate = signerCert; + List tspCertificateChain = new ArrayList(); + JcaX509CertificateConverter x509converter = new JcaX509CertificateConverter(); + x509converter.setProvider("BC"); + X509CertificateHolder certificate = signerCert; do { - LOG.log(POILogger.DEBUG, "adding to certificate chain: " - + certificate.getSubjectX500Principal()); - tspCertificateChain.add(certificate); - if (certificate.getSubjectX500Principal().equals( - certificate.getIssuerX500Principal())) { + LOG.log(POILogger.DEBUG, "adding to certificate chain: " + certificate.getSubject()); + tspCertificateChain.add(x509converter.getCertificate(certificate)); + if (certificate.getSubject().equals(certificate.getIssuer())) { break; } - String aki = Hex.encodeHexString(getAuthorityKeyId(certificate)); + byte akiBytes[] = utils.createAuthorityKeyIdentifier(certificate.getSubjectPublicKeyInfo()).getKeyIdentifier(); + String aki = Hex.encodeHexString(akiBytes); certificate = certificateMap.get(aki); } while (null != certificate); // verify TSP signer signature - X509CertificateHolderIf holder = newProxy(X509CertificateHolderIf.class, tspCertificateChain.get(0).getEncoded()); - DefaultDigestAlgorithmIdentifierFinderIf finder = newProxy(DefaultDigestAlgorithmIdentifierFinderIf.class); - BcDigestCalculatorProviderIf calculator = newProxy(BcDigestCalculatorProviderIf.class); - BcRSASignerInfoVerifierBuilderIf verifierBuilder = newProxy(BcRSASignerInfoVerifierBuilderIf.class, finder, calculator); - SignerInformationVerifierIf verifier = verifierBuilder.build(holder); + X509CertificateHolder holder = new X509CertificateHolder(tspCertificateChain.get(0).getEncoded()); + DefaultCMSSignatureAlgorithmNameGenerator nameGen = new DefaultCMSSignatureAlgorithmNameGenerator(); + DefaultSignatureAlgorithmIdentifierFinder sigAlgoFinder = new DefaultSignatureAlgorithmIdentifierFinder(); + DefaultDigestAlgorithmIdentifierFinder hashAlgoFinder = new DefaultDigestAlgorithmIdentifierFinder(); + BcDigestCalculatorProvider calculator = new BcDigestCalculatorProvider(); + BcRSASignerInfoVerifierBuilder verifierBuilder = new BcRSASignerInfoVerifierBuilder(nameGen, sigAlgoFinder, hashAlgoFinder, calculator); + SignerInformationVerifier verifier = verifierBuilder.build(holder); timeStampToken.validate(verifier); @@ -372,29 +370,19 @@ public class TSPTimeStampService implements TimeStampService { return timestamp; } - private byte[] getSubjectKeyId(X509Certificate cert) throws Exception { - // X509Extensions.SubjectKeyIdentifier.getId() - byte[] extvalue = cert.getExtensionValue("2.5.29.14"); - if (extvalue == null) return null; - - ASN1InputStreamIf keyCntStream = newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(extvalue)); - ASN1OctetStringIf cntStr = createProxy(ASN1OctetStringIf.class, "getInstance", keyCntStream.readObject$Object()); - ASN1InputStreamIf keyIdStream = newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(cntStr.getOctets())); - SubjectKeyIdentifierIf keyId = createProxy(SubjectKeyIdentifierIf.class, "getInstance", keyIdStream.readObject$Object()); - - return keyId.getKeyIdentifier(); + /** + * usually the request content type is "application/timestamp-query;charset=ISO-8859-1", + * but some timestamp server use a different content type + */ + public void setRequestContentType(String requestContentType) { + this.requestContentType = requestContentType; } - private byte[] getAuthorityKeyId(X509Certificate cert) throws Exception { - // X509Extensions.AuthorityKeyIdentifier.getId() - byte[] extvalue = cert.getExtensionValue("2.5.29.35"); - if (extvalue == null) return null; - - ASN1InputStreamIf keyCntStream = newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(extvalue)); - DEROctetStringIf cntStr = keyCntStream.readObject$DERString(); - ASN1InputStreamIf keyIdStream = newProxy(ASN1InputStreamIf.class, new ByteArrayInputStream(cntStr.getOctets())); - AuthorityKeyIdentifierIf keyId = newProxy(AuthorityKeyIdentifierIf.class, keyIdStream.readObject$Sequence()); - - return keyId.getKeyIdentifier(); + /** + * usually the response content type is "application/timestamp-reply", + * but some timestamp server use a different content type + */ + public void setResponseContentType(String responseContentType) { + this.responseContentType = responseContentType; } } \ No newline at end of file diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/XmlSignatureService.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/XmlSignatureService.java index 91ed1646b5..51b32a0c17 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/XmlSignatureService.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/XmlSignatureService.java @@ -24,20 +24,25 @@ package org.apache.poi.poifs.crypt.dsig.services; +import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlDSigNS; +import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlNS; + import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.net.MalformedURLException; +import java.net.URISyntaxException; import java.security.InvalidAlgorithmParameterException; -import java.security.Key; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; +import java.security.PrivateKey; import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.HashMap; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.UUID; @@ -45,7 +50,6 @@ import java.util.UUID; import javax.xml.crypto.MarshalException; import javax.xml.crypto.URIDereferencer; import javax.xml.crypto.XMLStructure; -import javax.xml.crypto.dom.DOMCryptoContext; import javax.xml.crypto.dsig.CanonicalizationMethod; import javax.xml.crypto.dsig.DigestMethod; import javax.xml.crypto.dsig.Manifest; @@ -57,11 +61,12 @@ import javax.xml.crypto.dsig.XMLSignContext; import javax.xml.crypto.dsig.XMLSignatureFactory; import javax.xml.crypto.dsig.dom.DOMSignContext; import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactoryConfigurationError; +import org.apache.jcp.xml.dsig.internal.dom.DOMReference; +import org.apache.jcp.xml.dsig.internal.dom.DOMSignedInfo; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackageNamespaces; @@ -74,11 +79,6 @@ import org.apache.poi.openxml4j.opc.PackagingURIHelper; 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.HorribleProxies.DOMReferenceIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DOMSignedInfoIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DOMXMLSignatureIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxies.XMLSignatureIf; -import org.apache.poi.poifs.crypt.dsig.HorribleProxy; import org.apache.poi.poifs.crypt.dsig.OOXMLURIDereferencer; import org.apache.poi.poifs.crypt.dsig.SignatureInfo; import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet; @@ -87,19 +87,22 @@ import org.apache.poi.poifs.crypt.dsig.facets.Office2010SignatureFacet; import org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet; import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet; import org.apache.poi.poifs.crypt.dsig.spi.AddressDTO; -import org.apache.poi.poifs.crypt.dsig.spi.Constants; import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo; import org.apache.poi.poifs.crypt.dsig.spi.IdentityDTO; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; +import org.apache.xml.security.signature.XMLSignature; +import org.apache.xml.security.utils.Base64; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlOptions; import org.w3.x2000.x09.xmldsig.SignatureDocument; -import org.w3.x2000.x09.xmldsig.SignatureType; -import org.w3.x2000.x09.xmldsig.SignatureValueType; import org.w3c.dom.Document; import org.w3c.dom.Element; 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; import org.xml.sax.SAXException; @@ -115,18 +118,18 @@ public class XmlSignatureService implements SignatureService { private String signatureId = "idPackageSignature"; private final HashAlgorithm hashAlgo; private final OPCPackage opcPackage; - private SignatureDocument sigDoc; + // private SignatureDocument sigDoc; private XAdESSignatureFacet xadesSignatureFacet; /** * Main constructor. */ public XmlSignatureService(HashAlgorithm digestAlgo, OPCPackage opcPackage) { - this.signatureFacets = new LinkedList(); + this.signatureFacets = new ArrayList(); this.signatureNamespacePrefix = null; this.hashAlgo = digestAlgo; this.opcPackage = opcPackage; - this.sigDoc = null; + // this.sigDoc = null; } public void initFacets(Date clock) { @@ -228,19 +231,20 @@ public class XmlSignatureService implements SignatureService { * @return */ // protected abstract OutputStream getSignedDocumentOutputStream(); - - public DigestInfo preSign(List digestInfos, + @Override + public DigestInfo preSign(Document document, List digestInfos, + PrivateKey key, List signingCertificateChain, IdentityDTO identity, AddressDTO address, byte[] photo) throws NoSuchAlgorithmException { SignatureInfo.initXmlProvider(); - + LOG.log(POILogger.DEBUG, "preSign"); HashAlgorithm hashAlgo = getSignatureDigestAlgorithm(); byte[] digestValue; try { - digestValue = getXmlSignatureDigestValue(hashAlgo, digestInfos, signingCertificateChain); + digestValue = getXmlSignatureDigestValue(document, hashAlgo, digestInfos, key, signingCertificateChain); } catch (Exception e) { throw new RuntimeException("XML signature error: " + e.getMessage(), e); } @@ -249,78 +253,74 @@ public class XmlSignatureService implements SignatureService { return new DigestInfo(digestValue, hashAlgo, description); } - public void postSign(byte[] signatureValue, List signingCertificateChain) - throws IOException { + @Override + public void postSign(Document document, byte[] signatureValue, List signingCertificateChain) + throws IOException, MarshalException, ParserConfigurationException, XmlException { LOG.log(POILogger.DEBUG, "postSign"); SignatureInfo.initXmlProvider(); - /* - * Retrieve the intermediate XML signature document from the temporary - * data storage. - */ - SignatureType sigType = sigDoc.getSignature(); - /* * Check ds:Signature node. */ - if (!signatureId.equals(sigType.getId())) { + if (!signatureId.equals(document.getDocumentElement().getAttribute("Id"))) { throw new RuntimeException("ds:Signature not found for @Id: " + signatureId); } /* * Insert signature value into the ds:SignatureValue element */ - SignatureValueType sigVal = sigType.getSignatureValue(); - sigVal.setByteArrayValue(signatureValue); + NodeList sigValNl = document.getElementsByTagNameNS(XmlDSigNS, "SignatureValue"); + if (sigValNl.getLength() != 1) { + throw new RuntimeException("preSign has to be called before postSign"); + } + sigValNl.item(0).setTextContent(Base64.encode(signatureValue)); /* * Allow signature facets to inject their own stuff. */ for (SignatureFacet signatureFacet : this.signatureFacets) { - signatureFacet.postSign(sigType, signingCertificateChain); + signatureFacet.postSign(document, signingCertificateChain); } - writeDocument(); + writeDocument(document); } @SuppressWarnings("unchecked") - private byte[] getXmlSignatureDigestValue(HashAlgorithm hashAlgo, + private byte[] getXmlSignatureDigestValue(Document document, HashAlgorithm hashAlgo, List digestInfos, + PrivateKey privateKey, List signingCertificateChain) throws ParserConfigurationException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, MarshalException, javax.xml.crypto.dsig.XMLSignatureException, TransformerFactoryConfigurationError, TransformerException, - IOException, SAXException, NoSuchProviderException, XmlException { - /* - * DOM Document construction. - */ - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware(true); - Document doc = dbf.newDocumentBuilder().newDocument(); - - /* - * Signature context construction. - */ - Key key = new Key() { - private static final long serialVersionUID = 1L; - - public String getAlgorithm() { - return null; - } - - public byte[] getEncoded() { - return null; - } - - public String getFormat() { - return null; + IOException, SAXException, NoSuchProviderException, XmlException, URISyntaxException { + + // 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 ... + final EventTarget et = (EventTarget)document; + EventListener myModificationListener = new EventListener() { + @Override + public void handleEvent(Event e) { + if (e instanceof MutationEvent) { + MutationEvent mutEvt = (MutationEvent)e; + if (mutEvt.getTarget() instanceof Element) { + Element el = (Element)mutEvt.getTarget(); + if ("idPackageObject".equals(el.getAttribute("Id"))) { + et.removeEventListener("DOMSubtreeModified", this, false); + el.setAttributeNS(XmlNS, "xmlns:mdssi", PackageNamespaces.DIGITAL_SIGNATURE); + } + } + } } }; - // As of JDK 7, can't use sigDoc here directly, because the - // setAttributeID will be called and it's not implemented in xmlbeans - XMLSignContext xmlSignContext = new DOMSignContext(key, doc); + et.addEventListener("DOMSubtreeModified", myModificationListener, false); + + /* + * Signature context construction. + */ + XMLSignContext xmlSignContext = new DOMSignContext(privateKey, document); URIDereferencer uriDereferencer = getURIDereferencer(); if (null != uriDereferencer) { xmlSignContext.setURIDereferencer(uriDereferencer); @@ -334,40 +334,34 @@ public class XmlSignatureService implements SignatureService { /* * OOo doesn't like ds namespaces so per default prefixing is off. */ - xmlSignContext.putNamespacePrefix( - javax.xml.crypto.dsig.XMLSignature.XMLNS, - this.signatureNamespacePrefix); + xmlSignContext.putNamespacePrefix(XmlDSigNS, this.signatureNamespacePrefix); } - XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM", "XMLDSig"); + XMLSignatureFactory signatureFactory = SignatureInfo.getSignatureFactory(); /* * Add ds:References that come from signing client local files. */ - List references = new LinkedList(); + List references = new ArrayList(); addDigestInfosAsReferences(digestInfos, signatureFactory, references); /* * Invoke the signature facets. */ - String localSignatureId; - if (null == this.signatureId) { + String localSignatureId = this.signatureId; + if (localSignatureId == null) { localSignatureId = "xmldsig-" + UUID.randomUUID().toString(); - } else { - localSignatureId = this.signatureId; } - List objects = new LinkedList(); + List objects = new ArrayList(); for (SignatureFacet signatureFacet : this.signatureFacets) { - LOG.log(POILogger.DEBUG, "invoking signature facet: " - + signatureFacet.getClass().getSimpleName()); - signatureFacet.preSign(signatureFactory, localSignatureId, signingCertificateChain, references, objects); + LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName()); + signatureFacet.preSign(document, signatureFactory, localSignatureId, signingCertificateChain, references, objects); } /* * ds:SignedInfo */ - SignatureMethod signatureMethod = signatureFactory.newSignatureMethod( - getSignatureMethod(hashAlgo), null); + SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(getSignatureMethod(hashAlgo), null); CanonicalizationMethod canonicalizationMethod = signatureFactory .newCanonicalizationMethod(getCanonicalizationMethod(), (C14NMethodParameterSpec) null); @@ -385,20 +379,12 @@ public class XmlSignatureService implements SignatureService { /* * ds:Signature Marshalling. */ - DOMXMLSignatureIf domXmlSignature; - try { - domXmlSignature = HorribleProxy.newProxy(DOMXMLSignatureIf.class, xmlSignature); - } catch (Exception e) { - throw new RuntimeException("DomXmlSignature instance error: " + e.getMessage(), e); - } - - domXmlSignature.marshal(doc, this.signatureNamespacePrefix, (DOMCryptoContext) xmlSignContext); + xmlSignContext.setDefaultNamespacePrefix(this.signatureNamespacePrefix); + // xmlSignContext.putNamespacePrefix(PackageNamespaces.DIGITAL_SIGNATURE, "mdssi"); + xmlSignature.sign(xmlSignContext); - registerIds(doc); - Element el = doc.getElementById("idPackageObject"); - if (el != null) { - el.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:mdssi", PackageNamespaces.DIGITAL_SIGNATURE); - } + registerIds(document); + // document.getElementById("idPackageObject").setAttributeNS(XmlNS, "xmlns:mdssi", PackageNamespaces.DIGITAL_SIGNATURE); /* @@ -415,12 +401,7 @@ public class XmlSignatureService implements SignatureService { for (Reference manifestReference : manifestReferences) { if (manifestReference.getDigestValue() != null) continue; - DOMReferenceIf manifestDOMReference; - try { - manifestDOMReference = HorribleProxy.newProxy(DOMReferenceIf.class, manifestReference); - } catch (Exception e) { - throw new RuntimeException("DOMReference instance error: " + e.getMessage(), e); - } + DOMReference manifestDOMReference = (DOMReference)manifestReference; manifestDOMReference.digest(xmlSignContext); } } @@ -431,12 +412,7 @@ public class XmlSignatureService implements SignatureService { */ List signedInfoReferences = signedInfo.getReferences(); for (Reference signedInfoReference : signedInfoReferences) { - DOMReferenceIf domReference; - try { - domReference = HorribleProxy.newProxy(DOMReferenceIf.class, signedInfoReference); - } catch (Exception e) { - throw new RuntimeException("DOMReference instance error: " + e.getMessage(), e); - } + DOMReference domReference = (DOMReference)signedInfoReference; // ds:Reference with external digest value if (domReference.getDigestValue() != null) continue; @@ -447,20 +423,11 @@ public class XmlSignatureService implements SignatureService { /* * Calculation of XML signature digest value. */ - DOMSignedInfoIf domSignedInfo; - try { - domSignedInfo = HorribleProxy.newProxy(DOMSignedInfoIf.class, signedInfo); - } catch (Exception e) { - throw new RuntimeException("DOMSignedInfo instance error: " + e.getMessage(), e); - } - + DOMSignedInfo domSignedInfo = (DOMSignedInfo)signedInfo; ByteArrayOutputStream dataStream = new ByteArrayOutputStream(); domSignedInfo.canonicalize(xmlSignContext, dataStream); byte[] octets = dataStream.toByteArray(); - sigDoc = SignatureDocument.Factory.parse(doc.getDocumentElement()); - - /* * TODO: we could be using DigestOutputStream here to optimize memory * usage. @@ -478,13 +445,13 @@ public class XmlSignatureService implements SignatureService { * @param doc */ public void registerIds(Document doc) { - NodeList nl = doc.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Object"); + NodeList nl = doc.getElementsByTagNameNS(XmlDSigNS, "Object"); registerIdAttribute(nl); nl = doc.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "SignedProperties"); registerIdAttribute(nl); } - protected void registerIdAttribute(NodeList nl) { + public static void registerIdAttribute(NodeList nl) { for (int i=0; i digestInfos, - XMLSignatureFactory signatureFactory, List references) - throws NoSuchAlgorithmException, - InvalidAlgorithmParameterException, MalformedURLException { - if (digestInfos == null) return; - for (DigestInfo digestInfo : digestInfos) { + private void addDigestInfosAsReferences(List digestInfos, XMLSignatureFactory signatureFactory, List references) + throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, MalformedURLException { + for (DigestInfo digestInfo : safe(digestInfos)) { byte[] documentDigestValue = digestInfo.digestValue; DigestMethod digestMethod = signatureFactory.newDigestMethod( @@ -517,19 +481,12 @@ public class XmlSignatureService implements SignatureService { throw new RuntimeException("digest algo is null"); } - XMLSignatureIf XmlSignature; - try { - XmlSignature = HorribleProxy.newProxy(XMLSignatureIf.class); - } catch (Exception e) { - throw new RuntimeException("JDK doesn't support XmlSignature", e); - } - switch (hashAlgo) { - case sha1: return XmlSignature.ALGO_ID_SIGNATURE_RSA_SHA1(); - case sha256: return XmlSignature.ALGO_ID_SIGNATURE_RSA_SHA256(); - case sha384: return XmlSignature.ALGO_ID_SIGNATURE_RSA_SHA384(); - case sha512: return XmlSignature.ALGO_ID_SIGNATURE_RSA_SHA512(); - case ripemd160: return XmlSignature.ALGO_ID_MAC_HMAC_RIPEMD160(); + case sha1: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1; + case sha256: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256; + case sha384: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384; + case sha512: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512; + case ripemd160: return XMLSignature.ALGO_ID_MAC_HMAC_RIPEMD160; default: break; } @@ -549,15 +506,11 @@ public class XmlSignatureService implements SignatureService { return null; } - public SignatureDocument getSignatureDocument() { - return sigDoc; - } - protected String getCanonicalizationMethod() { return CanonicalizationMethod.INCLUSIVE; } - protected void writeDocument() throws IOException { + protected void writeDocument(Document document) throws IOException, XmlException { XmlOptions xo = new XmlOptions(); Map namespaceMap = new HashMap(); for (SignatureFacet sf : this.signatureFacets) { @@ -594,6 +547,7 @@ public class XmlSignatureService implements SignatureService { } OutputStream os = sigPart.getOutputStream(); + SignatureDocument sigDoc = SignatureDocument.Factory.parse(document); sigDoc.save(os, xo); os.close(); @@ -612,4 +566,9 @@ public class XmlSignatureService implements SignatureService { sigsPart.addRelationship(sigPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE); } + + @SuppressWarnings("unchecked") + public static List safe(List other) { + return other == null ? Collections.EMPTY_LIST : other; + } } diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/spi/Constants.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/spi/Constants.java deleted file mode 100644 index 7c2caeb633..0000000000 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/spi/Constants.java +++ /dev/null @@ -1,30 +0,0 @@ -/* ==================================================================== - 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. -==================================================================== */ - -/* ==================================================================== - 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 - Copyright (C) 2008-2014 FedICT. - ================================================================= */ - -package org.apache.poi.poifs.crypt.dsig.spi; - -public interface Constants { - String NamespaceSpecNS = "http://www.w3.org/2000/xmlns/"; - String SignatureSpecNS = "http://www.w3.org/2000/09/xmldsig#"; -} -- 2.39.5