]> source.dussan.org Git - poi.git/commitdiff
reorganization, xmlsignatureservice is now in signatureinfo
authorAndreas Beeker <kiwiwings@apache.org>
Thu, 18 Sep 2014 23:47:41 +0000 (23:47 +0000)
committerAndreas Beeker <kiwiwings@apache.org>
Thu, 18 Sep 2014 23:47:41 +0000 (23:47 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/xml_signature@1626107 13f79535-47bb-0310-9956-ffa450edef68

14 files changed:
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfoConfig.java
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignaturePolicyService.java [deleted file]
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/SignaturePolicyService.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/SignatureService.java [deleted file]
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/XmlSignatureService.java [deleted file]
src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java

index 963d023c4a9d53454dc1981e268d36298f278630..038c4306dc6218e74614242cf1a6371fb2987da5 100644 (file)
 \r
 package org.apache.poi.poifs.crypt.dsig;\r
 \r
+import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_MAC_HMAC_RIPEMD160;\r
+import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;\r
+import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256;\r
+import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384;\r
+import static org.apache.xml.security.signature.XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512;\r
+\r
 import java.io.ByteArrayOutputStream;\r
+import java.io.File;\r
 import java.io.IOException;\r
+import java.io.OutputStream;\r
+import java.net.URISyntaxException;\r
+import java.security.InvalidAlgorithmParameterException;\r
+import java.security.MessageDigest;\r
 import java.security.NoSuchAlgorithmException;\r
-import java.security.PrivateKey;\r
+import java.security.NoSuchProviderException;\r
 import java.security.Provider;\r
 import java.security.cert.X509Certificate;\r
 import java.util.ArrayList;\r
 import java.util.Collections;\r
+import java.util.HashMap;\r
 import java.util.List;\r
+import java.util.Map;\r
 \r
 import javax.crypto.Cipher;\r
 import javax.xml.crypto.MarshalException;\r
+import javax.xml.crypto.URIDereferencer;\r
+import javax.xml.crypto.XMLStructure;\r
+import javax.xml.crypto.dsig.CanonicalizationMethod;\r
+import javax.xml.crypto.dsig.DigestMethod;\r
+import javax.xml.crypto.dsig.Manifest;\r
+import javax.xml.crypto.dsig.Reference;\r
+import javax.xml.crypto.dsig.SignatureMethod;\r
+import javax.xml.crypto.dsig.SignedInfo;\r
+import javax.xml.crypto.dsig.XMLObject;\r
+import javax.xml.crypto.dsig.XMLSignContext;\r
 import javax.xml.crypto.dsig.XMLSignature;\r
+import javax.xml.crypto.dsig.XMLSignatureException;\r
 import javax.xml.crypto.dsig.XMLSignatureFactory;\r
+import javax.xml.crypto.dsig.dom.DOMSignContext;\r
 import javax.xml.crypto.dsig.dom.DOMValidateContext;\r
 import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;\r
+import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;\r
 import javax.xml.parsers.ParserConfigurationException;\r
+import javax.xml.transform.TransformerException;\r
+import javax.xml.transform.TransformerFactoryConfigurationError;\r
 \r
+import org.apache.jcp.xml.dsig.internal.dom.DOMReference;\r
+import org.apache.jcp.xml.dsig.internal.dom.DOMSignedInfo;\r
 import org.apache.poi.EncryptedDocumentException;\r
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;\r
 import org.apache.poi.openxml4j.opc.OPCPackage;\r
+import org.apache.poi.openxml4j.opc.PackageNamespaces;\r
 import org.apache.poi.openxml4j.opc.PackagePart;\r
+import org.apache.poi.openxml4j.opc.PackagePartName;\r
 import org.apache.poi.openxml4j.opc.PackageRelationship;\r
 import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;\r
 import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;\r
+import org.apache.poi.openxml4j.opc.PackagingURIHelper;\r
+import org.apache.poi.openxml4j.opc.TargetMode;\r
 import org.apache.poi.poifs.crypt.ChainingMode;\r
 import org.apache.poi.poifs.crypt.CipherAlgorithm;\r
 import org.apache.poi.poifs.crypt.CryptoFunctions;\r
-import org.apache.poi.poifs.crypt.HashAlgorithm;\r
+import org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet;\r
 import org.apache.poi.poifs.crypt.dsig.services.RelationshipTransformService;\r
-import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;\r
 import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;\r
 import org.apache.poi.util.DocumentHelper;\r
 import org.apache.poi.util.POILogFactory;\r
 import org.apache.poi.util.POILogger;\r
 import org.apache.xml.security.Init;\r
-import org.apache.xmlbeans.XmlCursor;\r
+import org.apache.xml.security.utils.Base64;\r
 import org.apache.xmlbeans.XmlException;\r
-import org.apache.xmlbeans.XmlObject;\r
+import org.apache.xmlbeans.XmlOptions;\r
+import org.w3.x2000.x09.xmldsig.SignatureDocument;\r
 import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
 import org.w3c.dom.Node;\r
 import org.w3c.dom.NodeList;\r
+import org.w3c.dom.events.Event;\r
+import org.w3c.dom.events.EventListener;\r
+import org.w3c.dom.events.EventTarget;\r
+import org.w3c.dom.events.MutationEvent;\r
+import org.xml.sax.SAXException;\r
 \r
 public class SignatureInfo {\r
 \r
@@ -104,12 +144,16 @@ public class SignatureInfo {
     private static final POILogger LOG = POILogFactory.getLogger(SignatureInfo.class);\r
     private static boolean isInitialized = false;\r
     \r
-    private final OPCPackage pkg;\r
-    \r
-    public SignatureInfo(OPCPackage pkg) {\r
-        this.pkg = pkg;\r
+    private SignatureInfoConfig signatureConfig;\r
+\r
+    public SignatureInfoConfig getSignatureConfig() {\r
+        return signatureConfig;\r
     }\r
-    \r
+\r
+    public void setSignatureConfig(SignatureInfoConfig signatureConfig) {\r
+        this.signatureConfig = signatureConfig;\r
+    }\r
+\r
     public boolean verifySignature() {\r
         initXmlProvider();\r
         // http://www.oracle.com/technetwork/articles/javase/dig-signature-api-140772.html\r
@@ -117,40 +161,27 @@ public class SignatureInfo {
         return getSignersAndValidate(signers, true);\r
     }\r
 \r
-    public void confirmSignature(PrivateKey key, X509Certificate x509)\r
-    throws NoSuchAlgorithmException, IOException, MarshalException, ParserConfigurationException, XmlException {\r
-        confirmSignature(key, x509, HashAlgorithm.sha1);\r
-    }\r
-    \r
-    public void confirmSignature(PrivateKey key, X509Certificate x509, HashAlgorithm hashAlgo)\r
-    throws NoSuchAlgorithmException, IOException, MarshalException, ParserConfigurationException, XmlException {\r
-        SignatureInfoConfig signatureConfig = new SignatureInfoConfig();\r
-        signatureConfig.setOpcPackage(pkg);\r
-        signatureConfig.setDigestAlgo(hashAlgo);\r
-        signatureConfig.setSigningCertificateChain(Collections.singletonList(x509));\r
-        signatureConfig.setKey(key);\r
-        signatureConfig.addDefaultFacets();\r
-        XmlSignatureService signatureService = new XmlSignatureService(signatureConfig);\r
-\r
+    public void confirmSignature()\r
+    throws NoSuchAlgorithmException, IOException, MarshalException, ParserConfigurationException, XmlException, InvalidAlgorithmParameterException, NoSuchProviderException, XMLSignatureException, TransformerFactoryConfigurationError, TransformerException, SAXException, URISyntaxException {\r
         Document document = DocumentHelper.createDocument();\r
         \r
         // operate\r
-        DigestInfo digestInfo = signatureService.preSign(document, null);\r
+        DigestInfo digestInfo = preSign(document, null);\r
 \r
         // setup: key material, signature value\r
-        byte[] signatureValue = signDigest(key, hashAlgo, digestInfo.digestValue);\r
+        byte[] signatureValue = signDigest(digestInfo.digestValue);\r
         \r
         // operate: postSign\r
-        signatureService.postSign(document, signatureValue);\r
+        postSign(document, signatureValue);\r
     }\r
 \r
-    public static byte[] signDigest(PrivateKey key, HashAlgorithm hashAlgo, byte digest[]) {\r
-        Cipher cipher = CryptoFunctions.getCipher(key, CipherAlgorithm.rsa\r
+    public byte[] signDigest(byte digest[]) {\r
+        Cipher cipher = CryptoFunctions.getCipher(signatureConfig.getKey(), CipherAlgorithm.rsa\r
             , ChainingMode.ecb, null, Cipher.ENCRYPT_MODE, "PKCS1Padding");\r
             \r
         try {\r
             ByteArrayOutputStream digestInfoValueBuf = new ByteArrayOutputStream();\r
-            digestInfoValueBuf.write(getHashMagic(hashAlgo));\r
+            digestInfoValueBuf.write(getHashMagic());\r
             digestInfoValueBuf.write(digest);\r
             byte[] digestInfoValue = digestInfoValueBuf.toByteArray();\r
             byte[] signatureValue = cipher.doFinal(digestInfoValue);\r
@@ -175,15 +206,12 @@ public class SignatureInfo {
             allValid = false;\r
         }\r
 \r
-        SignatureInfoConfig signatureConfig = new SignatureInfoConfig();\r
-        signatureConfig.setOpcPackage(pkg);\r
-        \r
         for (PackagePart signaturePart : signatureParts) {\r
             KeyInfoKeySelector keySelector = new KeyInfoKeySelector();\r
 \r
             try {\r
                 Document doc = DocumentHelper.readDocument(signaturePart.getInputStream());\r
-                XmlSignatureService.registerIds(doc);\r
+                registerIds(doc);\r
                 \r
                 DOMValidateContext domValidateContext = new DOMValidateContext(keySelector, doc);\r
                 domValidateContext.setProperty("org.jcp.xml.dsig.validateManifests", Boolean.TRUE);\r
@@ -209,6 +237,7 @@ public class SignatureInfo {
 \r
     protected List<PackagePart> getSignatureParts(boolean onlyFirst) {\r
         List<PackagePart> packageParts = new ArrayList<PackagePart>();\r
+        OPCPackage pkg = signatureConfig.getOpcPackage();\r
         \r
         PackageRelationshipCollection sigOrigRels = pkg.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN);\r
         for (PackageRelationship rel : sigOrigRels) {\r
@@ -260,31 +289,6 @@ public class SignatureInfo {
         throw new RuntimeException("JRE doesn't support default xml signature provider - set jsr105Provider system property!");\r
     }\r
     \r
-    public static void insertXChild(XmlObject root, XmlObject child) {\r
-        XmlCursor rootCursor = root.newCursor();\r
-        insertXChild(rootCursor, child);\r
-        rootCursor.dispose();\r
-    }\r
-\r
-    public static void insertXChild(XmlCursor rootCursor, XmlObject child) {\r
-        rootCursor.toEndToken();\r
-        XmlCursor childCursor = child.newCursor();\r
-        childCursor.toNextToken();\r
-        childCursor.moveXml(rootCursor);\r
-        childCursor.dispose();\r
-    }\r
-\r
-//    public static void setPrefix(XmlObject xobj, String ns, String prefix) {\r
-//        XmlCursor cur;\r
-//        for (cur = xobj.newCursor(); cur.hasNextToken(); cur.toNextToken()) {\r
-//            if (cur.isStart()) {\r
-//                Element el = (Element)cur.getDomNode();\r
-//                if (ns.equals(el.getNamespaceURI())) el.setPrefix(prefix);\r
-//            }\r
-//        }\r
-//        cur.dispose();\r
-//    }\r
-\r
     public static void setPrefix(Node el, String ns, String prefix) {\r
         if (ns.equals(el.getNamespaceURI())) el.setPrefix(prefix);\r
         NodeList nl = el.getChildNodes();\r
@@ -293,8 +297,8 @@ public class SignatureInfo {
         }\r
     }\r
     \r
-    protected static byte[] getHashMagic(HashAlgorithm hashAlgo) {\r
-        switch (hashAlgo) {\r
+    protected byte[] getHashMagic() {\r
+        switch (signatureConfig.getDigestAlgo()) {\r
         case sha1: return SHA1_DIGEST_INFO_PREFIX;\r
         // sha224: return SHA224_DIGEST_INFO_PREFIX;\r
         case sha256: return SHA256_DIGEST_INFO_PREFIX;\r
@@ -303,9 +307,22 @@ public class SignatureInfo {
         case ripemd128: return RIPEMD128_DIGEST_INFO_PREFIX;\r
         case ripemd160: return RIPEMD160_DIGEST_INFO_PREFIX;\r
         // case ripemd256: return RIPEMD256_DIGEST_INFO_PREFIX;\r
-        default: throw new EncryptedDocumentException("Hash algorithm "+hashAlgo+" not supported for signing.");\r
+        default: throw new EncryptedDocumentException("Hash algorithm "+signatureConfig.getDigestAlgo()+" not supported for signing.");\r
         }\r
     }\r
+\r
+    protected String getSignatureMethod() {\r
+        switch (signatureConfig.getDigestAlgo()) {\r
+        case sha1:   return ALGO_ID_SIGNATURE_RSA_SHA1;\r
+        case sha256: return ALGO_ID_SIGNATURE_RSA_SHA256;\r
+        case sha384: return ALGO_ID_SIGNATURE_RSA_SHA384;\r
+        case sha512: return ALGO_ID_SIGNATURE_RSA_SHA512;\r
+        case ripemd160: return ALGO_ID_MAC_HMAC_RIPEMD160;\r
+        default: throw new EncryptedDocumentException("Hash algorithm "+signatureConfig.getDigestAlgo()+" not supported for signing.");\r
+        }\r
+    }\r
+\r
+    \r
     \r
     public static synchronized void initXmlProvider() {\r
         if (isInitialized) return;\r
@@ -319,4 +336,281 @@ public class SignatureInfo {
             throw new RuntimeException("Xml & BouncyCastle-Provider initialization failed", e);\r
         }\r
     }\r
+    \r
+    @SuppressWarnings("unchecked")\r
+    public DigestInfo preSign(Document document, List<DigestInfo> digestInfos)\r
+        throws ParserConfigurationException, NoSuchAlgorithmException,\r
+        InvalidAlgorithmParameterException, MarshalException,\r
+        javax.xml.crypto.dsig.XMLSignatureException,\r
+        TransformerFactoryConfigurationError, TransformerException,\r
+        IOException, SAXException, NoSuchProviderException, XmlException, URISyntaxException {\r
+        SignatureInfo.initXmlProvider();\r
+        \r
+        // it's necessary to explicitly set the mdssi namespace, but the sign() method has no\r
+        // normal way to interfere with, so we need to add the namespace under the hand ...\r
+        final EventTarget et = (EventTarget)document;\r
+        EventListener myModificationListener = new EventListener() {\r
+            @Override\r
+            public void handleEvent(Event e) {\r
+                if (e instanceof MutationEvent) {\r
+                    MutationEvent mutEvt = (MutationEvent)e;\r
+                    if (mutEvt.getTarget() instanceof Element) {\r
+                        Element el = (Element)mutEvt.getTarget();\r
+                        if ("idPackageObject".equals(el.getAttribute("Id"))) {\r
+                            et.removeEventListener("DOMSubtreeModified", this, false);\r
+                            el.setAttributeNS(XmlNS, "xmlns:mdssi", PackageNamespaces.DIGITAL_SIGNATURE);\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        };\r
+        \r
+        et.addEventListener("DOMSubtreeModified", myModificationListener, false);\r
+        \r
+        /*\r
+         * Signature context construction.\r
+         */\r
+        XMLSignContext xmlSignContext = new DOMSignContext(signatureConfig.getKey(), document);\r
+        URIDereferencer uriDereferencer = signatureConfig.getUriDereferencer();\r
+        if (null != uriDereferencer) {\r
+            xmlSignContext.setURIDereferencer(uriDereferencer);\r
+        }\r
+\r
+        xmlSignContext.putNamespacePrefix(\r
+                "http://schemas.openxmlformats.org/package/2006/digital-signature",\r
+                "mdssi");\r
+        \r
+        String sigNsPrefix = signatureConfig.getSignatureNamespacePrefix();\r
+        if (sigNsPrefix != null) {\r
+            /*\r
+             * OOo doesn't like ds namespaces so per default prefixing is off.\r
+             */\r
+            xmlSignContext.putNamespacePrefix(XmlDSigNS, sigNsPrefix);\r
+        }\r
+\r
+        XMLSignatureFactory signatureFactory = SignatureInfo.getSignatureFactory();\r
+\r
+        /*\r
+         * Add ds:References that come from signing client local files.\r
+         */\r
+        List<Reference> references = new ArrayList<Reference>();\r
+        for (DigestInfo digestInfo : safe(digestInfos)) {\r
+            byte[] documentDigestValue = digestInfo.digestValue;\r
+\r
+            DigestMethod digestMethod = signatureFactory.newDigestMethod(\r
+                            digestInfo.hashAlgo.xmlSignUri, null);\r
+\r
+            String uri = new File(digestInfo.description).getName();\r
+\r
+            Reference reference = signatureFactory.newReference\r
+                (uri, digestMethod, null, null, null, documentDigestValue);\r
+            references.add(reference);\r
+        }\r
+\r
+        /*\r
+         * Invoke the signature facets.\r
+         */\r
+        List<XMLObject> objects = new ArrayList<XMLObject>();\r
+        for (SignatureFacet signatureFacet : signatureConfig.getSignatureFacets()) {\r
+            LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName());\r
+            signatureFacet.preSign(document, signatureFactory, references, objects);\r
+        }\r
+\r
+        /*\r
+         * ds:SignedInfo\r
+         */\r
+        SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(getSignatureMethod(), null);\r
+        CanonicalizationMethod canonicalizationMethod = signatureFactory\r
+            .newCanonicalizationMethod(signatureConfig.getCanonicalizationMethod(),\r
+            (C14NMethodParameterSpec) null);\r
+        SignedInfo signedInfo = signatureFactory.newSignedInfo(\r
+            canonicalizationMethod, signatureMethod, references);\r
+\r
+        /*\r
+         * JSR105 ds:Signature creation\r
+         */\r
+        String signatureValueId = signatureConfig.getPackageSignatureId() + "-signature-value";\r
+        javax.xml.crypto.dsig.XMLSignature xmlSignature = signatureFactory\r
+            .newXMLSignature(signedInfo, null, objects, signatureConfig.getPackageSignatureId(),\r
+            signatureValueId);\r
+\r
+        /*\r
+         * ds:Signature Marshalling.\r
+         */\r
+        xmlSignContext.setDefaultNamespacePrefix(signatureConfig.getSignatureNamespacePrefix());\r
+        // xmlSignContext.putNamespacePrefix(PackageNamespaces.DIGITAL_SIGNATURE, "mdssi");\r
+        xmlSignature.sign(xmlSignContext);\r
+\r
+        registerIds(document);\r
+        \r
+        /*\r
+         * Completion of undigested ds:References in the ds:Manifests.\r
+         */\r
+        for (XMLObject object : objects) {\r
+            LOG.log(POILogger.DEBUG, "object java type: " + object.getClass().getName());\r
+            List<XMLStructure> objectContentList = object.getContent();\r
+            for (XMLStructure objectContent : objectContentList) {\r
+                LOG.log(POILogger.DEBUG, "object content java type: " + objectContent.getClass().getName());\r
+                if (!(objectContent instanceof Manifest)) continue;\r
+                Manifest manifest = (Manifest) objectContent;\r
+                List<Reference> manifestReferences = manifest.getReferences();\r
+                for (Reference manifestReference : manifestReferences) {\r
+                    if (manifestReference.getDigestValue() != null) continue;\r
+\r
+                    DOMReference manifestDOMReference = (DOMReference)manifestReference;\r
+                    manifestDOMReference.digest(xmlSignContext);\r
+                }\r
+            }\r
+        }\r
+\r
+        /*\r
+         * Completion of undigested ds:References.\r
+         */\r
+        List<Reference> signedInfoReferences = signedInfo.getReferences();\r
+        for (Reference signedInfoReference : signedInfoReferences) {\r
+            DOMReference domReference = (DOMReference)signedInfoReference;\r
+\r
+            // ds:Reference with external digest value\r
+            if (domReference.getDigestValue() != null) continue;\r
+            \r
+            domReference.digest(xmlSignContext);\r
+        }\r
+\r
+        /*\r
+         * Calculation of XML signature digest value.\r
+         */\r
+        DOMSignedInfo domSignedInfo = (DOMSignedInfo)signedInfo;\r
+        ByteArrayOutputStream dataStream = new ByteArrayOutputStream();\r
+        domSignedInfo.canonicalize(xmlSignContext, dataStream);\r
+        byte[] octets = dataStream.toByteArray();\r
+\r
+        /*\r
+         * TODO: we could be using DigestOutputStream here to optimize memory\r
+         * usage.\r
+         */\r
+\r
+        MessageDigest jcaMessageDigest = CryptoFunctions.getMessageDigest(signatureConfig.getDigestAlgo());\r
+        byte[] digestValue = jcaMessageDigest.digest(octets);\r
+        \r
+        \r
+        String description = signatureConfig.getSignatureDescription();\r
+        return new DigestInfo(digestValue, signatureConfig.getDigestAlgo(), description);\r
+    }\r
+\r
+    public void postSign(Document document, byte[] signatureValue)\r
+    throws IOException, MarshalException, ParserConfigurationException, XmlException {\r
+        LOG.log(POILogger.DEBUG, "postSign");\r
+        SignatureInfo.initXmlProvider();\r
+\r
+        /*\r
+         * Check ds:Signature node.\r
+         */\r
+        String signatureId = signatureConfig.getPackageSignatureId();\r
+        if (!signatureId.equals(document.getDocumentElement().getAttribute("Id"))) {\r
+            throw new RuntimeException("ds:Signature not found for @Id: " + signatureId);\r
+        }\r
+\r
+        /*\r
+         * Insert signature value into the ds:SignatureValue element\r
+         */\r
+        NodeList sigValNl = document.getElementsByTagNameNS(XmlDSigNS, "SignatureValue");\r
+        if (sigValNl.getLength() != 1) {\r
+            throw new RuntimeException("preSign has to be called before postSign");\r
+        }\r
+        sigValNl.item(0).setTextContent(Base64.encode(signatureValue));\r
+\r
+        /*\r
+         * Allow signature facets to inject their own stuff.\r
+         */\r
+        for (SignatureFacet signatureFacet : signatureConfig.getSignatureFacets()) {\r
+            signatureFacet.postSign(document, signatureConfig.getSigningCertificateChain());\r
+        }\r
+\r
+        registerIds(document);\r
+        writeDocument(document);\r
+    }\r
+\r
+    protected void writeDocument(Document document) throws IOException, XmlException {\r
+        XmlOptions xo = new XmlOptions();\r
+        Map<String,String> namespaceMap = new HashMap<String,String>();\r
+        for (SignatureFacet sf : signatureConfig.getSignatureFacets()) {\r
+            Map<String,String> sfm = sf.getNamespacePrefixMapping();\r
+            if (sfm != null) {\r
+                namespaceMap.putAll(sfm);\r
+            }\r
+        }\r
+        xo.setSaveSuggestedPrefixes(namespaceMap);\r
+        xo.setUseDefaultNamespace();\r
+\r
+        LOG.log(POILogger.DEBUG, "output signed Office OpenXML document");\r
+\r
+        /*\r
+         * Copy the original OOXML content to the signed OOXML package. During\r
+         * copying some files need to changed.\r
+         */\r
+        OPCPackage pkg = signatureConfig.getOpcPackage();\r
+\r
+        PackagePartName sigPartName, sigsPartName;\r
+        try {\r
+            // <Override PartName="/_xmlsignatures/sig1.xml" ContentType="application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"/>\r
+            sigPartName = PackagingURIHelper.createPartName("/_xmlsignatures/sig1.xml");\r
+            // <Default Extension="sigs" ContentType="application/vnd.openxmlformats-package.digital-signature-origin"/>\r
+            sigsPartName = PackagingURIHelper.createPartName("/_xmlsignatures/origin.sigs");\r
+        } catch (InvalidFormatException e) {\r
+            throw new IOException(e);\r
+        }\r
+        \r
+        String sigContentType = "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml";\r
+        PackagePart sigPart = pkg.getPart(sigPartName);\r
+        if (sigPart == null) {\r
+            sigPart = pkg.createPart(sigPartName, sigContentType);\r
+        }\r
+        \r
+        OutputStream os = sigPart.getOutputStream();\r
+        SignatureDocument sigDoc = SignatureDocument.Factory.parse(document);\r
+        sigDoc.save(os, xo);\r
+        os.close();\r
+        \r
+        String sigsContentType = "application/vnd.openxmlformats-package.digital-signature-origin";\r
+        PackagePart sigsPart = pkg.getPart(sigsPartName);\r
+        if (sigsPart == null) {\r
+            // touch empty marker file\r
+            sigsPart = pkg.createPart(sigsPartName, sigsContentType);\r
+        }\r
+        \r
+        PackageRelationshipCollection relCol = pkg.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN);\r
+        for (PackageRelationship pr : relCol) {\r
+            pkg.removeRelationship(pr.getId());\r
+        }\r
+        pkg.addRelationship(sigsPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN);\r
+        \r
+        sigsPart.addRelationship(sigPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE);\r
+    }\r
+    \r
+    /**\r
+     * the resulting document needs to be tweaked before it can be digested -\r
+     * this applies to the verification and signing step\r
+     *\r
+     * @param doc\r
+     */\r
+    private static void registerIds(Document doc) {\r
+        NodeList nl = doc.getElementsByTagNameNS(XmlDSigNS, "Object");\r
+        registerIdAttribute(nl);\r
+        nl = doc.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "SignedProperties");\r
+        registerIdAttribute(nl);\r
+    }\r
+    \r
+    public static void registerIdAttribute(NodeList nl) {\r
+        for (int i=0; i<nl.getLength(); i++) {\r
+            Element el = (Element)nl.item(i);\r
+            if (el.hasAttribute("Id")) {\r
+                el.setIdAttribute("Id", true);\r
+            }\r
+        }\r
+    }\r
+    \r
+    @SuppressWarnings("unchecked")\r
+    public static <T> List<T> safe(List<T> other) {\r
+        return other == null ? Collections.EMPTY_LIST : other;\r
+    }\r
 }\r
index 9468720bf211df776ff5b4f6a73ef2b27a1b5fb1..e7fc975f3c96e68dea49759c51d25b64c9bc957b 100644 (file)
@@ -22,8 +22,10 @@ import java.security.cert.X509Certificate;
 import java.util.ArrayList;\r
 import java.util.Date;\r
 import java.util.List;\r
+import java.util.UUID;\r
 \r
 import javax.xml.crypto.URIDereferencer;\r
+import javax.xml.crypto.dsig.CanonicalizationMethod;\r
 \r
 import org.apache.poi.openxml4j.opc.OPCPackage;\r
 import org.apache.poi.poifs.crypt.HashAlgorithm;\r
@@ -31,8 +33,8 @@ import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet;
 import org.apache.poi.poifs.crypt.dsig.facets.OOXMLSignatureFacet;\r
 import org.apache.poi.poifs.crypt.dsig.facets.Office2010SignatureFacet;\r
 import org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet;\r
-import org.apache.poi.poifs.crypt.dsig.facets.SignaturePolicyService;\r
 import org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet;\r
+import org.apache.poi.poifs.crypt.dsig.services.SignaturePolicyService;\r
 import org.apache.poi.poifs.crypt.dsig.spi.AddressDTO;\r
 import org.apache.poi.poifs.crypt.dsig.spi.IdentityDTO;\r
 \r
@@ -48,7 +50,21 @@ public class SignatureInfoConfig {
     private AddressDTO address;\r
     private byte[] photo;\r
     private SignaturePolicyService signaturePolicyService;\r
-    private URIDereferencer uriDereferencer; \r
+    private URIDereferencer uriDereferencer;\r
+    private String signatureNamespacePrefix;\r
+    private String canonicalizationMethod = CanonicalizationMethod.INCLUSIVE;\r
+\r
+    /**\r
+     * The signature Id attribute value used to create the XML signature. A\r
+     * <code>null</code> value will trigger an automatically generated signature Id.\r
+     */\r
+    private String packageSignatureId = "idPackageSignature";\r
+    \r
+    /**\r
+     * Gives back the human-readable description of what the citizen will be\r
+     * signing. The default value is "Office OpenXML Document".\r
+     */\r
+    private String signatureDescription = "Office OpenXML Document";\r
 \r
     public SignatureInfoConfig() {\r
         OOXMLURIDereferencer uriDereferencer = new OOXMLURIDereferencer();\r
@@ -148,8 +164,7 @@ public class SignatureInfoConfig {
     public SignaturePolicyService getSignaturePolicyService() {\r
         return signaturePolicyService;\r
     }\r
-    public void setSignaturePolicyService(\r
-            SignaturePolicyService signaturePolicyService) {\r
+    public void setSignaturePolicyService(SignaturePolicyService signaturePolicyService) {\r
         this.signaturePolicyService = signaturePolicyService;\r
     }\r
     public URIDereferencer getUriDereferencer() {\r
@@ -158,6 +173,30 @@ public class SignatureInfoConfig {
     public void setUriDereferencer(URIDereferencer uriDereferencer) {\r
         this.uriDereferencer = uriDereferencer;\r
     }\r
-\r
-\r
+    public String getSignatureDescription() {\r
+        return signatureDescription;\r
+    }\r
+    public void setSignatureDescription(String signatureDescription) {\r
+        this.signatureDescription = signatureDescription;\r
+    }\r
+    public String getSignatureNamespacePrefix() {\r
+        return signatureNamespacePrefix;\r
+    }\r
+    public void setSignatureNamespacePrefix(String signatureNamespacePrefix) {\r
+        this.signatureNamespacePrefix = signatureNamespacePrefix;\r
+    }\r
+    public String getCanonicalizationMethod() {\r
+        return canonicalizationMethod;\r
+    }\r
+    public void setCanonicalizationMethod(String canonicalizationMethod) {\r
+        this.canonicalizationMethod = canonicalizationMethod;\r
+    }\r
+    public String getPackageSignatureId() {\r
+        return packageSignatureId;\r
+    }\r
+    public void setPackageSignatureId(String packageSignatureId) {\r
+        this.packageSignatureId = (packageSignatureId != null)\r
+            ? packageSignatureId\r
+            : "xmldsig-" + UUID.randomUUID();\r
+    }\r
 }\r
index 6360d4a7e08fe83907f45c888f259814c237c516..1a6c93987e836918916d1701db65bbfba740b969 100644 (file)
@@ -15,7 +15,7 @@ import javax.xml.crypto.dsig.XMLObject;
 import javax.xml.crypto.dsig.XMLSignatureFactory;\r
 import javax.xml.crypto.dsig.spec.TransformParameterSpec;\r
 \r
-import org.apache.poi.poifs.crypt.HashAlgorithm;\r
+import org.apache.poi.poifs.crypt.dsig.SignatureInfoConfig;\r
 import org.w3c.dom.Document;\r
 \r
 /**\r
@@ -26,24 +26,10 @@ import org.w3c.dom.Document;
  */\r
 public class EnvelopedSignatureFacet implements SignatureFacet {\r
 \r
-    private final HashAlgorithm hashAlgo;\r
+    private SignatureInfoConfig signatureConfig;\r
 \r
-    /**\r
-     * Default constructor. Digest algorithm will be SHA-1.\r
-     */\r
-    public EnvelopedSignatureFacet() {\r
-        this(HashAlgorithm.sha1);\r
-    }\r
-\r
-    /**\r
-     * Main constructor.\r
-     * \r
-     * @param hashAlgo\r
-     *            the digest algorithm to be used within the ds:Reference\r
-     *            element. Possible values: "SHA-1", "SHA-256, or "SHA-512".\r
-     */\r
-    public EnvelopedSignatureFacet(HashAlgorithm hashAlgo) {\r
-        this.hashAlgo = hashAlgo;\r
+    public EnvelopedSignatureFacet(SignatureInfoConfig signatureConfig) {\r
+        this.signatureConfig = signatureConfig;\r
     }\r
 \r
     @Override\r
@@ -52,14 +38,12 @@ public class EnvelopedSignatureFacet implements SignatureFacet {
     }\r
 \r
     @Override\r
-    public void preSign(Document document,\r
-            XMLSignatureFactory signatureFactory,\r
-            String signatureId,\r
-            List<X509Certificate> signingCertificateChain,\r
-            List<Reference> references, List<XMLObject> objects)\r
-            throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {\r
-        DigestMethod digestMethod = signatureFactory.newDigestMethod(\r
-                this.hashAlgo.xmlSignUri, null);\r
+    public void preSign(Document document\r
+        , XMLSignatureFactory signatureFactory\r
+        , List<Reference> references\r
+        , List<XMLObject> objects)\r
+    throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {\r
+        DigestMethod digestMethod = signatureFactory.newDigestMethod(signatureConfig.getDigestAlgo().xmlSignUri, null);\r
 \r
         List<Transform> transforms = new ArrayList<Transform>();\r
         Transform envelopedTransform = signatureFactory\r
index 3768f58f9366915790248ac183ca71afe431a5ae..3355cb2bfd1dc670aadea69c18bbc348eec2a44e 100644 (file)
@@ -173,12 +173,11 @@ public class KeyInfoSignatureFacet implements SignatureFacet {
     }\r
 \r
     @Override\r
-    public void preSign(Document document,\r
-        XMLSignatureFactory signatureFactory,\r
-        String signatureId,\r
-        List<X509Certificate> signingCertificateChain,\r
-        List<Reference> references,\r
-        List<XMLObject> objects\r
+    public void preSign(\r
+          Document document\r
+        , XMLSignatureFactory signatureFactory\r
+        , List<Reference> references\r
+        , List<XMLObject> objects\r
     ) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {\r
         // empty\r
     }\r
index fbaf0e53f59d839a39ad0f25a791ef3ece9bb46c..8d87cae96662f3392d610460f95939cf8ef1db2b 100644 (file)
@@ -104,20 +104,20 @@ public class OOXMLSignatureFacet implements SignatureFacet {
     }\r
 \r
     @Override\r
-    public void preSign(Document document,\r
-            XMLSignatureFactory signatureFactory,\r
-            String signatureId,\r
-            List<X509Certificate> signingCertificateChain,\r
-            List<Reference> references, List<XMLObject> objects)\r
-            throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException {\r
+    public void preSign(\r
+        Document document\r
+        , XMLSignatureFactory signatureFactory\r
+        , List<Reference> references\r
+        , List<XMLObject> objects)\r
+    throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException {\r
         LOG.log(POILogger.DEBUG, "pre sign");\r
-        addManifestObject(document, signatureFactory, signatureId, references, objects);\r
-        addSignatureInfo(document, signatureFactory, signatureId, references, objects);\r
+        addManifestObject(document, signatureFactory, references, objects);\r
+        addSignatureInfo(document, signatureFactory, references, objects);\r
     }\r
 \r
     private void addManifestObject(Document document,\r
             XMLSignatureFactory signatureFactory,\r
-            String signatureId, List<Reference> references,\r
+            List<Reference> references,\r
             List<XMLObject> objects) throws NoSuchAlgorithmException,\r
             InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException {\r
 \r
@@ -129,7 +129,7 @@ public class OOXMLSignatureFacet implements SignatureFacet {
         List<XMLStructure> objectContent = new ArrayList<XMLStructure>();\r
         objectContent.add(manifest);\r
 \r
-        addSignatureTime(document, signatureFactory, signatureId, objectContent);\r
+        addSignatureTime(document, signatureFactory, objectContent);\r
 \r
         XMLObject xo = signatureFactory.newXMLObject(objectContent, objectId, null, null);\r
         objects.add(xo);\r
@@ -225,7 +225,6 @@ public class OOXMLSignatureFacet implements SignatureFacet {
 \r
     private void addSignatureTime(Document document,\r
             XMLSignatureFactory signatureFactory,\r
-            String signatureId,\r
             List<XMLStructure> objectContent) {\r
         /*\r
          * SignatureTime\r
@@ -247,7 +246,7 @@ public class OOXMLSignatureFacet implements SignatureFacet {
         List<XMLStructure> signatureTimeContent = new ArrayList<XMLStructure>();\r
         signatureTimeContent.add(new DOMStructure(n));\r
         SignatureProperty signatureTimeSignatureProperty = signatureFactory\r
-                .newSignatureProperty(signatureTimeContent, "#" + signatureId,\r
+                .newSignatureProperty(signatureTimeContent, "#" + signatureConfig.getPackageSignatureId(),\r
                         "idSignatureTime");\r
         List<SignatureProperty> signaturePropertyContent = new ArrayList<SignatureProperty>();\r
         signaturePropertyContent.add(signatureTimeSignatureProperty);\r
@@ -258,10 +257,10 @@ public class OOXMLSignatureFacet implements SignatureFacet {
     }\r
 \r
     private void addSignatureInfo(Document document,\r
-            XMLSignatureFactory signatureFactory,\r
-            String signatureId, List<Reference> references,\r
-            List<XMLObject> objects) throws NoSuchAlgorithmException,\r
-            InvalidAlgorithmParameterException {\r
+        XMLSignatureFactory signatureFactory,\r
+        List<Reference> references,\r
+        List<XMLObject> objects)\r
+    throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {\r
         List<XMLStructure> objectContent = new ArrayList<XMLStructure>();\r
 \r
         SignatureInfoV1Document sigV1 = SignatureInfoV1Document.Factory.newInstance();\r
@@ -273,7 +272,7 @@ public class OOXMLSignatureFacet implements SignatureFacet {
         List<XMLStructure> signatureInfoContent = new ArrayList<XMLStructure>();\r
         signatureInfoContent.add(new DOMStructure(n));\r
         SignatureProperty signatureInfoSignatureProperty = signatureFactory\r
-                .newSignatureProperty(signatureInfoContent, "#" + signatureId,\r
+                .newSignatureProperty(signatureInfoContent, "#" + signatureConfig.getPackageSignatureId(),\r
                         "idOfficeV1Details");\r
 \r
         List<SignatureProperty> signaturePropertyContent = new ArrayList<SignatureProperty>();\r
index 420f575bd574aa8382c158b71d338a7704b2e945..67fe400dbacaf46c918c792e4665699568576aca 100644 (file)
@@ -54,12 +54,11 @@ import org.w3c.dom.NodeList;
 public class Office2010SignatureFacet implements SignatureFacet {\r
 \r
     @Override\r
-    public void preSign(Document document,\r
-        XMLSignatureFactory signatureFactory,\r
-        String signatureId,\r
-        List<X509Certificate> signingCertificateChain,\r
-        List<Reference> references,\r
-        List<XMLObject> objects\r
+    public void preSign(\r
+          Document document\r
+        , XMLSignatureFactory signatureFactory\r
+        , List<Reference> references\r
+        , List<XMLObject> objects\r
     ) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {\r
     }\r
 \r
index eafa3cd46193db3eee7806f2fb7627fa2b6d54ba..85b51de049a7c71ce924b2800e6ed12c463c3434 100644 (file)
@@ -66,8 +66,6 @@ public interface SignatureFacet {
     void preSign(\r
           Document document\r
         , XMLSignatureFactory signatureFactory\r
-        , String signatureId\r
-        , List<X509Certificate> signingCertificateChain\r
         , List<Reference> references\r
         , List<XMLObject> objects\r
     ) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException, URISyntaxException, XmlException;\r
diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignaturePolicyService.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignaturePolicyService.java
deleted file mode 100644 (file)
index d19fb8d..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/* ====================================================================\r
-   Licensed to the Apache Software Foundation (ASF) under one or more\r
-   contributor license agreements.  See the NOTICE file distributed with\r
-   this work for additional information regarding copyright ownership.\r
-   The ASF licenses this file to You under the Apache License, Version 2.0\r
-   (the "License"); you may not use this file except in compliance with\r
-   the License.  You may obtain a copy of the License at\r
-\r
-       http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-   Unless required by applicable law or agreed to in writing, software\r
-   distributed under the License is distributed on an "AS IS" BASIS,\r
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-   See the License for the specific language governing permissions and\r
-   limitations under the License.\r
-==================================================================== */\r
-\r
-/* ====================================================================\r
-   This product contains an ASLv2 licensed version of the OOXML signer\r
-   package from the eID Applet project\r
-   http://code.google.com/p/eid-applet/source/browse/trunk/README.txt  \r
-   Copyright (C) 2008-2014 FedICT.\r
-   ================================================================= */ \r
-\r
-package org.apache.poi.poifs.crypt.dsig.facets;\r
-\r
-/**\r
- * Interface for the signature policy service.\r
- * \r
- * @author Frank Cornelis\r
- * \r
- */\r
-public interface SignaturePolicyService {\r
-\r
-    /**\r
-     * Gives back the signature policy identifier URI.\r
-     * \r
-     * @return\r
-     */\r
-    String getSignaturePolicyIdentifier();\r
-\r
-    /**\r
-     * Gives back the short description of the signature policy or\r
-     * <code>null</code> if a description is not available.\r
-     * \r
-     * @return the description, or <code>null</code>.\r
-     */\r
-    String getSignaturePolicyDescription();\r
-\r
-    /**\r
-     * Gives back the download URL where the signature policy document can be\r
-     * found. Can be <code>null</code> in case such a download location does not\r
-     * exist.\r
-     * \r
-     * @return the download URL, or <code>null</code>.\r
-     */\r
-    String getSignaturePolicyDownloadUrl();\r
-\r
-    /**\r
-     * Gives back the signature policy document.\r
-     * \r
-     * @return the bytes of the signature policy document.\r
-     */\r
-    byte[] getSignaturePolicyDocument();\r
-}
\ No newline at end of file
index a93f199e79fba0ab74700956c3a5c9187c55602f..0a2f063f67ac06afd6f65f661c3f1aef9811bc68 100644 (file)
@@ -53,9 +53,11 @@ import org.apache.poi.poifs.crypt.CryptoFunctions;
 import org.apache.poi.poifs.crypt.HashAlgorithm;\r
 import org.apache.poi.poifs.crypt.dsig.SignatureInfo;\r
 import org.apache.poi.poifs.crypt.dsig.SignatureInfoConfig;\r
-import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;\r
+import org.apache.poi.poifs.crypt.dsig.services.SignaturePolicyService;\r
 import org.apache.poi.util.POILogFactory;\r
 import org.apache.poi.util.POILogger;\r
+import org.apache.xmlbeans.XmlCursor;\r
+import org.apache.xmlbeans.XmlObject;\r
 import org.apache.xmlbeans.XmlString;\r
 import org.etsi.uri.x01903.v13.AnyType;\r
 import org.etsi.uri.x01903.v13.CertIDListType;\r
@@ -134,8 +136,6 @@ public class XAdESSignatureFacet implements SignatureFacet {
     @Override\r
     public void preSign(Document document,\r
             XMLSignatureFactory signatureFactory,\r
-            String signatureId,\r
-            List<X509Certificate> signingCertificateChain,\r
             List<Reference> references, List<XMLObject> objects)\r
             throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {\r
         LOG.log(POILogger.DEBUG, "preSign");\r
@@ -143,13 +143,13 @@ public class XAdESSignatureFacet implements SignatureFacet {
         // QualifyingProperties\r
         QualifyingPropertiesDocument qualDoc = QualifyingPropertiesDocument.Factory.newInstance();\r
         QualifyingPropertiesType qualifyingProperties = qualDoc.addNewQualifyingProperties();\r
-        qualifyingProperties.setTarget("#" + signatureId);\r
+        qualifyingProperties.setTarget("#" + signatureConfig.getPackageSignatureId());\r
         \r
         // SignedProperties\r
         SignedPropertiesType signedProperties = qualifyingProperties.addNewSignedProperties();\r
         String signedPropertiesId = this.idSignedProperties;\r
         if (this.idSignedProperties == null) {\r
-            signedPropertiesId = signatureId + "-xades";\r
+            signedPropertiesId = signatureConfig.getPackageSignatureId() + "-xades";\r
         }\r
         signedProperties.setId(signedPropertiesId);\r
 \r
@@ -164,13 +164,13 @@ public class XAdESSignatureFacet implements SignatureFacet {
         signedSignatureProperties.setSigningTime(xmlGregorianCalendar);\r
 \r
         // SigningCertificate\r
-        if (null == signingCertificateChain\r
-                || signingCertificateChain.isEmpty()) {\r
+        if (signatureConfig.getSigningCertificateChain() == null\r
+            || signatureConfig.getSigningCertificateChain().isEmpty()) {\r
             throw new RuntimeException("no signing certificate chain available");\r
         }\r
         CertIDListType signingCertificates = signedSignatureProperties.addNewSigningCertificate();\r
         CertIDType certId = signingCertificates.addNewCert();\r
-        X509Certificate signingCertificate = signingCertificateChain.get(0);\r
+        X509Certificate signingCertificate = signatureConfig.getSigningCertificateChain().get(0);\r
         setCertID(certId, signingCertificate, this.signatureConfig.getDigestAlgo(), this.issuerNameNoReverseOrder);\r
 \r
         // ClaimedRole\r
@@ -181,7 +181,7 @@ public class XAdESSignatureFacet implements SignatureFacet {
             AnyType claimedRole = claimedRolesList.addNewClaimedRole();\r
             XmlString roleString = XmlString.Factory.newInstance();\r
             roleString.setStringValue(this.role);\r
-            SignatureInfo.insertXChild(claimedRole, roleString);\r
+            insertXChild(claimedRole, roleString);\r
         }\r
 \r
         // XAdES-EPES\r
@@ -208,7 +208,7 @@ public class XAdESSignatureFacet implements SignatureFacet {
                 AnyType sigPolicyQualifier = sigPolicyQualifiers.addNewSigPolicyQualifier();\r
                 XmlString spUriElement = XmlString.Factory.newInstance();\r
                 spUriElement.setStringValue(signaturePolicyDownloadUrl);\r
-                SignatureInfo.insertXChild(sigPolicyQualifier, spUriElement);\r
+                insertXChild(sigPolicyQualifier, spUriElement);\r
             }\r
         } else if (this.signaturePolicyImplied) {\r
             SignaturePolicyIdentifierType signaturePolicyIdentifier = \r
@@ -238,7 +238,7 @@ public class XAdESSignatureFacet implements SignatureFacet {
         // add XAdES ds:Object\r
         List<XMLStructure> xadesObjectContent = new ArrayList<XMLStructure>();\r
         Element qualDocEl = (Element)document.importNode(qualifyingProperties.getDomNode(), true);\r
-        XmlSignatureService.registerIdAttribute(qualDocEl.getElementsByTagName("SignedProperties"));\r
+        SignatureInfo.registerIdAttribute(qualDocEl.getElementsByTagName("SignedProperties"));\r
         qualDocEl.setAttributeNS(XmlNS, "xmlns:xd", "http://uri.etsi.org/01903/v1.3.2#");\r
         setPrefix(qualDocEl, "http://uri.etsi.org/01903/v1.3.2#", "xd");\r
         xadesObjectContent.add(new DOMStructure(qualDocEl));\r
@@ -376,4 +376,14 @@ public class XAdESSignatureFacet implements SignatureFacet {
         return map;\r
     }\r
 \r
+    protected static void insertXChild(XmlObject root, XmlObject child) {\r
+        XmlCursor rootCursor = root.newCursor();\r
+        rootCursor.toEndToken();\r
+        XmlCursor childCursor = child.newCursor();\r
+        childCursor.toNextToken();\r
+        childCursor.moveXml(rootCursor);\r
+        childCursor.dispose();\r
+        rootCursor.dispose();\r
+    }\r
+\r
 }
\ No newline at end of file
index 8d895bac17e08b930fad6fcc3e721c0d1b893a04..9b79afcda9df721eb21d2eec96127814c795e333 100644 (file)
@@ -25,6 +25,7 @@
 package org.apache.poi.poifs.crypt.dsig.facets;\r
 \r
 import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlDSigNS;\r
+import static org.apache.poi.poifs.crypt.dsig.facets.XAdESSignatureFacet.insertXChild;\r
 \r
 import java.io.ByteArrayInputStream;\r
 import java.io.ByteArrayOutputStream;\r
@@ -50,7 +51,6 @@ import javax.xml.crypto.dsig.XMLObject;
 import javax.xml.crypto.dsig.XMLSignatureFactory;\r
 \r
 import org.apache.poi.poifs.crypt.HashAlgorithm;\r
-import org.apache.poi.poifs.crypt.dsig.SignatureInfo;\r
 import org.apache.poi.poifs.crypt.dsig.services.RevocationData;\r
 import org.apache.poi.poifs.crypt.dsig.services.RevocationDataService;\r
 import org.apache.poi.poifs.crypt.dsig.services.TimeStampService;\r
@@ -221,7 +221,7 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
         // xadesv141::TimeStampValidationData\r
         if (tsaRevocationDataXadesT.hasRevocationDataEntries()) {\r
             ValidationDataType validationData = createValidationData(tsaRevocationDataXadesT);\r
-            SignatureInfo.insertXChild(unsignedSigProps, validationData);\r
+            insertXChild(unsignedSigProps, validationData);\r
         }\r
 \r
         if (null == this.revocationDataService) {\r
@@ -334,7 +334,7 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
                 this.c14nAlgoId, this.timeStampService);\r
         if (tsaRevocationDataXadesX1.hasRevocationDataEntries()) {\r
             ValidationDataType timeStampXadesX1ValidationData = createValidationData(tsaRevocationDataXadesX1);\r
-            SignatureInfo.insertXChild(unsignedSigProps, timeStampXadesX1ValidationData);\r
+            insertXChild(unsignedSigProps, timeStampXadesX1ValidationData);\r
         }\r
 \r
         // marshal XAdES-X\r
@@ -381,8 +381,6 @@ public class XAdESXLSignatureFacet implements SignatureFacet {
     @Override\r
     public void preSign(Document document,\r
             XMLSignatureFactory signatureFactory,\r
-            String signatureId,\r
-            List<X509Certificate> signingCertificateChain,\r
             List<Reference> references, List<XMLObject> objects)\r
             throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {\r
         // nothing to do here\r
diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/SignaturePolicyService.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/SignaturePolicyService.java
new file mode 100644 (file)
index 0000000..1dbe1b1
--- /dev/null
@@ -0,0 +1,65 @@
+/* ====================================================================\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to You under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+==================================================================== */\r
+\r
+/* ====================================================================\r
+   This product contains an ASLv2 licensed version of the OOXML signer\r
+   package from the eID Applet project\r
+   http://code.google.com/p/eid-applet/source/browse/trunk/README.txt  \r
+   Copyright (C) 2008-2014 FedICT.\r
+   ================================================================= */ \r
+\r
+package org.apache.poi.poifs.crypt.dsig.services;\r
+\r
+/**\r
+ * Interface for the signature policy service.\r
+ * \r
+ * @author Frank Cornelis\r
+ * \r
+ */\r
+public interface SignaturePolicyService {\r
+\r
+    /**\r
+     * Gives back the signature policy identifier URI.\r
+     * \r
+     * @return\r
+     */\r
+    String getSignaturePolicyIdentifier();\r
+\r
+    /**\r
+     * Gives back the short description of the signature policy or\r
+     * <code>null</code> if a description is not available.\r
+     * \r
+     * @return the description, or <code>null</code>.\r
+     */\r
+    String getSignaturePolicyDescription();\r
+\r
+    /**\r
+     * Gives back the download URL where the signature policy document can be\r
+     * found. Can be <code>null</code> in case such a download location does not\r
+     * exist.\r
+     * \r
+     * @return the download URL, or <code>null</code>.\r
+     */\r
+    String getSignaturePolicyDownloadUrl();\r
+\r
+    /**\r
+     * Gives back the signature policy document.\r
+     * \r
+     * @return the bytes of the signature policy document.\r
+     */\r
+    byte[] getSignaturePolicyDocument();\r
+}
\ No newline at end of file
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
deleted file mode 100644 (file)
index addeff9..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* ====================================================================\r
-   Licensed to the Apache Software Foundation (ASF) under one or more\r
-   contributor license agreements.  See the NOTICE file distributed with\r
-   this work for additional information regarding copyright ownership.\r
-   The ASF licenses this file to You under the Apache License, Version 2.0\r
-   (the "License"); you may not use this file except in compliance with\r
-   the License.  You may obtain a copy of the License at\r
-\r
-       http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-   Unless required by applicable law or agreed to in writing, software\r
-   distributed under the License is distributed on an "AS IS" BASIS,\r
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-   See the License for the specific language governing permissions and\r
-   limitations under the License.\r
-==================================================================== */\r
-\r
-/* ====================================================================\r
-   This product contains an ASLv2 licensed version of the OOXML signer\r
-   package from the eID Applet project\r
-   http://code.google.com/p/eid-applet/source/browse/trunk/README.txt  \r
-   Copyright (C) 2008-2014 FedICT.\r
-   ================================================================= */ \r
-\r
-package org.apache.poi.poifs.crypt.dsig.services;\r
-\r
-import java.io.IOException;\r
-import java.security.NoSuchAlgorithmException;\r
-import java.util.List;\r
-\r
-import javax.xml.crypto.MarshalException;\r
-import javax.xml.parsers.ParserConfigurationException;\r
-\r
-import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;\r
-import org.apache.xmlbeans.XmlException;\r
-import org.w3c.dom.Document;\r
-\r
-/**\r
- * Interface for signature service component.\r
- * \r
- * @author Frank Cornelis\r
- * \r
- */\r
-public interface SignatureService {\r
-\r
-    /**\r
-     * Pre-sign callback method. Depending on the configuration some parameters\r
-     * are passed. The returned value will be signed by the eID Applet.\r
-     * \r
-     * @param digestInfos\r
-     *            the optional list of digest infos.\r
-     * @return the digest to be signed.\r
-     * @throws NoSuchAlgorithmException\r
-     */\r
-    DigestInfo preSign(Document document, List<DigestInfo> digestInfos)\r
-    throws NoSuchAlgorithmException;\r
-\r
-    /**\r
-     * Post-sign callback method. Received the signature value. Depending on the\r
-     * configuration the signing certificate chain is also obtained.\r
-     * \r
-     * @param signatureValue\r
-     * @param signingCertificateChain\r
-     *            the optional chain of signing certificates.\r
-     */\r
-    void postSign(Document document, byte[] signatureValue)\r
-    throws IOException, MarshalException, ParserConfigurationException, XmlException;\r
-}\r
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
deleted file mode 100644 (file)
index 0501c47..0000000
+++ /dev/null
@@ -1,481 +0,0 @@
-/* ====================================================================\r
-   Licensed to the Apache Software Foundation (ASF) under one or more\r
-   contributor license agreements.  See the NOTICE file distributed with\r
-   this work for additional information regarding copyright ownership.\r
-   The ASF licenses this file to You under the Apache License, Version 2.0\r
-   (the "License"); you may not use this file except in compliance with\r
-   the License.  You may obtain a copy of the License at\r
-\r
-       http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-   Unless required by applicable law or agreed to in writing, software\r
-   distributed under the License is distributed on an "AS IS" BASIS,\r
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-   See the License for the specific language governing permissions and\r
-   limitations under the License.\r
-==================================================================== */\r
-\r
-/* ====================================================================\r
-   This product contains an ASLv2 licensed version of the OOXML signer\r
-   package from the eID Applet project\r
-   http://code.google.com/p/eid-applet/source/browse/trunk/README.txt  \r
-   Copyright (C) 2008-2014 FedICT.\r
-   ================================================================= */ \r
-\r
-package org.apache.poi.poifs.crypt.dsig.services;\r
-\r
-import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlDSigNS;\r
-import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.XmlNS;\r
-\r
-import java.io.ByteArrayOutputStream;\r
-import java.io.File;\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.net.MalformedURLException;\r
-import java.net.URISyntaxException;\r
-import java.security.InvalidAlgorithmParameterException;\r
-import java.security.MessageDigest;\r
-import java.security.NoSuchAlgorithmException;\r
-import java.security.NoSuchProviderException;\r
-import java.util.ArrayList;\r
-import java.util.Collections;\r
-import java.util.HashMap;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.UUID;\r
-\r
-import javax.xml.crypto.MarshalException;\r
-import javax.xml.crypto.URIDereferencer;\r
-import javax.xml.crypto.XMLStructure;\r
-import javax.xml.crypto.dsig.CanonicalizationMethod;\r
-import javax.xml.crypto.dsig.DigestMethod;\r
-import javax.xml.crypto.dsig.Manifest;\r
-import javax.xml.crypto.dsig.Reference;\r
-import javax.xml.crypto.dsig.SignatureMethod;\r
-import javax.xml.crypto.dsig.SignedInfo;\r
-import javax.xml.crypto.dsig.XMLObject;\r
-import javax.xml.crypto.dsig.XMLSignContext;\r
-import javax.xml.crypto.dsig.XMLSignatureFactory;\r
-import javax.xml.crypto.dsig.dom.DOMSignContext;\r
-import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;\r
-import javax.xml.parsers.ParserConfigurationException;\r
-import javax.xml.transform.TransformerException;\r
-import javax.xml.transform.TransformerFactoryConfigurationError;\r
-\r
-import org.apache.jcp.xml.dsig.internal.dom.DOMReference;\r
-import org.apache.jcp.xml.dsig.internal.dom.DOMSignedInfo;\r
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;\r
-import org.apache.poi.openxml4j.opc.OPCPackage;\r
-import org.apache.poi.openxml4j.opc.PackageNamespaces;\r
-import org.apache.poi.openxml4j.opc.PackagePart;\r
-import org.apache.poi.openxml4j.opc.PackagePartName;\r
-import org.apache.poi.openxml4j.opc.PackageRelationship;\r
-import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;\r
-import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;\r
-import org.apache.poi.openxml4j.opc.PackagingURIHelper;\r
-import org.apache.poi.openxml4j.opc.TargetMode;\r
-import org.apache.poi.poifs.crypt.CryptoFunctions;\r
-import org.apache.poi.poifs.crypt.HashAlgorithm;\r
-import org.apache.poi.poifs.crypt.dsig.SignatureInfo;\r
-import org.apache.poi.poifs.crypt.dsig.SignatureInfoConfig;\r
-import org.apache.poi.poifs.crypt.dsig.facets.SignatureFacet;\r
-import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;\r
-import org.apache.poi.util.POILogFactory;\r
-import org.apache.poi.util.POILogger;\r
-import org.apache.xml.security.signature.XMLSignature;\r
-import org.apache.xml.security.utils.Base64;\r
-import org.apache.xmlbeans.XmlException;\r
-import org.apache.xmlbeans.XmlOptions;\r
-import org.w3.x2000.x09.xmldsig.SignatureDocument;\r
-import org.w3c.dom.Document;\r
-import org.w3c.dom.Element;\r
-import org.w3c.dom.NodeList;\r
-import org.w3c.dom.events.Event;\r
-import org.w3c.dom.events.EventListener;\r
-import org.w3c.dom.events.EventTarget;\r
-import org.w3c.dom.events.MutationEvent;\r
-import org.xml.sax.SAXException;\r
-\r
-\r
-/**\r
- * Abstract base class for an XML Signature Service implementation.\r
- */\r
-public class XmlSignatureService implements SignatureService {\r
-    private static final POILogger LOG = POILogFactory.getLogger(XmlSignatureService.class);\r
-\r
-    protected SignatureInfoConfig signatureConfig;\r
-    \r
-    private String signatureNamespacePrefix;\r
-    private String signatureId = "idPackageSignature";\r
-    \r
-    /**\r
-     * Main constructor.\r
-     */\r
-    public XmlSignatureService(SignatureInfoConfig signatureConfig) {\r
-        this.signatureNamespacePrefix = null;\r
-        this.signatureConfig = signatureConfig;\r
-    }\r
-    \r
-    public SignatureInfoConfig getSignatureConfig() {\r
-        return signatureConfig;\r
-    }\r
-\r
-    /**\r
-     * Sets the signature Id attribute value used to create the XML signature. A\r
-     * <code>null</code> value will trigger an automatically generated signature\r
-     * Id.\r
-     * \r
-     * @param signatureId\r
-     */\r
-    protected void setSignatureId(String signatureId) {\r
-            this.signatureId = signatureId;\r
-    }\r
-\r
-    /**\r
-     * Sets the XML Signature namespace prefix to be used for signature\r
-     * creation. A <code>null</code> value will omit the prefixing.\r
-     * \r
-     * @param signatureNamespacePrefix\r
-     */\r
-    protected void setSignatureNamespacePrefix(String signatureNamespacePrefix) {\r
-        this.signatureNamespacePrefix = signatureNamespacePrefix;\r
-    }\r
-\r
-    /**\r
-     * Gives back the human-readable description of what the citizen will be\r
-     * signing. The default value is "XML Document". Override this method to\r
-     * provide the citizen with another description.\r
-     * \r
-     * @return\r
-     */\r
-    protected String getSignatureDescription() {\r
-        return "Office OpenXML Document";\r
-    }\r
-\r
-    /**\r
-     * Gives back the output stream to which to write the signed XML document.\r
-     * \r
-     * @return\r
-     */\r
-    // protected abstract OutputStream getSignedDocumentOutputStream();\r
-    @Override\r
-    public DigestInfo preSign(Document document, List<DigestInfo> digestInfos)\r
-    throws NoSuchAlgorithmException {\r
-        SignatureInfo.initXmlProvider();\r
-\r
-        LOG.log(POILogger.DEBUG, "preSign");\r
-        HashAlgorithm hashAlgo = this.signatureConfig.getDigestAlgo();\r
-\r
-        byte[] digestValue;\r
-        try {\r
-            digestValue = getXmlSignatureDigestValue(document, digestInfos);\r
-        } catch (Exception e) {\r
-            throw new RuntimeException("XML signature error: " + e.getMessage(), e);\r
-        }\r
-\r
-        String description = getSignatureDescription();\r
-        return new DigestInfo(digestValue, hashAlgo, description);\r
-    }\r
-\r
-    @Override\r
-    public void postSign(Document document, byte[] signatureValue)\r
-    throws IOException, MarshalException, ParserConfigurationException, XmlException {\r
-        LOG.log(POILogger.DEBUG, "postSign");\r
-        SignatureInfo.initXmlProvider();\r
-\r
-        /*\r
-         * Check ds:Signature node.\r
-         */\r
-        if (!signatureId.equals(document.getDocumentElement().getAttribute("Id"))) {\r
-            throw new RuntimeException("ds:Signature not found for @Id: " + signatureId);\r
-        }\r
-\r
-        /*\r
-         * Insert signature value into the ds:SignatureValue element\r
-         */\r
-        NodeList sigValNl = document.getElementsByTagNameNS(XmlDSigNS, "SignatureValue");\r
-        if (sigValNl.getLength() != 1) {\r
-            throw new RuntimeException("preSign has to be called before postSign");\r
-        }\r
-        sigValNl.item(0).setTextContent(Base64.encode(signatureValue));\r
-\r
-        /*\r
-         * Allow signature facets to inject their own stuff.\r
-         */\r
-        for (SignatureFacet signatureFacet : this.signatureConfig.getSignatureFacets()) {\r
-            signatureFacet.postSign(document, this.signatureConfig.getSigningCertificateChain());\r
-        }\r
-\r
-        registerIds(document);\r
-        writeDocument(document);\r
-    }\r
-\r
-    @SuppressWarnings("unchecked")\r
-    private byte[] getXmlSignatureDigestValue(Document document, List<DigestInfo> digestInfos)\r
-        throws ParserConfigurationException, NoSuchAlgorithmException,\r
-        InvalidAlgorithmParameterException, MarshalException,\r
-        javax.xml.crypto.dsig.XMLSignatureException,\r
-        TransformerFactoryConfigurationError, TransformerException,\r
-        IOException, SAXException, NoSuchProviderException, XmlException, URISyntaxException {\r
-\r
-        // it's necessary to explicitly set the mdssi namespace, but the sign() method has no\r
-        // normal way to interfere with, so we need to add the namespace under the hand ...\r
-        final EventTarget et = (EventTarget)document;\r
-        EventListener myModificationListener = new EventListener() {\r
-            @Override\r
-            public void handleEvent(Event e) {\r
-                if (e instanceof MutationEvent) {\r
-                    MutationEvent mutEvt = (MutationEvent)e;\r
-                    if (mutEvt.getTarget() instanceof Element) {\r
-                        Element el = (Element)mutEvt.getTarget();\r
-                        if ("idPackageObject".equals(el.getAttribute("Id"))) {\r
-                            et.removeEventListener("DOMSubtreeModified", this, false);\r
-                            el.setAttributeNS(XmlNS, "xmlns:mdssi", PackageNamespaces.DIGITAL_SIGNATURE);\r
-                        }\r
-                    }\r
-                }\r
-            }\r
-        };\r
-        \r
-        et.addEventListener("DOMSubtreeModified", myModificationListener, false);\r
-        \r
-        /*\r
-         * Signature context construction.\r
-         */\r
-        XMLSignContext xmlSignContext = new DOMSignContext(this.signatureConfig.getKey(), document);\r
-        URIDereferencer uriDereferencer = this.signatureConfig.getUriDereferencer();\r
-        if (null != uriDereferencer) {\r
-            xmlSignContext.setURIDereferencer(uriDereferencer);\r
-        }\r
-\r
-        xmlSignContext.putNamespacePrefix(\r
-                "http://schemas.openxmlformats.org/package/2006/digital-signature",\r
-                "mdssi");\r
-        \r
-        if (this.signatureNamespacePrefix != null) {\r
-            /*\r
-             * OOo doesn't like ds namespaces so per default prefixing is off.\r
-             */\r
-            xmlSignContext.putNamespacePrefix(XmlDSigNS, this.signatureNamespacePrefix);\r
-        }\r
-\r
-        XMLSignatureFactory signatureFactory = SignatureInfo.getSignatureFactory();\r
-\r
-        /*\r
-         * Add ds:References that come from signing client local files.\r
-         */\r
-        List<Reference> references = new ArrayList<Reference>();\r
-        addDigestInfosAsReferences(digestInfos, signatureFactory, references);\r
-\r
-        /*\r
-         * Invoke the signature facets.\r
-         */\r
-        String localSignatureId = this.signatureId;\r
-        if (localSignatureId == null) {\r
-            localSignatureId = "xmldsig-" + UUID.randomUUID().toString();\r
-        }\r
-        List<XMLObject> objects = new ArrayList<XMLObject>();\r
-        for (SignatureFacet signatureFacet : this.signatureConfig.getSignatureFacets()) {\r
-            LOG.log(POILogger.DEBUG, "invoking signature facet: " + signatureFacet.getClass().getSimpleName());\r
-            signatureFacet.preSign(document, signatureFactory, localSignatureId, this.signatureConfig.getSigningCertificateChain(), references, objects);\r
-        }\r
-\r
-        /*\r
-         * ds:SignedInfo\r
-         */\r
-        SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(getSignatureMethod(this.signatureConfig.getDigestAlgo()), null);\r
-        CanonicalizationMethod canonicalizationMethod = signatureFactory\r
-            .newCanonicalizationMethod(getCanonicalizationMethod(),\r
-            (C14NMethodParameterSpec) null);\r
-        SignedInfo signedInfo = signatureFactory.newSignedInfo(\r
-            canonicalizationMethod, signatureMethod, references);\r
-\r
-        /*\r
-         * JSR105 ds:Signature creation\r
-         */\r
-        String signatureValueId = localSignatureId + "-signature-value";\r
-        javax.xml.crypto.dsig.XMLSignature xmlSignature = signatureFactory\r
-            .newXMLSignature(signedInfo, null, objects, localSignatureId,\r
-            signatureValueId);\r
-\r
-        /*\r
-         * ds:Signature Marshalling.\r
-         */\r
-        xmlSignContext.setDefaultNamespacePrefix(this.signatureNamespacePrefix);\r
-        // xmlSignContext.putNamespacePrefix(PackageNamespaces.DIGITAL_SIGNATURE, "mdssi");\r
-        xmlSignature.sign(xmlSignContext);\r
-\r
-        registerIds(document);\r
-        \r
-        /*\r
-         * Completion of undigested ds:References in the ds:Manifests.\r
-         */\r
-        for (XMLObject object : objects) {\r
-            LOG.log(POILogger.DEBUG, "object java type: " + object.getClass().getName());\r
-            List<XMLStructure> objectContentList = object.getContent();\r
-            for (XMLStructure objectContent : objectContentList) {\r
-                LOG.log(POILogger.DEBUG, "object content java type: " + objectContent.getClass().getName());\r
-                if (!(objectContent instanceof Manifest)) continue;\r
-                Manifest manifest = (Manifest) objectContent;\r
-                List<Reference> manifestReferences = manifest.getReferences();\r
-                for (Reference manifestReference : manifestReferences) {\r
-                    if (manifestReference.getDigestValue() != null) continue;\r
-\r
-                    DOMReference manifestDOMReference = (DOMReference)manifestReference;\r
-                    manifestDOMReference.digest(xmlSignContext);\r
-                }\r
-            }\r
-        }\r
-\r
-        /*\r
-         * Completion of undigested ds:References.\r
-         */\r
-        List<Reference> signedInfoReferences = signedInfo.getReferences();\r
-        for (Reference signedInfoReference : signedInfoReferences) {\r
-            DOMReference domReference = (DOMReference)signedInfoReference;\r
-\r
-            // ds:Reference with external digest value\r
-            if (domReference.getDigestValue() != null) continue;\r
-            \r
-            domReference.digest(xmlSignContext);\r
-        }\r
-\r
-        /*\r
-         * Calculation of XML signature digest value.\r
-         */\r
-        DOMSignedInfo domSignedInfo = (DOMSignedInfo)signedInfo;\r
-        ByteArrayOutputStream dataStream = new ByteArrayOutputStream();\r
-        domSignedInfo.canonicalize(xmlSignContext, dataStream);\r
-        byte[] octets = dataStream.toByteArray();\r
-\r
-        /*\r
-         * TODO: we could be using DigestOutputStream here to optimize memory\r
-         * usage.\r
-         */\r
-\r
-        MessageDigest jcaMessageDigest = CryptoFunctions.getMessageDigest(this.signatureConfig.getDigestAlgo());\r
-        byte[] digestValue = jcaMessageDigest.digest(octets);\r
-        return digestValue;\r
-    }\r
-\r
-    /**\r
-     * the resulting document needs to be tweaked before it can be digested -\r
-     * this applies to the verification and signing step\r
-     *\r
-     * @param doc\r
-     */\r
-    public static void registerIds(Document doc) {\r
-        NodeList nl = doc.getElementsByTagNameNS(XmlDSigNS, "Object");\r
-        registerIdAttribute(nl);\r
-        nl = doc.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "SignedProperties");\r
-        registerIdAttribute(nl);\r
-    }\r
-    \r
-    public static void registerIdAttribute(NodeList nl) {\r
-        for (int i=0; i<nl.getLength(); i++) {\r
-            Element el = (Element)nl.item(i);\r
-            if (el.hasAttribute("Id")) {\r
-                el.setIdAttribute("Id", true);\r
-            }\r
-        }\r
-    }\r
-    \r
-    private void addDigestInfosAsReferences(List<DigestInfo> digestInfos, XMLSignatureFactory signatureFactory, List<Reference> references)\r
-    throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, MalformedURLException {\r
-        for (DigestInfo digestInfo : safe(digestInfos)) {\r
-            byte[] documentDigestValue = digestInfo.digestValue;\r
-\r
-            DigestMethod digestMethod = signatureFactory.newDigestMethod(\r
-                            digestInfo.hashAlgo.xmlSignUri, null);\r
-\r
-            String uri = new File(digestInfo.description).getName();\r
-\r
-            Reference reference = signatureFactory.newReference(uri,\r
-                            digestMethod, null, null, null, documentDigestValue);\r
-            references.add(reference);\r
-        }\r
-    }\r
-\r
-    private String getSignatureMethod(HashAlgorithm hashAlgo) {\r
-        if (null == hashAlgo) {\r
-            throw new RuntimeException("digest algo is null");\r
-        }\r
-\r
-        switch (hashAlgo) {\r
-        case sha1:   return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1;\r
-        case sha256: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256;\r
-        case sha384: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA384;\r
-        case sha512: return XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA512;\r
-        case ripemd160: return XMLSignature.ALGO_ID_MAC_HMAC_RIPEMD160;\r
-        default: break;\r
-        }\r
-\r
-        throw new RuntimeException("unsupported sign algo: " + hashAlgo);\r
-    }\r
-\r
-    protected String getCanonicalizationMethod() {\r
-        return CanonicalizationMethod.INCLUSIVE;\r
-    }\r
-\r
-    protected void writeDocument(Document document) throws IOException, XmlException {\r
-        XmlOptions xo = new XmlOptions();\r
-        Map<String,String> namespaceMap = new HashMap<String,String>();\r
-        for (SignatureFacet sf : this.signatureConfig.getSignatureFacets()) {\r
-            Map<String,String> sfm = sf.getNamespacePrefixMapping();\r
-            if (sfm != null) {\r
-                namespaceMap.putAll(sfm);\r
-            }\r
-        }\r
-        xo.setSaveSuggestedPrefixes(namespaceMap);\r
-        xo.setUseDefaultNamespace();\r
-\r
-        LOG.log(POILogger.DEBUG, "output signed Office OpenXML document");\r
-\r
-        /*\r
-         * Copy the original OOXML content to the signed OOXML package. During\r
-         * copying some files need to changed.\r
-         */\r
-        OPCPackage pkg = this.signatureConfig.getOpcPackage();\r
-\r
-        PackagePartName sigPartName, sigsPartName;\r
-        try {\r
-            // <Override PartName="/_xmlsignatures/sig1.xml" ContentType="application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml"/>\r
-            sigPartName = PackagingURIHelper.createPartName("/_xmlsignatures/sig1.xml");\r
-            // <Default Extension="sigs" ContentType="application/vnd.openxmlformats-package.digital-signature-origin"/>\r
-            sigsPartName = PackagingURIHelper.createPartName("/_xmlsignatures/origin.sigs");\r
-        } catch (InvalidFormatException e) {\r
-            throw new IOException(e);\r
-        }\r
-        \r
-        String sigContentType = "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml";\r
-        PackagePart sigPart = pkg.getPart(sigPartName);\r
-        if (sigPart == null) {\r
-            sigPart = pkg.createPart(sigPartName, sigContentType);\r
-        }\r
-        \r
-        OutputStream os = sigPart.getOutputStream();\r
-        SignatureDocument sigDoc = SignatureDocument.Factory.parse(document);\r
-        sigDoc.save(os, xo);\r
-        os.close();\r
-        \r
-        String sigsContentType = "application/vnd.openxmlformats-package.digital-signature-origin";\r
-        PackagePart sigsPart = pkg.getPart(sigsPartName);\r
-        if (sigsPart == null) {\r
-            // touch empty marker file\r
-            sigsPart = pkg.createPart(sigsPartName, sigsContentType);\r
-        }\r
-        \r
-        PackageRelationshipCollection relCol = pkg.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN);\r
-        for (PackageRelationship pr : relCol) {\r
-            pkg.removeRelationship(pr.getId());\r
-        }\r
-        pkg.addRelationship(sigsPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN);\r
-        \r
-        sigsPart.addRelationship(sigPartName, TargetMode.INTERNAL, PackageRelationshipTypes.DIGITAL_SIGNATURE);\r
-    }\r
-\r
-    @SuppressWarnings("unchecked")\r
-    public static <T> List<T> safe(List<T> other) {\r
-        return other == null ? Collections.EMPTY_LIST : other;\r
-    }\r
-}\r
index 4dfc0f46b050261dc11b1d3c636bb0bbc3ad65e1..2b9f8b7e7413bde8e851dd6f6ac51971ef153ff5 100644 (file)
@@ -67,7 +67,6 @@ import org.apache.poi.poifs.crypt.dsig.services.RevocationDataService;
 import org.apache.poi.poifs.crypt.dsig.services.TSPTimeStampService;\r
 import org.apache.poi.poifs.crypt.dsig.services.TimeStampService;\r
 import org.apache.poi.poifs.crypt.dsig.services.TimeStampServiceValidator;\r
-import org.apache.poi.poifs.crypt.dsig.services.XmlSignatureService;\r
 import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;\r
 import org.apache.poi.util.DocumentHelper;\r
 import org.apache.poi.util.IOUtils;\r
@@ -120,7 +119,10 @@ public class TestSignatureInfo {
         \r
         for (String testFile : testFiles) {\r
             OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ);\r
-            SignatureInfo si = new SignatureInfo(pkg);\r
+            SignatureInfoConfig sic = new SignatureInfoConfig();\r
+            sic.setOpcPackage(pkg);\r
+            SignatureInfo si = new SignatureInfo();\r
+            si.setSignatureConfig(sic);\r
             List<X509Certificate> result = si.getSigners();\r
             pkg.revert();\r
             pkg.close();\r
@@ -146,7 +148,10 @@ public class TestSignatureInfo {
         \r
         for (String testFile : testFiles) {\r
             OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ);\r
-            SignatureInfo si = new SignatureInfo(pkg);\r
+            SignatureInfoConfig sic = new SignatureInfoConfig();\r
+            sic.setOpcPackage(pkg);\r
+            SignatureInfo si = new SignatureInfo();\r
+            si.setSignatureConfig(sic);\r
             List<X509Certificate> result = si.getSigners();\r
 \r
             assertNotNull(result);\r
@@ -164,7 +169,10 @@ public class TestSignatureInfo {
     public void getMultiSigners() throws Exception {\r
         String testFile = "hello-world-signed-twice.docx";\r
         OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ);\r
-        SignatureInfo si = new SignatureInfo(pkg);\r
+        SignatureInfoConfig sic = new SignatureInfoConfig();\r
+        sic.setOpcPackage(pkg);\r
+        SignatureInfo si = new SignatureInfo();\r
+        si.setSignatureConfig(sic);\r
         List<X509Certificate> result = si.getSigners();\r
 \r
         assertNotNull(result);\r
@@ -189,12 +197,18 @@ public class TestSignatureInfo {
 \r
     @Test\r
     public void testSignSpreadsheetWithSignatureInfo() throws Exception {\r
+        initKeyPair("Test", "CN=Test");\r
         String testFile = "hello-world-unsigned.xlsx";\r
         OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE);\r
-        SignatureInfo si = new SignatureInfo(pkg);\r
-        initKeyPair("Test", "CN=Test");\r
+        SignatureInfoConfig sic = new SignatureInfoConfig();\r
+        sic.setOpcPackage(pkg);\r
+        sic.setKey(keyPair.getPrivate());\r
+        sic.setSigningCertificateChain(Collections.singletonList(x509));\r
+        sic.addDefaultFacets();\r
+        SignatureInfo si = new SignatureInfo();\r
+        si.setSignatureConfig(sic);\r
         // hash > sha1 doesn't work in excel viewer ...\r
-        si.confirmSignature(keyPair.getPrivate(), x509, HashAlgorithm.sha1);\r
+        si.confirmSignature();\r
         List<X509Certificate> signer = si.getSigners();\r
         assertEquals(1, signer.size());\r
         pkg.close();\r
@@ -223,7 +237,7 @@ public class TestSignatureInfo {
         certificateChain.add(x509);\r
         signatureConfig.setSigningCertificateChain(certificateChain);\r
         \r
-        signatureConfig.addSignatureFacet(new EnvelopedSignatureFacet());\r
+        signatureConfig.addSignatureFacet(new EnvelopedSignatureFacet(signatureConfig));\r
         signatureConfig.addSignatureFacet(new KeyInfoSignatureFacet(true, false, false));\r
         signatureConfig.addSignatureFacet(new XAdESSignatureFacet(signatureConfig));\r
         \r
@@ -274,12 +288,13 @@ public class TestSignatureInfo {
 \r
         XAdESXLSignatureFacet xadesXLSignatureFacet = new XAdESXLSignatureFacet(\r
                 timeStampService, revocationDataService);\r
-        XmlSignatureService testedInstance = new XmlSignatureService(signatureConfig);\r
+        SignatureInfo si = new SignatureInfo();\r
+        si.setSignatureConfig(signatureConfig);\r
         \r
         Document document = DocumentHelper.createDocument();\r
         \r
         // operate\r
-        DigestInfo digestInfo = testedInstance.preSign(document, null);\r
+        DigestInfo digestInfo = si.preSign(document, null);\r
 \r
         // verify\r
         assertNotNull(digestInfo);\r
@@ -297,10 +312,10 @@ public class TestSignatureInfo {
         assertNotNull(certDigest.getDigestValue());\r
 \r
         // Sign the received XML signature digest value.\r
-        byte[] signatureValue = SignatureInfo.signDigest(keyPair.getPrivate(), HashAlgorithm.sha1, digestInfo.digestValue);\r
+        byte[] signatureValue = si.signDigest(digestInfo.digestValue);\r
 \r
         // Operate: postSign\r
-        testedInstance.postSign(document, signatureValue);\r
+        si.postSign(document, signatureValue);\r
         \r
         DOMValidateContext domValidateContext = new DOMValidateContext(\r
                 KeySelector.singletonKeySelector(keyPair.getPublic()),\r
@@ -341,12 +356,13 @@ public class TestSignatureInfo {
         signatureConfig.setOpcPackage(pkgCopy);\r
         signatureConfig.addDefaultFacets();\r
         \r
-        XmlSignatureService signatureService = new XmlSignatureService(signatureConfig);\r
+        SignatureInfo si = new SignatureInfo();\r
+        si.setSignatureConfig(signatureConfig);\r
 \r
         Document document = DocumentHelper.createDocument();\r
 \r
         // operate\r
-        DigestInfo digestInfo = signatureService.preSign(document, null);\r
+        DigestInfo digestInfo = si.preSign(document, null);\r
 \r
         // verify\r
         assertNotNull(digestInfo);\r
@@ -357,13 +373,13 @@ public class TestSignatureInfo {
         assertNotNull(digestInfo.digestValue);\r
 \r
         // setup: key material, signature value\r
-        byte[] signatureValue = SignatureInfo.signDigest(keyPair.getPrivate(), HashAlgorithm.sha1, digestInfo.digestValue);\r
+        byte[] signatureValue = si.signDigest(digestInfo.digestValue);\r
         \r
         // operate: postSign\r
-        signatureService.postSign(document, signatureValue);\r
+        si.postSign(document, signatureValue);\r
 \r
         // verify: signature\r
-        SignatureInfo si = new SignatureInfo(pkgCopy);\r
+        si.getSignatureConfig().setOpcPackage(pkgCopy);\r
         List<X509Certificate> signers = si.getSigners();\r
         assertEquals(signerCount, signers.size());\r
 \r