You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ki...@apache.org on 2014/08/10 20:25:12 UTC

svn commit: r1617141 [2/5] - in /poi/branches/xml_signature: ./ src/java/org/apache/poi/poifs/crypt/ src/ooxml/java/org/apache/poi/openxml4j/opc/ src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ src/ooxml/java/org/apache/poi/poifs/crypt/dsig/ src/...

Added: poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java
URL: http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java?rev=1617141&view=auto
==============================================================================
--- poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java (added)
+++ poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/KeyInfoSignatureFacet.java Sun Aug 10 18:25:10 2014
@@ -0,0 +1,194 @@
+/* ====================================================================
+   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.facets;
+
+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.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.dsig.Reference;
+import javax.xml.crypto.dsig.XMLObject;
+import javax.xml.crypto.dsig.XMLSignatureFactory;
+import javax.xml.crypto.dsig.dom.DOMSignContext;
+import javax.xml.crypto.dsig.keyinfo.KeyInfo;
+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.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.Node;
+
+/**
+ * Signature Facet implementation that adds ds:KeyInfo to the XML signature.
+ * 
+ * @author Frank Cornelis
+ * 
+ */
+public class KeyInfoSignatureFacet implements SignatureFacet {
+
+    private static final POILogger LOG = POILogFactory.getLogger(KeyInfoSignatureFacet.class);
+
+    private final boolean includeEntireCertificateChain;
+
+    private final boolean includeIssuerSerial;
+
+    private final boolean includeKeyValue;
+
+    /**
+     * Main constructor.
+     * 
+     * @param includeEntireCertificateChain
+     * @param includeIssuerSerial
+     * @param includeKeyValue
+     */
+    public KeyInfoSignatureFacet(boolean includeEntireCertificateChain,
+            boolean includeIssuerSerial, boolean includeKeyValue) {
+        this.includeEntireCertificateChain = includeEntireCertificateChain;
+        this.includeIssuerSerial = includeIssuerSerial;
+        this.includeKeyValue = includeKeyValue;
+    }
+
+    public void postSign(SignatureType signatureElement,
+            List<X509Certificate> signingCertificateChain) {
+        LOG.log(POILogger.DEBUG, "postSign");
+
+        List<ObjectType> objList = signatureElement.getObjectList();
+        
+        /*
+         * 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();
+
+        /*
+         * 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<Object> x509DataObjects = new LinkedList<Object>();
+        X509Certificate signingCertificate = signingCertificateChain.get(0);
+
+        List<Object> keyInfoContent = new LinkedList<Object>();
+
+        if (this.includeKeyValue) {
+            KeyValue keyValue;
+            try {
+                keyValue = keyInfoFactory.newKeyValue(signingCertificate.getPublicKey());
+            } catch (KeyException e) {
+                throw new RuntimeException("key exception: " + e.getMessage(), e);
+            }
+            keyInfoContent.add(keyValue);
+        }
+
+        if (this.includeIssuerSerial) {
+            x509DataObjects.add(keyInfoFactory.newX509IssuerSerial(
+                    signingCertificate.getIssuerX500Principal().toString(),
+                    signingCertificate.getSerialNumber()));
+        }
+
+        if (this.includeEntireCertificateChain) {
+            for (X509Certificate certificate : signingCertificateChain) {
+                x509DataObjects.add(certificate);
+            }
+        } else {
+            x509DataObjects.add(signingCertificate);
+        }
+
+        if (false == 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);
+        }        
+
+        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;
+            }
+        };
+
+        DOMSignContext domSignContext = new DOMSignContext(key, signatureElement.getDomNode());
+        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);
+        }
+    }
+
+    public void preSign(XMLSignatureFactory signatureFactory,
+        String signatureId,
+        List<X509Certificate> signingCertificateChain,
+        List<Reference> references,
+        List<XMLObject> objects
+    ) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
+        // empty
+    }
+
+    public Map<String,String> getNamespacePrefixMapping() {
+        Map<String,String> map = new HashMap<String,String>();
+        // map.put("xd", "http://www.w3.org/2000/09/xmldsig#");
+        return map;
+    }
+
+}
\ No newline at end of file

Added: poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java
URL: http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java?rev=1617141&view=auto
==============================================================================
--- poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java (added)
+++ poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/OOXMLSignatureFacet.java Sun Aug 10 18:25:10 2014
@@ -0,0 +1,541 @@
+/* ====================================================================
+   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.facets;
+
+import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.setPrefix;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+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;
+import java.util.TimeZone;
+
+import javax.xml.crypto.XMLStructure;
+import javax.xml.crypto.dom.DOMStructure;
+import javax.xml.crypto.dsig.CanonicalizationMethod;
+import javax.xml.crypto.dsig.DigestMethod;
+import javax.xml.crypto.dsig.Manifest;
+import javax.xml.crypto.dsig.Reference;
+import javax.xml.crypto.dsig.SignatureProperties;
+import javax.xml.crypto.dsig.SignatureProperty;
+import javax.xml.crypto.dsig.Transform;
+import javax.xml.crypto.dsig.XMLObject;
+import javax.xml.crypto.dsig.XMLSignatureFactory;
+import javax.xml.crypto.dsig.spec.TransformParameterSpec;
+
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.openxml4j.opc.ContentTypes;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.openxml4j.opc.PackageNamespaces;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.openxml4j.opc.PackagePartName;
+import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
+import org.apache.poi.openxml4j.opc.PackagingURIHelper;
+import org.apache.poi.openxml4j.opc.TargetMode;
+import org.apache.poi.poifs.crypt.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.Element;
+import org.w3c.dom.Node;
+
+import com.microsoft.schemas.office.x2006.digsig.CTSignatureInfoV1;
+import com.microsoft.schemas.office.x2006.digsig.SignatureInfoV1Document;
+
+/**
+ * Office OpenXML Signature Facet implementation.
+ * 
+ * @author fcorneli
+ * @see http://msdn.microsoft.com/en-us/library/cc313071.aspx
+ */
+public class OOXMLSignatureFacet implements SignatureFacet {
+
+    private static final POILogger LOG = POILogFactory.getLogger(OOXMLSignatureFacet.class);
+
+    public static final String OOXML_DIGSIG_NS = "http://schemas.openxmlformats.org/package/2006/digital-signature";
+    public static final String OFFICE_DIGSIG_NS = "http://schemas.microsoft.com/office/2006/digsig";
+
+    private final XmlSignatureService signatureService;
+
+    private final Date clock;
+
+    private final HashAlgorithm hashAlgo;
+
+    /**
+     * Main constructor.
+     */
+    public OOXMLSignatureFacet(XmlSignatureService signatureService, Date clock, HashAlgorithm hashAlgo) {
+        this.signatureService = signatureService;
+        this.clock = (clock == null ? new Date() : clock);
+        this.hashAlgo = (hashAlgo == null ? HashAlgorithm.sha1 : hashAlgo);
+    }
+
+    public void preSign(XMLSignatureFactory signatureFactory,
+            String signatureId,
+            List<X509Certificate> signingCertificateChain,
+            List<Reference> references, List<XMLObject> objects)
+            throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
+        LOG.log(POILogger.DEBUG, "pre sign");
+        addManifestObject(signatureFactory, signatureId, references, objects);
+        addSignatureInfo(signatureFactory, signatureId, references, objects);
+    }
+
+    private void addManifestObject(XMLSignatureFactory signatureFactory,
+            String signatureId, List<Reference> references,
+            List<XMLObject> objects) throws NoSuchAlgorithmException,
+            InvalidAlgorithmParameterException {
+        Manifest manifest = constructManifest(signatureFactory);
+        String objectId = "idPackageObject"; // really has to be this value.
+        List<XMLStructure> objectContent = new LinkedList<XMLStructure>();
+        objectContent.add(manifest);
+
+        addSignatureTime(signatureFactory, signatureId, objectContent);
+
+        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);
+        references.add(reference);
+    }
+
+    private Manifest constructManifest(XMLSignatureFactory signatureFactory)
+    throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
+        List<Reference> manifestReferences = new ArrayList<Reference>();
+
+        try {
+            addManifestReferences(signatureFactory, manifestReferences);
+        } catch (Exception e) {
+            throw new RuntimeException("error: " + e.getMessage(), e);
+        }
+
+        return signatureFactory.newManifest(manifestReferences);
+    }
+
+    private void addManifestReferences(XMLSignatureFactory signatureFactory, List<Reference> manifestReferences)
+            throws IOException, NoSuchAlgorithmException,
+            InvalidAlgorithmParameterException, URISyntaxException, XmlException {
+
+        OPCPackage ooxml = this.signatureService.getOfficeOpenXMLDocument();
+        List<PackagePart> relsEntryNames = ooxml.getPartsByContentType(ContentTypes.RELATIONSHIPS_PART);
+
+
+        DigestMethod digestMethod = signatureFactory.newDigestMethod(this.hashAlgo.xmlSignUri, null);
+        Set<String> digestedPartNames = new HashSet<String>();
+        for (PackagePart pp : relsEntryNames) {
+            String baseUri = pp.getPartName().getName().replaceFirst("(.*)/_rels/.*", "$1");
+
+            PackageRelationshipCollection prc;
+            try {
+                prc = new PackageRelationshipCollection(ooxml);
+                prc.parseRelationshipsPart(pp);
+            } catch (InvalidFormatException e) {
+                throw new IOException("Invalid relationship descriptor: "+pp.getPartName().getName(), e);
+            }
+            
+            RelationshipTransformParameterSpec parameterSpec = new RelationshipTransformParameterSpec();
+            for (PackageRelationship relationship : prc) {
+                String relationshipType = relationship.getRelationshipType();
+                
+                if (TargetMode.EXTERNAL == relationship.getTargetMode()) {
+                    /*
+                     * ECMA-376 Part 2 - 3rd edition
+                     * 13.2.4.16 Manifest Element
+                     * "The producer shall not create a Manifest element that references any data outside of the package."
+                     */
+                    continue;
+                }
+
+                if (!isSignedRelationship(relationshipType)) continue;
+
+                parameterSpec.addRelationshipReference(relationship.getId());
+
+                // TODO: find a better way ...
+                String partName = baseUri + relationship.getTargetURI().toString();
+                partName = new URI(partName).normalize().getPath().replace('\\', '/');
+                LOG.log(POILogger.DEBUG, "part name: " + partName);
+                
+                String contentType;
+                try {
+                    PackagePartName relName = PackagingURIHelper.createPartName(partName);
+                    PackagePart pp2 = ooxml.getPart(relName);
+                    contentType = pp2.getContentType();
+                } catch (InvalidFormatException e) {
+                    throw new IOException(e);
+                }
+                if (relationshipType.endsWith("customXml")
+                    && !(contentType.equals("inkml+xml") || contentType.equals("text/xml"))) {
+                    LOG.log(POILogger.DEBUG, "skipping customXml with content type: " + contentType);
+                    continue;
+                }
+                
+                if (!digestedPartNames.contains(partName)) {
+                    // We only digest a part once.
+                    String uri = partName + "?ContentType=" + contentType;
+                    Reference reference = signatureFactory.newReference(uri, digestMethod);
+                    manifestReferences.add(reference);
+                    digestedPartNames.add(partName);
+                }
+            }
+            
+            if (parameterSpec.hasSourceIds()) {
+                List<Transform> transforms = new LinkedList<Transform>();
+                transforms.add(signatureFactory.newTransform(
+                        RelationshipTransformService.TRANSFORM_URI,
+                        parameterSpec));
+                transforms.add(signatureFactory.newTransform(
+                        CanonicalizationMethod.INCLUSIVE,
+                        (TransformParameterSpec) null));
+                String uri = pp.getPartName().getName()
+                    + "?ContentType=application/vnd.openxmlformats-package.relationships+xml";
+                Reference reference = signatureFactory.newReference(uri, digestMethod, transforms, null, null);
+                manifestReferences.add(reference);
+            }
+        }
+    }
+
+
+    private void addSignatureTime(XMLSignatureFactory signatureFactory,
+            String signatureId,
+            List<XMLStructure> objectContent) {
+        /*
+         * SignatureTime
+         */
+        DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+        fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
+        String nowStr = fmt.format(this.clock);
+        LOG.log(POILogger.DEBUG, "now: " + nowStr);
+
+        SignatureTimeDocument sigTime = SignatureTimeDocument.Factory.newInstance();
+        CTSignatureTime ctTime = sigTime.addNewSignatureTime();
+        ctTime.setFormat("YYYY-MM-DDThh:mm:ssTZD");
+        ctTime.setValue(nowStr);
+
+        // TODO: find better method to have xmlbeans + export the prefix
+        Node n = ctTime.getDomNode();
+        setPrefix(ctTime, PackageNamespaces.DIGITAL_SIGNATURE, "mdssi");
+        
+        List<XMLStructure> signatureTimeContent = new LinkedList<XMLStructure>();
+        signatureTimeContent.add(new DOMStructure(n));
+        SignatureProperty signatureTimeSignatureProperty = signatureFactory
+                .newSignatureProperty(signatureTimeContent, "#" + signatureId,
+                        "idSignatureTime");
+        List<SignatureProperty> signaturePropertyContent = new LinkedList<SignatureProperty>();
+        signaturePropertyContent.add(signatureTimeSignatureProperty);
+        SignatureProperties signatureProperties = signatureFactory
+                .newSignatureProperties(signaturePropertyContent,
+                        "id-signature-time-" + this.clock.getTime());
+        objectContent.add(signatureProperties);
+    }
+
+    private void addSignatureInfo(XMLSignatureFactory signatureFactory,
+            String signatureId, List<Reference> references,
+            List<XMLObject> objects) throws NoSuchAlgorithmException,
+            InvalidAlgorithmParameterException {
+        List<XMLStructure> objectContent = new LinkedList<XMLStructure>();
+
+        SignatureInfoV1Document sigV1 = SignatureInfoV1Document.Factory.newInstance();
+        CTSignatureInfoV1 ctSigV1 = sigV1.addNewSignatureInfoV1();
+        ctSigV1.setManifestHashAlgorithm("http://www.w3.org/2000/09/xmldsig#sha1");
+        Node n = ctSigV1.getDomNode();
+        ((Element)n).setAttributeNS(Constants.NamespaceSpecNS, "xmlns", "http://schemas.microsoft.com/office/2006/digsig");
+        
+        List<XMLStructure> signatureInfoContent = new LinkedList<XMLStructure>();
+        signatureInfoContent.add(new DOMStructure(n));
+        SignatureProperty signatureInfoSignatureProperty = signatureFactory
+                .newSignatureProperty(signatureInfoContent, "#" + signatureId,
+                        "idOfficeV1Details");
+
+        List<SignatureProperty> signaturePropertyContent = new LinkedList<SignatureProperty>();
+        signaturePropertyContent.add(signatureInfoSignatureProperty);
+        SignatureProperties signatureProperties = signatureFactory
+                .newSignatureProperties(signaturePropertyContent, null);
+        objectContent.add(signatureProperties);
+
+        String objectId = "idOfficeObject";
+        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);
+        references.add(reference);
+    }
+
+    public void postSign(SignatureType signatureElement,
+            List<X509Certificate> signingCertificateChain) {
+        // empty
+    }
+
+    public static String getRelationshipReferenceURI(String zipEntryName) {
+
+        return "/"
+                + zipEntryName
+                + "?ContentType=application/vnd.openxmlformats-package.relationships+xml";
+    }
+
+    public static String getResourceReferenceURI(String resourceName,
+            String contentType) {
+
+        return "/" + resourceName + "?ContentType=" + contentType;
+    }
+
+    public static String[] contentTypes = {
+
+            /*
+             * Word
+             */
+            "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
+            "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml",
+            "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
+            "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
+            "application/vnd.openxmlformats-officedocument.theme+xml",
+            "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml",
+            "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml",
+
+            /*
+             * Word 2010
+             */
+            "application/vnd.ms-word.stylesWithEffects+xml",
+
+            /*
+             * Excel
+             */
+            "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
+            "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml",
+            "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml",
+            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
+
+            /*
+             * Powerpoint
+             */
+            "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml",
+            "application/vnd.openxmlformats-officedocument.presentationml.slideLayout+xml",
+            "application/vnd.openxmlformats-officedocument.presentationml.slideMaster+xml",
+            "application/vnd.openxmlformats-officedocument.presentationml.slide+xml",
+            "application/vnd.openxmlformats-officedocument.presentationml.tableStyles+xml",
+
+            /*
+             * Powerpoint 2010
+             */
+            "application/vnd.openxmlformats-officedocument.presentationml.viewProps+xml",
+            "application/vnd.openxmlformats-officedocument.presentationml.presProps+xml" };
+
+    public static boolean isSignedRelationship(String relationshipType) {
+        LOG.log(POILogger.DEBUG, "relationship type: " + relationshipType);
+        for (String signedTypeExtension : signed) {
+            if (relationshipType.endsWith(signedTypeExtension)) {
+                return true;
+            }
+        }
+        if (relationshipType.endsWith("customXml")) {
+            LOG.log(POILogger.DEBUG, "customXml relationship type");
+            return true;
+        }
+        return false;
+    }
+
+    public Map<String,String> getNamespacePrefixMapping() {
+        Map<String,String> m = new HashMap<String,String>();
+        m.put("mdssi", OOXML_DIGSIG_NS);
+        m.put("xd", "http://uri.etsi.org/01903/v1.3.2#");
+        return m;
+    }
+
+    
+    /**
+     * Office 2010 list of signed types (extensions).
+     */
+    public static String[] signed = { "powerPivotData", //
+            "activeXControlBinary", //
+            "attachedToolbars", //
+            "connectorXml", //
+            "downRev", //
+            "functionPrototypes", //
+            "graphicFrameDoc", //
+            "groupShapeXml", //
+            "ink", //
+            "keyMapCustomizations", //
+            "legacyDiagramText", //
+            "legacyDocTextInfo", //
+            "officeDocument", //
+            "pictureXml", //
+            "shapeXml", //
+            "smartTags", //
+            "ui/altText", //
+            "ui/buttonSize", //
+            "ui/controlID", //
+            "ui/description", //
+            "ui/enabled", //
+            "ui/extensibility", //
+            "ui/helperText", //
+            "ui/imageID", //
+            "ui/imageMso", //
+            "ui/keyTip", //
+            "ui/label", //
+            "ui/lcid", //
+            "ui/loud", //
+            "ui/pressed", //
+            "ui/progID", //
+            "ui/ribbonID", //
+            "ui/showImage", //
+            "ui/showLabel", //
+            "ui/supertip", //
+            "ui/target", //
+            "ui/text", //
+            "ui/title", //
+            "ui/tooltip", //
+            "ui/userCustomization", //
+            "ui/visible", //
+            "userXmlData", //
+            "vbaProject", //
+            "wordVbaData", //
+            "wsSortMap", //
+            "xlBinaryIndex", //
+            "xlExternalLinkPath/xlAlternateStartup", //
+            "xlExternalLinkPath/xlLibrary", //
+            "xlExternalLinkPath/xlPathMissing", //
+            "xlExternalLinkPath/xlStartup", //
+            "xlIntlMacrosheet", //
+            "xlMacrosheet", //
+            "customData", //
+            "diagramDrawing", //
+            "hdphoto", //
+            "inkXml", //
+            "media", //
+            "slicer", //
+            "slicerCache", //
+            "stylesWithEffects", //
+            "ui/extensibility", //
+            "chartColorStyle", //
+            "chartLayout", //
+            "chartStyle", //
+            "dictionary", //
+            "timeline", //
+            "timelineCache", //
+            "aFChunk", //
+            "attachedTemplate", //
+            "audio", //
+            "calcChain", //
+            "chart", //
+            "chartsheet", //
+            "chartUserShapes", //
+            "commentAuthors", //
+            "comments", //
+            "connections", //
+            "control", //
+            "customProperty", //
+            "customXml", //
+            "diagramColors", //
+            "diagramData", //
+            "diagramLayout", //
+            "diagramQuickStyle", //
+            "dialogsheet", //
+            "drawing", //
+            "endnotes", //
+            "externalLink", //
+            "externalLinkPath", //
+            "font", //
+            "fontTable", //
+            "footer", //
+            "footnotes", //
+            "glossaryDocument", //
+            "handoutMaster", //
+            "header", //
+            "hyperlink", //
+            "image", //
+            "mailMergeHeaderSource", //
+            "mailMergeRecipientData", //
+            "mailMergeSource", //
+            "notesMaster", //
+            "notesSlide", //
+            "numbering", //
+            "officeDocument", //
+            "oleObject", //
+            "package", //
+            "pivotCacheDefinition", //
+            "pivotCacheRecords", //
+            "pivotTable", //
+            "presProps", //
+            "printerSettings", //
+            "queryTable", //
+            "recipientData", //
+            "settings", //
+            "sharedStrings", //
+            "sheetMetadata", //
+            "slide", //
+            "slideLayout", //
+            "slideMaster", //
+            "slideUpdateInfo", //
+            "slideUpdateUrl", //
+            "styles", //
+            "table", //
+            "tableSingleCells", //
+            "tableStyles", //
+            "tags", //
+            "theme", //
+            "themeOverride", //
+            "transform", //
+            "video", //
+            "viewProps", //
+            "volatileDependencies", //
+            "webSettings", //
+            "worksheet", //
+            "xmlMaps", //
+            "ctrlProp", //
+            "customData", //
+            "diagram", //
+            "diagramColorsHeader", //
+            "diagramLayoutHeader", //
+            "diagramQuickStyleHeader", //
+            "documentParts", //
+            "slicer", //
+            "slicerCache", //
+            "vmlDrawing" //
+    };
+}
\ No newline at end of file

