From: Andreas Beeker Date: Sun, 24 Aug 2014 23:06:05 +0000 (+0000) Subject: removed HorribleProxy X-Git-Tag: REL_3_11_BETA3~73^2~16 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=3d81d013a363dac6bfebb59dddaae035d59e86bb;p=poi.git 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 --- 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#"; -}