Added: poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java
URL: http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java?rev=1617141&view=auto
==============================================================================
--- poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java (added)
+++ poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/Office2010SignatureFacet.java Sun Aug 10 18:25:10 2014
@@ -0,0 +1,101 @@
+/* ====================================================================
+   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.facets;
+
+import static org.apache.poi.poifs.crypt.dsig.facets.XAdESXLSignatureFacet.XADES_NAMESPACE;
+
+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.dsig.Reference;
+import javax.xml.crypto.dsig.XMLObject;
+import javax.xml.crypto.dsig.XMLSignatureFactory;
+import javax.xml.namespace.QName;
+
+import org.apache.xmlbeans.XmlException;
+import org.apache.xmlbeans.XmlObject;
+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.ObjectType;
+import org.w3.x2000.x09.xmldsig.SignatureType;
+
+/**
+ * Work-around for Office2010 to accept the XAdES-BES/EPES signature.
+ * 
+ * xades:UnsignedProperties/xades:UnsignedSignatureProperties needs to be
+ * present.
+ * 
+ * @author Frank Cornelis
+ * 
+ */
+public class Office2010SignatureFacet implements SignatureFacet {
+
+    public void preSign(XMLSignatureFactory signatureFactory,
+        String signatureId,
+        List<X509Certificate> signingCertificateChain,
+        List<Reference> references,
+        List<XMLObject> objects
+    ) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
+    }
+
+    public void postSign(SignatureType signatureElement, List<X509Certificate> signingCertificateChain) {
+        QualifyingPropertiesType qualProps = null;
+        
+        try {
+            // check for XAdES-BES
+            for (ObjectType ot : signatureElement.getObjectList()) {
+                XmlObject xo[] = ot.selectChildren(new QName(XADES_NAMESPACE, "QualifyingProperties"));
+                if (xo != null && xo.length > 0) {
+                    qualProps = QualifyingPropertiesType.Factory.parse(xo[0].getDomNode());
+                    break;
+                }
+            }
+        } catch (XmlException e) {
+            throw new RuntimeException("signature decoding error", e);
+        }        
+        
+        if (qualProps == null) {
+            throw new IllegalArgumentException("no XAdES-BES extension present");
+        }
+
+        // create basic XML container structure
+        UnsignedPropertiesType unsignedProps = qualProps.getUnsignedProperties();
+        if (unsignedProps == null) {
+            unsignedProps = qualProps.addNewUnsignedProperties();
+        }
+        UnsignedSignaturePropertiesType unsignedSigProps = unsignedProps.getUnsignedSignatureProperties();
+        if (unsignedSigProps == null) {
+            unsignedSigProps = unsignedProps.addNewUnsignedSignatureProperties();
+        }
+    }
+    
+    public Map<String,String> getNamespacePrefixMapping() {
+        return null;
+    }
+}
\ No newline at end of file

Added: poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java
URL: http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java?rev=1617141&view=auto
==============================================================================
--- poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java (added)
+++ poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignatureFacet.java Sun Aug 10 18:25:10 2014
@@ -0,0 +1,83 @@
+/* ====================================================================
+   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.facets;
+
+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.dsig.Reference;
+import javax.xml.crypto.dsig.XMLObject;
+import javax.xml.crypto.dsig.XMLSignatureFactory;
+
+import org.w3.x2000.x09.xmldsig.SignatureType;
+
+/**
+ * JSR105 Signature Facet interface.
+ * 
+ * @author Frank Cornelis
+ * 
+ */
+public interface SignatureFacet {
+
+    /**
+     * This method is being invoked by the XML signature service engine during
+     * pre-sign phase. Via this method a signature facet implementation can add
+     * signature facets to an XML signature.
+     * 
+     * @param signatureFactory
+     * @param document
+     * @param signatureId
+     * @param signingCertificateChain
+     *            the optional signing certificate chain
+     * @param references
+     * @param objects
+     * @throws InvalidAlgorithmParameterException
+     * @throws NoSuchAlgorithmException
+     */
+    void preSign(
+          XMLSignatureFactory signatureFactory
+        , String signatureId
+        , List<X509Certificate> signingCertificateChain
+        , List<Reference> references
+        , List<XMLObject> objects
+    ) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException;
+
+    /**
+     * This method is being invoked by the XML signature service engine during
+     * the post-sign phase. Via this method a signature facet can extend the XML
+     * signatures with for example key information.
+     * 
+     * @param signatureElement
+     * @param signingCertificateChain
+     */
+    void postSign(
+          SignatureType signatureElement
+        , List<X509Certificate> signingCertificateChain);
+    
+    Map<String,String> getNamespacePrefixMapping();
+}
\ No newline at end of file

Added: poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignaturePolicyService.java
URL: http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignaturePolicyService.java?rev=1617141&view=auto
==============================================================================
--- poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignaturePolicyService.java (added)
+++ poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/SignaturePolicyService.java Sun Aug 10 18:25:10 2014
@@ -0,0 +1,65 @@
+/* ====================================================================
+   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.facets;
+
+/**
+ * Interface for the signature policy service.
+ * 
+ * @author Frank Cornelis
+ * 
+ */
+public interface SignaturePolicyService {
+
+    /**
+     * Gives back the signature policy identifier URI.
+     * 
+     * @return
+     */
+    String getSignaturePolicyIdentifier();
+
+    /**
+     * Gives back the short description of the signature policy or
+     * <code>null</code> if a description is not available.
+     * 
+     * @return the description, or <code>null</code>.
+     */
+    String getSignaturePolicyDescription();
+
+    /**
+     * Gives back the download URL where the signature policy document can be
+     * found. Can be <code>null</code> in case such a download location does not
+     * exist.
+     * 
+     * @return the download URL, or <code>null</code>.
+     */
+    String getSignaturePolicyDownloadUrl();
+
+    /**
+     * Gives back the signature policy document.
+     * 
+     * @return the bytes of the signature policy document.
+     */
+    byte[] getSignaturePolicyDocument();
+}
\ No newline at end of file

Added: poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java
URL: http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java?rev=1617141&view=auto
==============================================================================
--- poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java (added)
+++ poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESSignatureFacet.java Sun Aug 10 18:25:10 2014
@@ -0,0 +1,385 @@
+/* ====================================================================
+   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.facets;
+
+import static org.apache.poi.poifs.crypt.dsig.SignatureInfo.setPrefix;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+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;
+
+import javax.xml.crypto.XMLStructure;
+import javax.xml.crypto.dom.DOMStructure;
+import javax.xml.crypto.dsig.CanonicalizationMethod;
+import javax.xml.crypto.dsig.DigestMethod;
+import javax.xml.crypto.dsig.Reference;
+import javax.xml.crypto.dsig.Transform;
+import javax.xml.crypto.dsig.XMLObject;
+import javax.xml.crypto.dsig.XMLSignatureFactory;
+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.util.POILogFactory;
+import org.apache.poi.util.POILogger;
+import org.apache.xmlbeans.XmlString;
+import org.etsi.uri.x01903.v13.AnyType;
+import org.etsi.uri.x01903.v13.CertIDListType;
+import org.etsi.uri.x01903.v13.CertIDType;
+import org.etsi.uri.x01903.v13.ClaimedRolesListType;
+import org.etsi.uri.x01903.v13.DataObjectFormatType;
+import org.etsi.uri.x01903.v13.DigestAlgAndValueType;
+import org.etsi.uri.x01903.v13.IdentifierType;
+import org.etsi.uri.x01903.v13.ObjectIdentifierType;
+import org.etsi.uri.x01903.v13.QualifyingPropertiesDocument;
+import org.etsi.uri.x01903.v13.QualifyingPropertiesType;
+import org.etsi.uri.x01903.v13.SigPolicyQualifiersListType;
+import org.etsi.uri.x01903.v13.SignaturePolicyIdType;
+import org.etsi.uri.x01903.v13.SignaturePolicyIdentifierType;
+import org.etsi.uri.x01903.v13.SignedDataObjectPropertiesType;
+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.Element;
+
+/**
+ * XAdES Signature Facet. Implements XAdES v1.4.1 which is compatible with XAdES
+ * v1.3.2. The implemented XAdES format is XAdES-BES/EPES. It's up to another
+ * part of the signature service to upgrade the XAdES-BES to a XAdES-X-L.
+ * 
+ * This implementation has been tested against an implementation that
+ * participated multiple ETSI XAdES plugtests.
+ * 
+ * @author Frank Cornelis
+ * @see http://en.wikipedia.org/wiki/XAdES
+ * 
+ */
+public class XAdESSignatureFacet implements SignatureFacet {
+
+    private static final POILogger LOG = POILogFactory.getLogger(XAdESSignatureFacet.class);
+
+    private static final String XADES_TYPE = "http://uri.etsi.org/01903#SignedProperties";
+    
+    private final Date clock;
+
+    private final HashAlgorithm hashAlgo;
+
+    private final SignaturePolicyService signaturePolicyService;
+
+    private String idSignedProperties;
+
+    private boolean signaturePolicyImplied;
+
+    private String role;
+
+    private boolean issuerNameNoReverseOrder = false;
+
+    private Map<String, String> dataObjectFormatMimeTypes;
+
+    /**
+     * Main constructor.
+     * 
+     * @param clock
+     *            the clock to be used for determining the xades:SigningTime,
+     *            defaults to now when null
+     * @param hashAlgo
+     *            the digest algorithm to be used for all required XAdES digest
+     *            operations. Possible values: "SHA-1", "SHA-256", or "SHA-512",
+     *            defaults to SHA-1 when null
+     * @param signaturePolicyService
+     *            the optional signature policy service used for XAdES-EPES.
+     */
+    public XAdESSignatureFacet(Date clock, HashAlgorithm hashAlgo,
+            SignaturePolicyService signaturePolicyService) {
+        this.clock = (clock == null ? new Date() : clock);
+        this.hashAlgo = (hashAlgo == null ? HashAlgorithm.sha1 : hashAlgo);
+        this.signaturePolicyService = signaturePolicyService;
+        this.dataObjectFormatMimeTypes = new HashMap<String, String>();
+    }
+
+    public void postSign(SignatureType signatureElement,
+            List<X509Certificate> signingCertificateChain) {
+        LOG.log(POILogger.DEBUG, "postSign");
+    }
+
+    public void preSign(XMLSignatureFactory signatureFactory,
+            String signatureId,
+            List<X509Certificate> signingCertificateChain,
+            List<Reference> references, List<XMLObject> objects)
+            throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
+        LOG.log(POILogger.DEBUG, "preSign");
+
+        // QualifyingProperties
+        QualifyingPropertiesDocument qualDoc = QualifyingPropertiesDocument.Factory.newInstance();
+        QualifyingPropertiesType qualifyingProperties = qualDoc.addNewQualifyingProperties();
+        qualifyingProperties.setTarget("#" + signatureId);
+        
+        // SignedProperties
+        SignedPropertiesType signedProperties = qualifyingProperties.addNewSignedProperties();
+        String signedPropertiesId;
+        if (null != this.idSignedProperties) {
+            signedPropertiesId = this.idSignedProperties;
+        } else {
+            signedPropertiesId = signatureId + "-xades";
+        }
+        signedProperties.setId(signedPropertiesId);
+
+        // SignedSignatureProperties
+        SignedSignaturePropertiesType signedSignatureProperties = signedProperties.addNewSignedSignatureProperties();
+
+        // SigningTime
+        Calendar xmlGregorianCalendar = Calendar.getInstance();
+        xmlGregorianCalendar.setTimeZone(TimeZone.getTimeZone("Z"));
+        xmlGregorianCalendar.setTime(this.clock);
+        xmlGregorianCalendar.clear(Calendar.MILLISECOND);
+        signedSignatureProperties.setSigningTime(xmlGregorianCalendar);
+
+        // SigningCertificate
+        if (null == signingCertificateChain
+                || signingCertificateChain.isEmpty()) {
+            throw new RuntimeException("no signing certificate chain available");
+        }
+        CertIDListType signingCertificates = signedSignatureProperties.addNewSigningCertificate();
+        CertIDType certId = signingCertificates.addNewCert();
+        X509Certificate signingCertificate = signingCertificateChain.get(0);
+        setCertID(certId, signingCertificate, this.hashAlgo, this.issuerNameNoReverseOrder);
+
+        // ClaimedRole
+        if (null != this.role && false == this.role.isEmpty()) {
+            SignerRoleType signerRole = signedSignatureProperties.addNewSignerRole();
+            signedSignatureProperties.setSignerRole(signerRole);
+            ClaimedRolesListType claimedRolesList = signerRole.addNewClaimedRoles();
+            AnyType claimedRole = claimedRolesList.addNewClaimedRole();
+            XmlString roleString = XmlString.Factory.newInstance();
+            roleString.setStringValue(this.role);
+            SignatureInfo.insertXChild(claimedRole, roleString);
+        }
+
+        // XAdES-EPES
+        if (null != this.signaturePolicyService) {
+            SignaturePolicyIdentifierType signaturePolicyIdentifier =
+                signedSignatureProperties.addNewSignaturePolicyIdentifier();
+            
+            SignaturePolicyIdType signaturePolicyId = signaturePolicyIdentifier.addNewSignaturePolicyId();
+
+            ObjectIdentifierType objectIdentifier = signaturePolicyId.addNewSigPolicyId();
+            objectIdentifier.setDescription(this.signaturePolicyService.getSignaturePolicyDescription());
+            
+            IdentifierType identifier = objectIdentifier.addNewIdentifier();
+            identifier.setStringValue(this.signaturePolicyService.getSignaturePolicyIdentifier());
+
+            byte[] signaturePolicyDocumentData = this.signaturePolicyService.getSignaturePolicyDocument();
+            DigestAlgAndValueType sigPolicyHash = signaturePolicyId.addNewSigPolicyHash();
+            setDigestAlgAndValue(sigPolicyHash, signaturePolicyDocumentData, this.hashAlgo);
+
+            String signaturePolicyDownloadUrl = this.signaturePolicyService
+                    .getSignaturePolicyDownloadUrl();
+            if (null != signaturePolicyDownloadUrl) {
+                SigPolicyQualifiersListType sigPolicyQualifiers = signaturePolicyId.addNewSigPolicyQualifiers(); 
+                AnyType sigPolicyQualifier = sigPolicyQualifiers.addNewSigPolicyQualifier();
+                XmlString spUriElement = XmlString.Factory.newInstance();
+                spUriElement.setStringValue(signaturePolicyDownloadUrl);
+                SignatureInfo.insertXChild(sigPolicyQualifier, spUriElement);
+            }
+        } else if (this.signaturePolicyImplied) {
+            SignaturePolicyIdentifierType signaturePolicyIdentifier = 
+                    signedSignatureProperties.addNewSignaturePolicyIdentifier();
+            signaturePolicyIdentifier.addNewSignaturePolicyImplied();
+        }
+
+        // DataObjectFormat
+        if (false == this.dataObjectFormatMimeTypes.isEmpty()) {
+            SignedDataObjectPropertiesType signedDataObjectProperties =
+                signedProperties.addNewSignedDataObjectProperties();
+
+            List<DataObjectFormatType> dataObjectFormats = signedDataObjectProperties
+                    .getDataObjectFormatList();
+            for (Map.Entry<String, String> dataObjectFormatMimeType : this.dataObjectFormatMimeTypes
+                    .entrySet()) {
+                DataObjectFormatType dataObjectFormat = DataObjectFormatType.Factory.newInstance();
+                dataObjectFormat.setObjectReference("#" + dataObjectFormatMimeType.getKey());
+                dataObjectFormat.setMimeType(dataObjectFormatMimeType.getValue());
+                dataObjectFormats.add(dataObjectFormat);
+            }
+        }
+
+        // marshall XAdES QualifyingProperties
+        // ((Element)qualifyingProperties.getSignedProperties().getDomNode()).setIdAttribute("Id", true);
+
+        // add XAdES ds:Object
+        List<XMLStructure> xadesObjectContent = new LinkedList<XMLStructure>();
+        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");
+        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<Transform> transforms = new LinkedList<Transform>();
+        Transform exclusiveTransform = signatureFactory
+                .newTransform(CanonicalizationMethod.INCLUSIVE,
+                        (TransformParameterSpec) null);
+        transforms.add(exclusiveTransform);
+        Reference reference = signatureFactory.newReference("#"
+                + signedPropertiesId, digestMethod, transforms, XADES_TYPE,
+                null);
+        references.add(reference);
+    }
+
+    /**
+     * Gives back the JAXB DigestAlgAndValue data structure.
+     * 
+     * @param data
+     * @param xadesObjectFactory
+     * @param xmldsigObjectFactory
+     * @param hashAlgo
+     * @return
+     */
+    protected static void setDigestAlgAndValue(
+            DigestAlgAndValueType digestAlgAndValue,
+            byte[] data,
+            HashAlgorithm hashAlgo) {
+        DigestMethodType digestMethod = digestAlgAndValue.addNewDigestMethod();
+        digestMethod.setAlgorithm(hashAlgo.xmlSignUri);
+        
+        MessageDigest messageDigest = CryptoFunctions.getMessageDigest(hashAlgo);
+        byte[] digestValue = messageDigest.digest(data);
+        digestAlgAndValue.setDigestValue(digestValue);
+    }
+
+    /**
+     * Gives back the JAXB CertID data structure.
+     * 
+     * @param certificate
+     * @param xadesObjectFactory
+     * @param xmldsigObjectFactory
+     * @param digestAlgorithm
+     * @return
+     */
+    protected static void setCertID(
+            CertIDType certId,
+            X509Certificate certificate,
+            HashAlgorithm digestAlgorithm, boolean issuerNameNoReverseOrder) {
+        X509IssuerSerialType issuerSerial = certId.addNewIssuerSerial();
+        String issuerName;
+        if (issuerNameNoReverseOrder) {
+            /*
+             * Make sure the DN is encoded using the same order as present
+             * within the certificate. This is an Office2010 work-around.
+             * Should be reverted back.
+             * 
+             * XXX: not correct according to RFC 4514.
+             */
+            // TODO: check if issuerName is different on getTBSCertificate
+            // issuerName = PrincipalUtil.getIssuerX509Principal(certificate).getName().replace(",", ", ");
+            issuerName = certificate.getIssuerDN().getName().replace(",", ", ");
+        } else {
+            issuerName = certificate.getIssuerX500Principal().toString();
+        }
+        issuerSerial.setX509IssuerName(issuerName);
+        issuerSerial.setX509SerialNumber(certificate.getSerialNumber());
+
+        byte[] encodedCertificate;
+        try {
+            encodedCertificate = certificate.getEncoded();
+        } catch (CertificateEncodingException e) {
+            throw new RuntimeException("certificate encoding error: "
+                    + e.getMessage(), e);
+        }
+        DigestAlgAndValueType certDigest = certId.addNewCertDigest(); 
+        setDigestAlgAndValue(certDigest, encodedCertificate, digestAlgorithm);
+    }
+
+    /**
+     * Adds a mime-type for the given ds:Reference (referred via its @URI). This
+     * information is added via the xades:DataObjectFormat element.
+     * 
+     * @param dsReferenceUri
+     * @param mimetype
+     */
+    public void addMimeType(String dsReferenceUri, String mimetype) {
+        this.dataObjectFormatMimeTypes.put(dsReferenceUri, mimetype);
+    }
+
+    /**
+     * Sets the Id that will be used on the SignedProperties element;
+     * 
+     * @param idSignedProperties
+     */
+    public void setIdSignedProperties(String idSignedProperties) {
+        this.idSignedProperties = idSignedProperties;
+    }
+
+    /**
+     * Sets the signature policy to implied.
+     * 
+     * @param signaturePolicyImplied
+     */
+    public void setSignaturePolicyImplied(boolean signaturePolicyImplied) {
+        this.signaturePolicyImplied = signaturePolicyImplied;
+    }
+
+    /**
+     * Sets the XAdES claimed role.
+     * 
+     * @param role
+     */
+    public void setRole(String role) {
+        this.role = role;
+    }
+
+    /**
+     * Work-around for Office 2010 IssuerName encoding.
+     * 
+     * @param reverseOrder
+     */
+    public void setIssuerNameNoReverseOrder(boolean reverseOrder) {
+        this.issuerNameNoReverseOrder = reverseOrder;
+    }
+
+
+    public Map<String,String> getNamespacePrefixMapping() {
+        Map<String,String> map = new HashMap<String,String>();
+        map.put("xd", "http://uri.etsi.org/01903/v1.3.2#");
+        return map;
+    }
+
+}
\ No newline at end of file

Added: poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java
URL: http://svn.apache.org/viewvc/poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java?rev=1617141&view=auto
==============================================================================
--- poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java (added)
+++ poi/branches/xml_signature/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/XAdESXLSignatureFacet.java Sun Aug 10 18:25:10 2014
@@ -0,0 +1,492 @@
+/* ====================================================================
+   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.facets;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.math.BigInteger;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CRLException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509CRL;
+import java.security.cert.X509Certificate;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.xml.crypto.dsig.CanonicalizationMethod;
+import javax.xml.crypto.dsig.Reference;
+import javax.xml.crypto.dsig.XMLObject;
+import javax.xml.crypto.dsig.XMLSignatureFactory;
+import javax.xml.namespace.QName;
+
+import org.apache.poi.poifs.crypt.HashAlgorithm;
+import org.apache.poi.poifs.crypt.dsig.HorribleProxy;
+import org.apache.poi.poifs.crypt.dsig.SignatureInfo;
+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.BasicOCSPRespIf;
+import org.apache.poi.poifs.crypt.dsig.HorribleProxies.CanonicalizerIf;
+import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DERIntegerIf;
+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.X509NameIf;
+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.XmlException;
+import org.apache.xmlbeans.XmlObject;
+import org.etsi.uri.x01903.v13.CRLIdentifierType;
+import org.etsi.uri.x01903.v13.CRLRefType;
+import org.etsi.uri.x01903.v13.CRLRefsType;
+import org.etsi.uri.x01903.v13.CRLValuesType;
+import org.etsi.uri.x01903.v13.CertIDListType;
+import org.etsi.uri.x01903.v13.CertIDType;
+import org.etsi.uri.x01903.v13.CertificateValuesType;
+import org.etsi.uri.x01903.v13.CompleteCertificateRefsType;
+import org.etsi.uri.x01903.v13.CompleteRevocationRefsType;
+import org.etsi.uri.x01903.v13.DigestAlgAndValueType;
+import org.etsi.uri.x01903.v13.EncapsulatedPKIDataType;
+import org.etsi.uri.x01903.v13.OCSPIdentifierType;
+import org.etsi.uri.x01903.v13.OCSPRefType;
+import org.etsi.uri.x01903.v13.OCSPRefsType;
+import org.etsi.uri.x01903.v13.OCSPValuesType;
+import org.etsi.uri.x01903.v13.QualifyingPropertiesType;
+import org.etsi.uri.x01903.v13.ResponderIDType;
+import org.etsi.uri.x01903.v13.RevocationValuesType;
+import org.etsi.uri.x01903.v13.UnsignedPropertiesType;
+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.ObjectType;
+import org.w3.x2000.x09.xmldsig.SignatureType;
+import org.w3.x2000.x09.xmldsig.SignatureValueType;
+import org.w3c.dom.Node;
+
+/**
+ * XAdES-X-L v1.4.1 signature facet. This signature facet implementation will
+ * upgrade a given XAdES-BES/EPES signature to XAdES-X-L.
+ * 
+ * We don't inherit from XAdESSignatureFacet as we also want to be able to use
+ * this facet out of the context of a signature creation. This signature facet
+ * assumes that the signature is already XAdES-BES/EPES compliant.
+ * 
+ * This implementation has been tested against an implementation that
+ * participated multiple ETSI XAdES plugtests.
+ * 
+ * @author Frank Cornelis
+ * @see XAdESSignatureFacet
+ */
+public class XAdESXLSignatureFacet implements SignatureFacet {
+
+    private static final POILogger LOG = POILogFactory.getLogger(XAdESXLSignatureFacet.class);
+
+    public static final String XADES_NAMESPACE = "http://uri.etsi.org/01903/v1.3.2#";
+
+    public static final String XADES141_NAMESPACE = "http://uri.etsi.org/01903/v1.4.1#";
+
+    private final TimeStampService timeStampService;
+
+    private String c14nAlgoId;
+
+    private final RevocationDataService revocationDataService;
+
+    private final CertificateFactory certificateFactory;
+
+    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.
+     * 
+     * @param timeStampService
+     *            the time-stamp service used for XAdES-T and XAdES-X.
+     * @param revocationDataService
+     *            the optional revocation data service used for XAdES-C and
+     *            XAdES-X-L. When <code>null</code> the signature will be
+     *            limited to XAdES-T only.
+     */
+    public XAdESXLSignatureFacet(TimeStampService timeStampService,
+            RevocationDataService revocationDataService) {
+        this(timeStampService, revocationDataService, HashAlgorithm.sha1);
+    }
+
+    /**
+     * Main constructor.
+     * 
+     * @param timeStampService
+     *            the time-stamp service used for XAdES-T and XAdES-X.
+     * @param revocationDataService
+     *            the optional revocation data service used for XAdES-C and
+     *            XAdES-X-L. When <code>null</code> the signature will be
+     *            limited to XAdES-T only.
+     * @param digestAlgorithm
+     *            the digest algorithm to be used for construction of the
+     *            XAdES-X-L elements.
+     */
+    public XAdESXLSignatureFacet(TimeStampService timeStampService,
+            RevocationDataService revocationDataService,
+            HashAlgorithm digestAlgorithm) {
+        this.c14nAlgoId = CanonicalizationMethod.EXCLUSIVE;
+        this.hashAlgo = digestAlgorithm;
+        this.timeStampService = timeStampService;
+        this.revocationDataService = revocationDataService;
+
+        try {
+            this.certificateFactory = CertificateFactory.getInstance("X.509");
+        } catch (CertificateException e) {
+            throw new RuntimeException("X509 JCA error: " + e.getMessage(), e);
+        }
+    }
+
+    public void setCanonicalizerAlgorithm(String c14nAlgoId) {
+        this.c14nAlgoId = c14nAlgoId;
+    }
+
+    public void postSign(SignatureType signatureElement,
+            List<X509Certificate> signingCertificateChain) {
+        LOG.log(POILogger.DEBUG, "XAdES-X-L post sign phase");
+
+        QualifyingPropertiesType qualProps = null;
+        
+        try {
+            // check for XAdES-BES
+            for (ObjectType ot : signatureElement.getObjectList()) {
+                XmlObject xo[] = ot.selectChildren(new QName(XADES_NAMESPACE, "QualifyingProperties"));
+                if (xo != null && xo.length > 0) {
+                    qualProps = QualifyingPropertiesType.Factory.parse(xo[0].getDomNode());
+                    break;
+                }
+            }
+        } catch (XmlException e) {
+            throw new RuntimeException("signature decoding error", e);
+        }
+        
+        if (qualProps == null) {
+            throw new IllegalArgumentException("no XAdES-BES extension present");
+        }
+
+        // create basic XML container structure
+        UnsignedPropertiesType unsignedProps = qualProps.getUnsignedProperties();
+        if (unsignedProps == null) {
+            unsignedProps = qualProps.addNewUnsignedProperties();
+        }
+        UnsignedSignaturePropertiesType unsignedSigProps = unsignedProps.getUnsignedSignatureProperties();
+        if (unsignedSigProps == null) {
+            unsignedSigProps = unsignedProps.addNewUnsignedSignatureProperties();
+        }
+        
+
+        // create the XAdES-T time-stamp
+        SignatureValueType svt = signatureElement.getSignatureValue();
+        
+        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);
+
+        // marshal the XAdES-T extension
+        unsignedSigProps.addNewSignatureTimeStamp().set(signatureTimeStamp);
+
+        // xadesv141::TimeStampValidationData
+        if (tsaRevocationDataXadesT.hasRevocationDataEntries()) {
+            ValidationDataType validationData = createValidationData(tsaRevocationDataXadesT);
+            SignatureInfo.insertXChild(unsignedSigProps, validationData);
+        }
+
+        if (null == this.revocationDataService) {
+            /*
+             * Without revocation data service we cannot construct the XAdES-C
+             * extension.
+             */
+            return;
+        }
+
+        // XAdES-C: complete certificate refs
+        CompleteCertificateRefsType completeCertificateRefs = 
+            unsignedSigProps.addNewCompleteCertificateRefs();
+
+        CertIDListType certIdList = completeCertificateRefs.addNewCertRefs();
+        for (int certIdx = 1; certIdx < signingCertificateChain.size(); certIdx++) {
+            /*
+             * We skip the signing certificate itself according to section
+             * 4.4.3.2 of the XAdES 1.4.1 specification.
+             */
+            X509Certificate certificate = signingCertificateChain.get(certIdx);
+            CertIDType certId = certIdList.addNewCert();
+            XAdESSignatureFacet.setCertID(certId, certificate, this.hashAlgo, false);
+        }
+
+        // XAdES-C: complete revocation refs
+        CompleteRevocationRefsType completeRevocationRefs = 
+            unsignedSigProps.addNewCompleteRevocationRefs();
+        RevocationData revocationData = this.revocationDataService
+                .getRevocationData(signingCertificateChain);
+        if (revocationData.hasCRLs()) {
+            CRLRefsType crlRefs = completeRevocationRefs.addNewCRLRefs();
+            completeRevocationRefs.setCRLRefs(crlRefs);
+
+            for (byte[] encodedCrl : revocationData.getCRLs()) {
+                CRLRefType crlRef = crlRefs.addNewCRLRef();
+                X509CRL crl;
+                try {
+                    crl = (X509CRL) this.certificateFactory
+                            .generateCRL(new ByteArrayInputStream(encodedCrl));
+                } catch (CRLException e) {
+                    throw new RuntimeException("CRL parse error: "
+                            + e.getMessage(), e);
+                }
+
+                CRLIdentifierType crlIdentifier = crlRef.addNewCRLIdentifier();
+                String issuerName = crl.getIssuerDN().getName().replace(",", ", ");
+                crlIdentifier.setIssuer(issuerName);
+                Calendar cal = Calendar.getInstance();
+                cal.setTime(crl.getThisUpdate());
+                crlIdentifier.setIssueTime(cal);
+                crlIdentifier.setNumber(getCrlNumber(crl));
+
+                DigestAlgAndValueType digestAlgAndValue = crlRef.addNewDigestAlgAndValue();
+                XAdESSignatureFacet.setDigestAlgAndValue(digestAlgAndValue, encodedCrl, this.hashAlgo);
+            }
+        }
+        if (revocationData.hasOCSPs()) {
+            OCSPRefsType ocspRefs = completeRevocationRefs.addNewOCSPRefs();
+            for (byte[] ocsp : revocationData.getOCSPs()) {
+                try {
+                    OCSPRefType ocspRef = ocspRefs.addNewOCSPRef();
+    
+                    DigestAlgAndValueType digestAlgAndValue = ocspRef.addNewDigestAlgAndValue();
+                    XAdESSignatureFacet.setDigestAlgAndValue(digestAlgAndValue, ocsp, this.hashAlgo);
+    
+                    OCSPIdentifierType ocspIdentifier = ocspRef.addNewOCSPIdentifier();
+                    
+                    OCSPRespIf ocspResp = HorribleProxy.newProxy(OCSPRespIf.class, ocsp);
+                    
+                    BasicOCSPRespIf basicOcspResp = ocspResp.getResponseObject();
+                    
+                    Calendar cal = Calendar.getInstance();
+                    cal.setTime(basicOcspResp.getProducedAt());
+                    ocspIdentifier.setProducedAt(cal);
+    
+                    ResponderIDType responderId = ocspIdentifier.addNewResponderID();
+    
+                    RespIDIf respId = basicOcspResp.getResponderId();
+                    ResponderIDIf ocspResponderId = respId.toASN1Object();
+                    DERTaggedObjectIf derTaggedObject = ocspResponderId.toASN1Object();
+                    if (2 == derTaggedObject.getTagNo()) {
+                        ASN1OctetStringIf keyHashOctetString = derTaggedObject.getObject$String();
+                        byte key[] = keyHashOctetString.getOctets();
+                        responderId.setByKey(key);
+                    } else {
+                        X509NameIf name = HorribleProxy.createProxy(X509NameIf.class, "getInstance", derTaggedObject.getObject$Object());
+                        String nameStr = name.toString$delegate();
+                        responderId.setByName(nameStr);
+                    }
+                } catch (Exception e) {
+                    throw new RuntimeException("OCSP decoding error: " + e.getMessage(), e);
+                }
+            }
+        }
+
+        // marshal XAdES-C
+
+        // XAdES-X Type 1 timestamp
+        
+        
+        
+        List<Node> timeStampNodesXadesX1 = new LinkedList<Node>();
+        timeStampNodesXadesX1.add(signatureElement.getDomNode());
+        timeStampNodesXadesX1.add(signatureTimeStamp.getDomNode());
+        timeStampNodesXadesX1.add(completeCertificateRefs.getDomNode());
+        timeStampNodesXadesX1.add(completeRevocationRefs.getDomNode());
+
+        RevocationData tsaRevocationDataXadesX1 = new RevocationData();
+        LOG.log(POILogger.DEBUG, "creating XAdES-X time-stamp");
+        XAdESTimeStampType timeStampXadesX1 = createXAdESTimeStamp(
+                timeStampNodesXadesX1, tsaRevocationDataXadesX1,
+                this.c14nAlgoId, this.timeStampService);
+        if (tsaRevocationDataXadesX1.hasRevocationDataEntries()) {
+            ValidationDataType timeStampXadesX1ValidationData = createValidationData(tsaRevocationDataXadesX1);
+            SignatureInfo.insertXChild(unsignedSigProps, timeStampXadesX1ValidationData);
+        }
+
+        // marshal XAdES-X
+
+        // XAdES-X-L
+        CertificateValuesType certificateValues = unsignedSigProps.addNewCertificateValues();
+        for (X509Certificate certificate : signingCertificateChain) {
+            EncapsulatedPKIDataType encapsulatedPKIDataType = certificateValues.addNewEncapsulatedX509Certificate();
+            try {
+                encapsulatedPKIDataType.setByteArrayValue(certificate.getEncoded());
+            } catch (CertificateEncodingException e) {
+                throw new RuntimeException("certificate encoding error: " + e.getMessage(), e);
+            }
+        }
+        
+        RevocationValuesType revocationValues = unsignedSigProps.addNewRevocationValues();
+        createRevocationValues(revocationValues, revocationData);
+
+        // marshal XAdES-X-L
+    }
+
+    public static byte[] getC14nValue(List<Node> nodeList, String c14nAlgoId) {
+        byte[] c14nValue = null;
+        try {
+            for (Node node : nodeList) {
+                /*
+                 * 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, "newInstance", c14nAlgoId);
+                ByteArrayOutputStream bos = new ByteArrayOutputStream();
+                bos.write(c14nValue);
+                bos.write(c14n.canonicalizeSubtree(node));
+                c14nValue = bos.toByteArray();
+            }
+        } catch (RuntimeException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new RuntimeException("c14n error: " + e.getMessage(), e);
+        }
+        return c14nValue;
+    }
+
+    public void preSign(XMLSignatureFactory signatureFactory,
+            String signatureId,
+            List<X509Certificate> signingCertificateChain,
+            List<Reference> references, List<XMLObject> objects)
+            throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
+        // nothing to do here
+    }
+
+    private BigInteger getCrlNumber(X509CRL crl) {
+        byte[] crlNumberExtensionValue = crl.getExtensionValue("2.5.29.20" /*CRLNumber*/);
+        if (null == crlNumberExtensionValue) {
+            return null;
+        }
+        try {
+            ASN1InputStreamIf asn1InputStream = HorribleProxy.newProxy(ASN1InputStreamIf.class, crlNumberExtensionValue);
+            ASN1OctetStringIf octetString = asn1InputStream.readObject$ASNString();
+            byte[] octets = octetString.getOctets();
+            asn1InputStream = HorribleProxy.newProxy(ASN1InputStreamIf.class, octets);
+            DERIntegerIf integer =  asn1InputStream.readObject$Integer();
+            BigInteger crlNumber = integer.getPositiveValue();
+            return crlNumber;
+        } catch (Exception e) {
+            throw new RuntimeException("I/O error: " + e.getMessage(), e);
+        }
+    }
+
+    public static XAdESTimeStampType createXAdESTimeStamp(
+            List<Node> nodeList,
+            RevocationData revocationData,
+            String c14nAlgoId,
+            TimeStampService timeStampService) {
+        byte[] c14nSignatureValueElement = getC14nValue(nodeList, c14nAlgoId);
+
+        return createXAdESTimeStamp(c14nSignatureValueElement, revocationData,
+                c14nAlgoId, timeStampService);
+    }
+
+    public static XAdESTimeStampType createXAdESTimeStamp(
+            byte[] data,
+            RevocationData revocationData,
+            String c14nAlgoId,
+            TimeStampService timeStampService) {
+        // create the time-stamp
+        byte[] timeStampToken;
+        try {
+            timeStampToken = timeStampService.timeStamp(data, revocationData);
+        } catch (Exception e) {
+            throw new RuntimeException("error while creating a time-stamp: "
+                    + e.getMessage(), e);
+        }
+
+        // create a XAdES time-stamp container
+        XAdESTimeStampType xadesTimeStamp = XAdESTimeStampType.Factory.newInstance();
+        xadesTimeStamp.setId("time-stamp-" + UUID.randomUUID().toString());
+        CanonicalizationMethodType c14nMethod = xadesTimeStamp.addNewCanonicalizationMethod();
+        c14nMethod.setAlgorithm(c14nAlgoId);
+
+        // embed the time-stamp
+        EncapsulatedPKIDataType encapsulatedTimeStamp = xadesTimeStamp.addNewEncapsulatedTimeStamp();
+        encapsulatedTimeStamp.setByteArrayValue(timeStampToken);
+        encapsulatedTimeStamp.setId("time-stamp-token-" + UUID.randomUUID().toString());
+
+        return xadesTimeStamp;
+    }
+
+    private ValidationDataType createValidationData(
+            RevocationData revocationData) {
+        ValidationDataType validationData = ValidationDataType.Factory.newInstance();
+        RevocationValuesType revocationValues = validationData.addNewRevocationValues();
+        createRevocationValues(revocationValues, revocationData);
+        return validationData;
+    }
+
+    private void createRevocationValues(
+            RevocationValuesType revocationValues, RevocationData revocationData) {
+        if (revocationData.hasCRLs()) {
+            CRLValuesType crlValues = revocationValues.addNewCRLValues();
+            for (byte[] crl : revocationData.getCRLs()) {
+                EncapsulatedPKIDataType encapsulatedCrlValue = crlValues.addNewEncapsulatedCRLValue();
+                encapsulatedCrlValue.setByteArrayValue(crl);
+            }
+        }
+        if (revocationData.hasOCSPs()) {
+            OCSPValuesType ocspValues = revocationValues.addNewOCSPValues();
+            for (byte[] ocsp : revocationData.getOCSPs()) {
+                EncapsulatedPKIDataType encapsulatedOcspValue = ocspValues.addNewEncapsulatedOCSPValue();
+                encapsulatedOcspValue.setByteArrayValue(ocsp);
+            }
+        }
+    }
+
+    public Map<String,String> getNamespacePrefixMapping() {
+        return null;
+    }
+
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org