]> source.dussan.org Git - poi.git/commitdiff
sync merge to trunk
authorAndreas Beeker <kiwiwings@apache.org>
Tue, 12 Aug 2014 23:33:07 +0000 (23:33 +0000)
committerAndreas Beeker <kiwiwings@apache.org>
Tue, 12 Aug 2014 23:33:07 +0000 (23:33 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/xml_signature@1617624 13f79535-47bb-0310-9956-ffa450edef68

1  2 
.classpath
.settings/org.sonar.ide.eclipse.core.prefs
build.xml
src/ooxml/java/org/apache/poi/openxml4j/opc/PackageRelationshipCollection.java
src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ContentTypeManager.java
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/HorribleProxies.java
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureInfo.java
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/facets/EnvelopedSignatureFacet.java
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/XmlSignatureService.java
src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java

diff --cc .classpath
index 8df184abf0f2cb8fbb6b2c3d71af31020df6cff9,a7dc0d8fc5dea3ab40f47db3e6fecd556b7533e4..bcce3b2c0d49c9290496fd4be8f51ba9eddee0fa
@@@ -1,30 -1,29 +1,30 @@@
--<?xml version="1.0" encoding="UTF-8"?>
--<classpath>
--      <classpathentry kind="src" path="src/java"/>
--      <classpathentry kind="src" path="src/testcases"/>
--      <classpathentry kind="src" path="src/resources/main"/>
--      <classpathentry kind="src" path="src/ooxml/java"/>
--      <classpathentry kind="src" path="src/ooxml/testcases"/>
--      <classpathentry kind="src" path="src/resources/ooxml"/>
--      <classpathentry kind="src" path="src/scratchpad/src"/>
--      <classpathentry kind="src" path="src/scratchpad/testcases"/>
--      <classpathentry kind="src" path="src/resources/scratchpad"/>
--      <classpathentry kind="src" path="src/contrib/poi-ruby/java"/>
--      <classpathentry kind="src" path="src/examples/src"/>
--      <classpathentry kind="src" path="src/excelant/java"/>
--      <classpathentry kind="src" path="src/excelant/testcases"/>
--      <classpathentry kind="src" path="src/excelant/resources"/>
--      <classpathentry kind="lib" path="lib/ant-1.9.4.jar"/>
--      <classpathentry kind="lib" path="lib/ant-launcher-1.9.4.jar"/>
--      <classpathentry kind="lib" path="lib/commons-codec-1.9.jar"/>
--      <classpathentry kind="lib" path="lib/commons-logging-1.1.3.jar"/>
--      <classpathentry kind="lib" path="lib/log4j-1.2.17.jar"/>
-       <classpathentry kind="lib" path="ooxml-lib/dom4j-1.6.1.jar"/>
--      <classpathentry kind="lib" path="ooxml-lib/xmlbeans-2.6.0.jar"/>
--      <classpathentry kind="lib" path="lib/hamcrest-core-1.3.jar"/>
--      <classpathentry kind="lib" path="lib/junit-4.11.jar"/>
--      <classpathentry kind="lib" path="ooxml-lib/ooxml-schemas-1.1.jar" sourcepath="ooxml-lib/ooxml-schemas-src-1.1.jar"/>
-       <classpathentry kind="lib" path="ooxml-lib/ooxml-encryption-1.2.jar" sourcepath="ooxml-lib/ooxml-encryption-src-1.2.jar"/>
 -      <classpathentry kind="lib" path="ooxml-lib/ooxml-encryption-1.1.jar" sourcepath="ooxml-lib/ooxml-encryption-src-1.1.jar"/>
--      <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
--      <classpathentry kind="output" path="build/eclipse"/>
--</classpath>
++<?xml version="1.0" encoding="UTF-8"?>\r
++<classpath>\r
++      <classpathentry kind="src" path="src/java"/>\r
++      <classpathentry kind="src" path="src/testcases"/>\r
++      <classpathentry kind="src" path="src/resources/main"/>\r
++      <classpathentry kind="src" path="src/ooxml/java"/>\r
++      <classpathentry kind="src" path="src/ooxml/testcases"/>\r
++      <classpathentry kind="src" path="src/resources/ooxml"/>\r
++      <classpathentry kind="src" path="src/scratchpad/src"/>\r
++      <classpathentry kind="src" path="src/scratchpad/testcases"/>\r
++      <classpathentry kind="src" path="src/resources/scratchpad"/>\r
++      <classpathentry kind="src" path="src/contrib/poi-ruby/java"/>\r
++      <classpathentry kind="src" path="src/examples/src"/>\r
++      <classpathentry kind="src" path="src/excelant/java"/>\r
++      <classpathentry kind="src" path="src/excelant/testcases"/>\r
++      <classpathentry kind="src" path="src/excelant/resources"/>\r
++      <classpathentry kind="lib" path="lib/ant-1.9.4.jar"/>\r
++      <classpathentry kind="lib" path="lib/ant-launcher-1.9.4.jar"/>\r
++      <classpathentry kind="lib" path="lib/commons-codec-1.9.jar"/>\r
++      <classpathentry kind="lib" path="lib/commons-logging-1.1.3.jar"/>\r
++      <classpathentry kind="lib" path="lib/log4j-1.2.17.jar"/>\r
++      <classpathentry kind="lib" path="ooxml-lib/xmlbeans-2.6.0.jar"/>\r
++      <classpathentry kind="lib" path="lib/hamcrest-core-1.3.jar"/>\r
++      <classpathentry kind="lib" path="lib/junit-4.11.jar"/>\r
++      <classpathentry kind="lib" path="ooxml-lib/ooxml-schemas-1.1.jar" sourcepath="ooxml-lib/ooxml-schemas-src-1.1.jar"/>\r
++      <classpathentry kind="lib" path="ooxml-lib/ooxml-encryption-1.2.jar" sourcepath="ooxml-lib/ooxml-encryption-src-1.2.jar"/>\r
++      <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>\r
++      <classpathentry kind="lib" path="lib/mockito-core-1.9.5.jar" sourcepath="E:/tmp/mavenRepo/org/mockito/mockito-core/1.9.5/mockito-core-1.9.5-sources.jar"/>\r
++      <classpathentry kind="output" path="build/eclipse"/>\r
++</classpath>\r
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..80551be6b141dd60f9612ba4451f4b53d91f7fc5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,6 @@@
++eclipse.preferences.version=1\r
++extraProperties=\r
++lastAnalysisDate=1394235544000\r
++projectKey=org.apache.poi\:poi-main\r
++serverUrl=http\://nemo.sonarqube.org\r
++version=2\r
diff --cc build.xml
index b2d15a9a2c2d15a1858099f4e74f2ad550fad0d3,3dbf0a81b8a31dbcf655d84f18f01a7b6ac28ce0..4423a7833d894b4f8a60b03c0ebe496b3cbe32a4
+++ b/build.xml
@@@ -1465,9 -1436,8 +1454,8 @@@ under the License
                                <exclude name="poi-*${version.id}-sources-*.jar"/>
                        </fileset>
                        <auxClasspath path="ooxml-lib/ooxml-schemas-1.1.jar" />
 -                      <auxClasspath path="ooxml-lib/ooxml-encryption-1.1.jar" />
 +                      <auxClasspath path="ooxml-lib/ooxml-encryption-1.2.jar" />
                        <auxClasspath path="ooxml-lib/xmlbeans-2.6.0.jar" />
-                       <auxClasspath path="ooxml-lib/dom4j-1.6.1.jar" />
                        <auxClasspath path="lib/commons-codec-1.9.jar" />
                        <auxClasspath path="lib/commons-logging-1.1.3.jar" />
                        <auxClasspath path="lib/junit-4.11.jar" />
index 54a5aad3255a9e6e1b22c2536a81ef4ef4390f1e,0000000000000000000000000000000000000000..96395b3d08ae87e6c94e44dbbac2d13ca2b4459d
mode 100644,000000..100644
--- /dev/null
@@@ -1,375 -1,0 +1,376 @@@
 +package org.apache.poi.poifs.crypt.dsig;\r
 +\r
 +import java.io.ByteArrayOutputStream;\r
 +import java.io.IOException;\r
 +import java.math.BigInteger;\r
 +import java.security.PrivateKey;\r
 +import java.security.PublicKey;\r
 +import java.security.cert.Certificate;\r
 +import java.security.cert.X509CRL;\r
 +import java.security.cert.X509Certificate;\r
 +import java.util.Collection;\r
 +import java.util.Date;\r
 +\r
 +import javax.security.auth.x500.X500Principal;\r
 +import javax.xml.crypto.MarshalException;\r
 +import javax.xml.crypto.XMLCryptoContext;\r
 +import javax.xml.crypto.dom.DOMCryptoContext;\r
 +import javax.xml.crypto.dsig.XMLSignContext;\r
 +import javax.xml.crypto.dsig.XMLSignatureException;\r
 +\r
 +import org.apache.poi.poifs.crypt.dsig.HorribleProxy.ProxyIf;\r
 +import org.w3c.dom.Node;\r
 +\r
 +public interface HorribleProxies {\r
 +    public static final String xmlSecBase = "org.jcp.xml.dsig.internal.dom";\r
 +    // public static final String xmlSecBase = "org.apache.jcp.xml.dsig.internal.dom";\r
 +    \r
 +    public interface ASN1InputStreamIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.ASN1InputStream";\r
 +        \r
 +        ASN1OctetStringIf readObject$ASNString() throws IOException;\r
 +        DEROctetStringIf readObject$DERString() throws IOException;\r
 +        DERIntegerIf readObject$Integer() throws IOException;\r
 +        ASN1SequenceIf readObject$Sequence() throws IOException;\r
 +        Object readObject$Object() throws IOException;\r
 +    }\r
 +\r
 +    public interface ASN1ObjectIdentifierIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.ASN1ObjectIdentifier";\r
 +    }\r
 +    \r
 +    public interface ASN1OctetStringIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.ASN1OctetString";\r
 +        byte[] getOctets();\r
 +    }\r
 +    \r
 +    public interface ASN1SequenceIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.ASN1Sequence";\r
 +    }\r
 +    \r
 +    public interface AuthorityInformationAccessIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.x509.AuthorityInformationAccess";\r
 +    }\r
 +    \r
 +    public interface AuthorityKeyIdentifierIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.x509.AuthorityKeyIdentifier";\r
 +        byte[] getKeyIdentifier();\r
 +    }\r
 +    \r
 +    public interface BasicConstraintsIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.x509.BasicConstraints";\r
 +    }\r
 +    \r
 +    public interface BasicOCSPRespIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.cert.ocsp.BasicOCSPResp";\r
 +        Date getProducedAt();\r
 +        RespIDIf getResponderId();\r
 +    }\r
 +    \r
 +    public interface BcDigestCalculatorProviderIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.operator.bc.BcDigestCalculatorProvider";\r
 +    }\r
 +\r
 +    public interface BcRSASignerInfoVerifierBuilderIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.cms.bc.BcRSASignerInfoVerifierBuilder";\r
 +        SignerInformationVerifierIf build(X509CertificateHolderIf holder); \r
 +    }\r
 +    \r
 +    public interface CanonicalizerIf extends ProxyIf {\r
 +        String delegateClass = "com.sun.org.apache.xml.internal.security.c14n.Canonicalizer";\r
 +        byte[] canonicalizeSubtree(Node node) throws Exception;\r
 +    }\r
 +    \r
 +    public interface CRLNumberIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.x509.CRLNumber";\r
 +    }\r
 +    \r
 +    public interface DefaultDigestAlgorithmIdentifierFinderIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder";\r
 +    }\r
 +    \r
 +    public interface DistributionPointNameIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.x509.DistributionPointName";\r
 +    }\r
 +    \r
 +    public interface DistributionPointIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.x509.DistributionPoint";\r
 +    }\r
 +    \r
 +    public interface DERIA5StringIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.DERIA5String";\r
 +    }\r
 +    \r
 +    public interface DERIntegerIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.DERInteger";\r
 +        BigInteger getPositiveValue();\r
 +    }\r
 +    \r
 +    public interface DEROctetStringIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.DEROctetString";\r
 +        byte[] getOctets();\r
 +    }\r
 +    \r
 +    public interface DERTaggedObjectIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.DERTaggedObject";\r
 +        int getTagNo();\r
 +        ASN1OctetStringIf getObject$String();\r
 +        Object getObject$Object();\r
 +    }\r
 +\r
 +    public interface DERSequenceIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.DERSequence";\r
 +    }\r
 +    \r
 +    public interface DOMKeyInfoIf extends ProxyIf {\r
 +        String delegateClass = xmlSecBase+".DOMKeyInfo";\r
 +        void marshal(Node parent, Node nextSibling, String dsPrefix, DOMCryptoContext context) throws MarshalException;\r
 +    }\r
 +    \r
 +    public interface DOMReferenceIf extends ProxyIf {\r
 +        String delegateClass = xmlSecBase+".DOMReference";\r
 +        void digest(XMLSignContext paramXMLSignContext) throws XMLSignatureException;\r
 +        byte[] getDigestValue();\r
 +    }\r
 +    \r
 +    public interface DOMSignedInfoIf extends ProxyIf {\r
 +        String delegateClass = xmlSecBase+".DOMSignedInfo";\r
 +        void canonicalize(XMLCryptoContext paramXMLCryptoContext, ByteArrayOutputStream paramByteArrayOutputStream);\r
 +    }\r
 +    \r
 +    public interface XMLSignatureIf extends ProxyIf {\r
 +        String delegateClass = "com.sun.org.apache.xml.internal.security.signature.XMLSignature";\r
 +        String ALGO_ID_SIGNATURE_RSA_SHA1();\r
 +        String ALGO_ID_SIGNATURE_RSA_SHA256();\r
 +        String ALGO_ID_SIGNATURE_RSA_SHA384();\r
 +        String ALGO_ID_SIGNATURE_RSA_SHA512();\r
 +        String ALGO_ID_MAC_HMAC_RIPEMD160();\r
 +    }\r
 +    \r
 +    public interface DOMXMLSignatureIf extends ProxyIf {\r
 +        String delegateClass = xmlSecBase+".DOMXMLSignature";\r
 +        void marshal(Node node, String prefix, DOMCryptoContext context) throws MarshalException;\r
 +    }\r
 +    \r
 +    public interface GeneralNameIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.x509.GeneralName";\r
 +        \r
 +        int uniformResourceIdentifier();\r
 +        \r
 +    }\r
 +    \r
 +    public interface GeneralNamesIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.x509.GeneralNames";\r
 +    }\r
 +    \r
 +    public interface InitIf extends ProxyIf {\r
 +        String delegateClass = "com.sun.org.apache.xml.internal.security.Init";\r
 +        void init();\r
 +    }\r
 +\r
 +    public interface KeyUsageIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.x509.KeyUsage";\r
 +        int digitalSignature();\r
 +    }\r
 +    \r
 +    public interface OCSPRespIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.cert.ocsp.OCSPResp";\r
 +        BasicOCSPRespIf getResponseObject();\r
++        byte[] getEncoded() throws IOException;\r
 +    }\r
 +    \r
 +    public interface PKIFailureInfoIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.cmp.PKIFailureInfo";\r
 +        int intValue();\r
 +    }\r
 +\r
 +    public interface RespIDIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.cert.ocsp.RespID";\r
 +        ResponderIDIf toASN1Object();\r
 +    }\r
 +    \r
 +    public interface ResponderIDIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.ocsp.ResponderID";\r
 +        DERTaggedObjectIf toASN1Object();\r
 +    }\r
 +\r
 +    public interface SignerIdIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.cms.SignerId";\r
 +        BigInteger getSerialNumber();\r
 +        X500Principal getIssuer();\r
 +    }\r
 +\r
 +    public interface SignerInformationVerifierIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.cms.SignerInformationVerifier";\r
 +    }\r
 +    \r
 +    public interface StoreIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.util.Store";\r
 +        Collection<Certificate> getMatches(Object selector) throws Exception;\r
 +    }\r
 +    \r
 +    public interface SubjectKeyIdentifierIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.x509.SubjectKeyIdentifier";\r
 +        byte[] getKeyIdentifier();\r
 +    }\r
 +    \r
 +    public interface SubjectPublicKeyInfoIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.x509.SubjectPublicKeyInfo";\r
 +    }\r
 +    \r
 +    public interface TimeStampRequestGeneratorIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.tsp.TimeStampRequestGenerator";\r
 +        void setCertReq(boolean certReq);\r
 +        void setReqPolicy(String reqPolicy);\r
 +        TimeStampRequestIf generate(String igestAlgorithmOID, byte[] digest, BigInteger nonce);\r
 +    }\r
 +    \r
 +    public interface TimeStampRequestIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.tsp.TimeStampRequest";\r
 +        byte[] getEncoded() throws IOException;\r
 +    }\r
 +    \r
 +    public interface TimeStampResponseIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.tsp.TimeStampResponse";\r
 +        void validate(TimeStampRequestIf request) throws Exception;\r
 +        int getStatus();\r
 +        String getStatusString();\r
 +        PKIFailureInfoIf getFailInfo();\r
 +        TimeStampTokenIf getTimeStampToken();\r
 +    }\r
 +    \r
 +    public interface TimeStampTokenIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.tsp.TimeStampToken";\r
 +        SignerIdIf getSID();\r
 +        StoreIf getCertificates();\r
 +        StoreIf getCRLs();\r
 +        TimeStampTokenInfoIf getTimeStampInfo();\r
 +        byte[] getEncoded() throws IOException;\r
 +        void validate(SignerInformationVerifierIf verifier) throws Exception;\r
 +    }\r
 +    \r
 +    public interface TimeStampTokenInfoIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.tsp.TimeStampTokenInfo";\r
 +        Date getGenTime();\r
 +    }\r
 +    \r
 +    public interface X509CertificateHolderIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.cert.X509CertificateHolder";\r
 +    }\r
 +\r
 +    public interface X509NameIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.x509.X509Name";\r
 +        String toString$delegate();\r
 +    }\r
 +\r
 +    public interface X509PrincipalIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.jce.X509Principal";\r
 +        String getName();\r
 +    }\r
 +    \r
 +    public interface X509V3CertificateGeneratorIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.x509.X509V3CertificateGenerator";\r
 +        \r
 +        void reset();\r
 +        void setPublicKey(PublicKey key);\r
 +        void setSignatureAlgorithm(String signatureAlgorithm);\r
 +        void setNotBefore(Date date);\r
 +        void setNotAfter(Date date);\r
 +        void setIssuerDN(X509PrincipalIf issuerDN);\r
 +        void setSubjectDN(X509PrincipalIf issuerDN);\r
 +        void setSerialNumber(BigInteger serialNumber);\r
 +        \r
 +        void addExtension(ASN1ObjectIdentifierIf oid, boolean critical, SubjectKeyIdentifierIf value);\r
 +        void addExtension(ASN1ObjectIdentifierIf oid, boolean critical, AuthorityKeyIdentifierIf value);\r
 +        void addExtension(ASN1ObjectIdentifierIf oid, boolean critical, BasicConstraintsIf value);\r
 +        void addExtension(ASN1ObjectIdentifierIf oid, boolean critical, DERSequenceIf value);\r
 +        void addExtension(ASN1ObjectIdentifierIf oid, boolean critical, AuthorityInformationAccessIf value);\r
 +        void addExtension(ASN1ObjectIdentifierIf oid, boolean critical, KeyUsageIf value);\r
 +        \r
 +        X509Certificate generate(PrivateKey issuerPrivateKey);\r
 +    }\r
 +\r
 +    public interface OCSPReqIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.cert.ocsp.OCSPReq";\r
 +\r
 +        ReqIf[] getRequestList();\r
 +    }\r
 +    \r
 +    public interface OCSPReqGeneratorIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.ocsp.OCSPReqGenerator";\r
 +        \r
 +        void addRequest(CertificateIDIf certId);\r
 +        OCSPReqIf generate();\r
 +    }\r
 +\r
 +    public interface BasicOCSPRespGeneratorIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.ocsp.BasicOCSPRespGenerator";\r
 +\r
 +        void addResponse(CertificateIDIf certificateID, CertificateStatusIf certificateStatus);\r
 +        BasicOCSPRespIf generate(String signatureAlgorithm, PrivateKey ocspResponderPrivateKey,\r
 +                X509Certificate chain[], Date date, String provider);\r
 +    }\r
 +    \r
 +    public interface CertificateIDIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.cert.ocsp.CertificateID";\r
 +        \r
 +        String HASH_SHA1();\r
 +    }\r
 +    \r
 +    public interface X509ExtensionsIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.x509.X509Extensions";\r
 +        \r
 +        ASN1ObjectIdentifierIf AuthorityKeyIdentifier();\r
 +        ASN1ObjectIdentifierIf SubjectKeyIdentifier();\r
 +        ASN1ObjectIdentifierIf BasicConstraints();\r
 +        ASN1ObjectIdentifierIf CRLDistributionPoints();\r
 +        ASN1ObjectIdentifierIf AuthorityInfoAccess();\r
 +        ASN1ObjectIdentifierIf KeyUsage();\r
 +        ASN1ObjectIdentifierIf CRLNumber();\r
 +    }\r
 +    \r
 +    public interface X509ObjectIdentifiersIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.x509.X509ObjectIdentifiers";\r
 +        \r
 +        ASN1ObjectIdentifierIf ocspAccessMethod();\r
 +    }\r
 +    \r
 +    public interface X509V2CRLGeneratorIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.x509.X509V2CRLGenerator";\r
 +        \r
 +        void setIssuerDN(X500Principal issuerDN);\r
 +        void setThisUpdate(Date date);\r
 +        void setNextUpdate(Date date);\r
 +        void setSignatureAlgorithm(String algorithm);\r
 +        \r
 +        void addExtension(ASN1ObjectIdentifierIf oid, boolean critical, CRLNumberIf value);\r
 +        X509CRL generate(PrivateKey privateKey);\r
 +    }\r
 +    \r
 +    public interface ReqIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.cert.ocsp.Req";\r
 +        \r
 +        CertificateIDIf getCertID();\r
 +    }\r
 +    \r
 +    public interface CertificateStatusIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.cert.ocsp.CertificateStatus";\r
 +        \r
 +        CertificateStatusIf GOOD();\r
 +    }\r
 +    \r
 +    public interface RevokedStatusIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.cert.ocsp.RevokedStatus";\r
 +    }\r
 +    \r
 +    public interface CRLReasonIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.asn1.x509.CRLReason";\r
 +        int unspecified();\r
 +    }\r
 +\r
 +    public interface OCSPRespGeneratorIf extends ProxyIf {\r
 +        String delegateClass = "org.bouncycastle.ocsp.OCSPRespGenerator";\r
 +        int SUCCESSFUL();\r
 +        OCSPRespIf generate(int status, BasicOCSPRespIf basicOCSPResp);\r
 +    }\r
 +}\r
index 4dbfa5474aed875a947e1336cebaff610018471d,0000000000000000000000000000000000000000..142d56bc0acff454f153acb59f6fee69b2ad76c5
mode 100644,000000..100644
--- /dev/null
@@@ -1,297 -1,0 +1,297 @@@
-                 Document doc = SAXHelper.readSAXDocumentW3C(signaturePart.getInputStream());\r
 +/* ====================================================================\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;\r
 +\r
 +import java.io.ByteArrayOutputStream;\r
 +import java.io.IOException;\r
 +import java.security.Key;\r
 +import java.security.NoSuchAlgorithmException;\r
 +import java.security.Provider;\r
 +import java.security.Security;\r
 +import java.security.cert.X509Certificate;\r
 +import java.util.Collections;\r
 +import java.util.Date;\r
 +import java.util.LinkedList;\r
 +import java.util.List;\r
 +\r
 +import javax.crypto.Cipher;\r
 +import javax.xml.crypto.dsig.XMLSignature;\r
 +import javax.xml.crypto.dsig.XMLSignatureFactory;\r
 +import javax.xml.crypto.dsig.dom.DOMValidateContext;\r
 +import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;\r
 +\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.PackagePart;\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.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.HorribleProxies.InitIf;\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.POILogFactory;\r
 +import org.apache.poi.util.POILogger;\r
 +import org.apache.poi.util.SAXHelper;\r
 +import org.apache.xmlbeans.XmlCursor;\r
 +import org.apache.xmlbeans.XmlObject;\r
 +import org.w3c.dom.Document;\r
 +import org.w3c.dom.Element;\r
 +\r
 +public class SignatureInfo {\r
 +    \r
 +    public static final byte[] SHA1_DIGEST_INFO_PREFIX = new byte[]\r
 +        { 0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x04, 0x14 };\r
 +\r
 +    public static final byte[] SHA224_DIGEST_INFO_PREFIX = new byte[] \r
 +        { 0x30, 0x2b, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86\r
 +        , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x04, 0x1c };\r
 +\r
 +    public static final byte[] SHA256_DIGEST_INFO_PREFIX = new byte[]\r
 +        { 0x30, 0x2f, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86\r
 +        , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x04, 0x20 };\r
 +\r
 +    public static final byte[] SHA384_DIGEST_INFO_PREFIX = new byte[]\r
 +        { 0x30, 0x3f, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86\r
 +        , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x04, 0x30 };\r
 +\r
 +    public static final byte[] SHA512_DIGEST_INFO_PREFIX = new byte[]\r
 +        { 0x30, 0x4f, 0x30, 0x0b, 0x06, 0x09, 0x60, (byte) 0x86\r
 +        , 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x04, 0x40 };\r
 +\r
 +    public static final byte[] RIPEMD128_DIGEST_INFO_PREFIX = new byte[]\r
 +        { 0x30, 0x1b, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x02, 0x04, 0x10 };\r
 +\r
 +    public static final byte[] RIPEMD160_DIGEST_INFO_PREFIX = new byte[]\r
 +        { 0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x01, 0x04, 0x14 };\r
 +\r
 +    public static final byte[] RIPEMD256_DIGEST_INFO_PREFIX = new byte[]\r
 +        { 0x30, 0x2b, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x24, 0x03, 0x02, 0x03, 0x04, 0x20 };\r
 +    \r
 +    \r
 +    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
 +    }\r
 +    \r
 +    public boolean verifySignature() {\r
 +        initXmlProvider();\r
 +        // http://www.oracle.com/technetwork/articles/javase/dig-signature-api-140772.html\r
 +        List<X509Certificate> signers = new LinkedList<X509Certificate>();\r
 +        return getSignersAndValidate(signers, true);\r
 +    }\r
 +\r
 +    public void confirmSignature(Key key, X509Certificate x509)\r
 +    throws NoSuchAlgorithmException, IOException {\r
 +        confirmSignature(key, x509, HashAlgorithm.sha1);\r
 +    }\r
 +    \r
 +    public void confirmSignature(Key key, X509Certificate x509, HashAlgorithm hashAlgo)\r
 +    throws NoSuchAlgorithmException, IOException {\r
 +        XmlSignatureService signatureService = createSignatureService(hashAlgo, pkg);\r
 +        \r
 +        // operate\r
 +        List<X509Certificate> x509Chain = Collections.singletonList(x509);\r
 +        DigestInfo digestInfo = signatureService.preSign(null, x509Chain, null, null, null);\r
 +\r
 +        // setup: key material, signature value\r
 +\r
 +        Cipher cipher = CryptoFunctions.getCipher(key, CipherAlgorithm.rsa\r
 +            , ChainingMode.ecb, null, Cipher.ENCRYPT_MODE, "PKCS1Padding");\r
 +        \r
 +        byte[] signatureValue;\r
 +        try {\r
 +            ByteArrayOutputStream digestInfoValueBuf = new ByteArrayOutputStream();\r
 +            digestInfoValueBuf.write(getHashMagic(hashAlgo));\r
 +            digestInfoValueBuf.write(digestInfo.digestValue);\r
 +            byte[] digestInfoValue = digestInfoValueBuf.toByteArray();\r
 +            signatureValue = cipher.doFinal(digestInfoValue);\r
 +        } catch (Exception e) {\r
 +            throw new EncryptedDocumentException(e);\r
 +        }\r
 +\r
 +        \r
 +        // operate: postSign\r
 +        signatureService.postSign(signatureValue, Collections.singletonList(x509));\r
 +    }\r
 +\r
 +    public XmlSignatureService createSignatureService(HashAlgorithm hashAlgo, OPCPackage pkg) {\r
 +        XmlSignatureService signatureService = new XmlSignatureService(hashAlgo, pkg);\r
 +        signatureService.initFacets(new Date());\r
 +        return signatureService;\r
 +    }\r
 +    \r
 +    public List<X509Certificate> getSigners() {\r
 +        initXmlProvider();\r
 +        List<X509Certificate> signers = new LinkedList<X509Certificate>();\r
 +        getSignersAndValidate(signers, false);\r
 +        return signers;\r
 +    }\r
 +    \r
 +    protected boolean getSignersAndValidate(List<X509Certificate> signers, boolean onlyFirst) {\r
 +        boolean allValid = true;\r
 +        List<PackagePart> signatureParts = getSignatureParts(onlyFirst);\r
 +        if (signatureParts.isEmpty()) {\r
 +            LOG.log(POILogger.DEBUG, "no signature resources");\r
 +            allValid = false;\r
 +        }\r
 +        \r
 +        for (PackagePart signaturePart : signatureParts) {\r
 +            KeyInfoKeySelector keySelector = new KeyInfoKeySelector();\r
 +\r
 +            try {\r
++                Document doc = SAXHelper.readSAXDocument(signaturePart.getInputStream());\r
 +                // dummy call to createSignatureService to tweak document afterwards\r
 +                createSignatureService(HashAlgorithm.sha1, pkg).registerIds(doc);\r
 +                \r
 +                DOMValidateContext domValidateContext = new DOMValidateContext(keySelector, doc);\r
 +                domValidateContext.setProperty("org.jcp.xml.dsig.validateManifests", Boolean.TRUE);\r
 +                OOXMLURIDereferencer dereferencer = new OOXMLURIDereferencer(pkg);\r
 +                domValidateContext.setURIDereferencer(dereferencer);\r
 +    \r
 +                XMLSignatureFactory xmlSignatureFactory = getSignatureFactory();\r
 +                XMLSignature xmlSignature = xmlSignatureFactory.unmarshalXMLSignature(domValidateContext);\r
 +                boolean validity = xmlSignature.validate(domValidateContext);\r
 +                allValid &= validity;\r
 +                if (!validity) continue;\r
 +                // TODO: check what has been signed.\r
 +            } catch (Exception e) {\r
 +                LOG.log(POILogger.ERROR, "error in marshalling and validating the signature", e);\r
 +                continue;\r
 +            }\r
 +\r
 +            X509Certificate signer = keySelector.getCertificate();\r
 +            signers.add(signer);\r
 +        }\r
 +        \r
 +        return allValid;\r
 +    }\r
 +\r
 +    protected List<PackagePart> getSignatureParts(boolean onlyFirst) {\r
 +        List<PackagePart> packageParts = new LinkedList<PackagePart>();\r
 +        \r
 +        PackageRelationshipCollection sigOrigRels = pkg.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN);\r
 +        for (PackageRelationship rel : sigOrigRels) {\r
 +            PackagePart sigPart = pkg.getPart(rel);\r
 +            LOG.log(POILogger.DEBUG, "Digital Signature Origin part", sigPart);\r
 +\r
 +            try {\r
 +                PackageRelationshipCollection sigRels = sigPart.getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE);\r
 +                for (PackageRelationship sigRel : sigRels) {\r
 +                    PackagePart sigRelPart = sigPart.getRelatedPart(sigRel); \r
 +                    LOG.log(POILogger.DEBUG, "XML Signature part", sigRelPart);\r
 +                    packageParts.add(sigRelPart);\r
 +                    if (onlyFirst) break;\r
 +                }\r
 +            } catch (InvalidFormatException e) {\r
 +                LOG.log(POILogger.WARN, "Reference to signature is invalid.", e);\r
 +            }\r
 +            \r
 +            if (onlyFirst && !packageParts.isEmpty()) break;\r
 +        }\r
 +\r
 +        return packageParts;\r
 +    }\r
 +    \r
 +    public static XMLSignatureFactory getSignatureFactory() {\r
 +        Provider p = Security.getProvider("XMLDSig");\r
 +        assert(p != null);\r
 +        return XMLSignatureFactory.getInstance("DOM", p);\r
 +    }\r
 +\r
 +    public static KeyInfoFactory getKeyInfoFactory() {\r
 +        Provider p = Security.getProvider("XMLDSig");\r
 +        assert(p != null);\r
 +        return KeyInfoFactory.getInstance("DOM", p);\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
 +        for (XmlCursor 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
 +    }\r
 +    \r
 +    protected static byte[] getHashMagic(HashAlgorithm hashAlgo) {\r
 +        switch (hashAlgo) {\r
 +        case sha1: return SHA1_DIGEST_INFO_PREFIX;\r
 +        // sha224: return SHA224_DIGEST_INFO_PREFIX;\r
 +        case sha256: return SHA256_DIGEST_INFO_PREFIX;\r
 +        case sha384: return SHA384_DIGEST_INFO_PREFIX;\r
 +        case sha512: return SHA512_DIGEST_INFO_PREFIX;\r
 +        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
 +        }\r
 +    }\r
 +    \r
 +    public static synchronized void initXmlProvider() {\r
 +        if (isInitialized) return;\r
 +        isInitialized = true;\r
 +        \r
 +        try {\r
 +            InitIf init = HorribleProxy.newProxy(InitIf.class);\r
 +            init.init();\r
 +\r
 +            RelationshipTransformService.registerDsigProvider();\r
 +            \r
 +            Provider bcProv = Security.getProvider("BC");\r
 +            if (bcProv == null) {\r
 +                ClassLoader cl = Thread.currentThread().getContextClassLoader();\r
 +                Class<?> c = cl.loadClass("org.bouncycastle.jce.provider.BouncyCastleProvider");\r
 +                bcProv = (Provider)c.newInstance();\r
 +                Security.addProvider(bcProv);\r
 +            }\r
 +        } catch (Exception e) {\r
 +            throw new RuntimeException("Xml & BouncyCastle-Provider initialization failed", e);\r
 +        }\r
 +    }\r
 +}\r
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..4f4f9af7ad8c5e914146ca07e5243176344afffc
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,84 @@@
++package org.apache.poi.poifs.crypt.dsig.facets;\r
++\r
++import java.security.InvalidAlgorithmParameterException;\r
++import java.security.NoSuchAlgorithmException;\r
++import java.security.cert.X509Certificate;\r
++import java.util.LinkedList;\r
++import java.util.List;\r
++import java.util.Map;\r
++\r
++import javax.xml.crypto.dsig.CanonicalizationMethod;\r
++import javax.xml.crypto.dsig.DigestMethod;\r
++import javax.xml.crypto.dsig.Reference;\r
++import javax.xml.crypto.dsig.Transform;\r
++import javax.xml.crypto.dsig.XMLObject;\r
++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.w3.x2000.x09.xmldsig.SignatureType;\r
++\r
++/**\r
++ * Signature Facet implementation to create enveloped signatures.\r
++ * \r
++ * @author Frank Cornelis\r
++ * \r
++ */\r
++public class EnvelopedSignatureFacet implements SignatureFacet {\r
++\r
++    private final HashAlgorithm hashAlgo;\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
++    }\r
++\r
++    @Override\r
++    public void postSign(SignatureType signatureElement\r
++        , List<X509Certificate> signingCertificateChain) {\r
++        // empty\r
++    }\r
++\r
++    @Override\r
++    public void preSign(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
++\r
++        List<Transform> transforms = new LinkedList<Transform>();\r
++        Transform envelopedTransform = signatureFactory\r
++                .newTransform(CanonicalizationMethod.ENVELOPED,\r
++                        (TransformParameterSpec) null);\r
++        transforms.add(envelopedTransform);\r
++        Transform exclusiveTransform = signatureFactory\r
++                .newTransform(CanonicalizationMethod.EXCLUSIVE,\r
++                        (TransformParameterSpec) null);\r
++        transforms.add(exclusiveTransform);\r
++\r
++        Reference reference = signatureFactory.newReference("", digestMethod,\r
++                transforms, null, null);\r
++\r
++        references.add(reference);\r
++    }\r
++\r
++    @Override\r
++    public Map<String,String> getNamespacePrefixMapping() {\r
++        return null;\r
++    }\r
++}\r
index c09501a4a1a5823a6dbcd6f2fafb129e3644aae6,0000000000000000000000000000000000000000..bea7653430af81d0cbc84f394f3767cd37b1a4b0
mode 100644,000000..100644
--- /dev/null
@@@ -1,610 -1,0 +1,612 @@@
-     protected void addSignatureFacet(SignatureFacet signatureFacet) {\r
-         this.signatureFacets.add(signatureFacet);\r
 +/* ====================================================================\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.ByteArrayOutputStream;\r
 +import java.io.File;\r
 +import java.io.IOException;\r
 +import java.io.OutputStream;\r
 +import java.net.MalformedURLException;\r
 +import java.security.InvalidAlgorithmParameterException;\r
 +import java.security.Key;\r
 +import java.security.MessageDigest;\r
 +import java.security.NoSuchAlgorithmException;\r
 +import java.security.NoSuchProviderException;\r
 +import java.security.cert.X509Certificate;\r
 +import java.util.Date;\r
 +import java.util.HashMap;\r
 +import java.util.LinkedList;\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.dom.DOMCryptoContext;\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.DocumentBuilderFactory;\r
 +import javax.xml.parsers.ParserConfigurationException;\r
 +import javax.xml.transform.TransformerException;\r
 +import javax.xml.transform.TransformerFactoryConfigurationError;\r
 +\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.HorribleProxies.DOMReferenceIf;\r
 +import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DOMSignedInfoIf;\r
 +import org.apache.poi.poifs.crypt.dsig.HorribleProxies.DOMXMLSignatureIf;\r
 +import org.apache.poi.poifs.crypt.dsig.HorribleProxies.XMLSignatureIf;\r
 +import org.apache.poi.poifs.crypt.dsig.HorribleProxy;\r
 +import org.apache.poi.poifs.crypt.dsig.OOXMLURIDereferencer;\r
 +import org.apache.poi.poifs.crypt.dsig.SignatureInfo;\r
 +import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet;\r
 +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.XAdESSignatureFacet;\r
 +import org.apache.poi.poifs.crypt.dsig.spi.AddressDTO;\r
 +import org.apache.poi.poifs.crypt.dsig.spi.Constants;\r
 +import org.apache.poi.poifs.crypt.dsig.spi.DigestInfo;\r
 +import org.apache.poi.poifs.crypt.dsig.spi.IdentityDTO;\r
 +import org.apache.poi.util.POILogFactory;\r
 +import org.apache.poi.util.POILogger;\r
 +import org.apache.xmlbeans.XmlException;\r
 +import org.apache.xmlbeans.XmlOptions;\r
 +import org.w3.x2000.x09.xmldsig.SignatureDocument;\r
 +import org.w3.x2000.x09.xmldsig.SignatureType;\r
 +import org.w3.x2000.x09.xmldsig.SignatureValueType;\r
 +import org.w3c.dom.Document;\r
 +import org.w3c.dom.Element;\r
 +import org.w3c.dom.NodeList;\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 final List<SignatureFacet> signatureFacets;\r
 +\r
 +    private String signatureNamespacePrefix;\r
 +    private String signatureId;\r
 +    private final HashAlgorithm hashAlgo;\r
 +    private final OPCPackage opcPackage;\r
 +    private SignatureDocument sigDoc;\r
 +    private XAdESSignatureFacet xadesSignatureFacet;\r
 +    \r
 +    /**\r
 +     * Main constructor.\r
 +     */\r
 +    public XmlSignatureService(HashAlgorithm digestAlgo, OPCPackage opcPackage) {\r
 +        this.signatureFacets = new LinkedList<SignatureFacet>();\r
 +        this.signatureNamespacePrefix = null;\r
 +        this.signatureId = null;\r
 +        this.hashAlgo = digestAlgo;\r
 +        this.opcPackage = opcPackage;\r
 +        this.sigDoc = null;\r
 +    }\r
 +\r
 +    public void initFacets(Date clock) {\r
 +        if (clock == null) clock = new Date();\r
 +        addSignatureFacet(new OOXMLSignatureFacet(this, clock, hashAlgo));\r
 +        addSignatureFacet(new KeyInfoSignatureFacet(true, false, false));\r
 +\r
 +        this.xadesSignatureFacet = new XAdESSignatureFacet(clock, hashAlgo, null);\r
 +        this.xadesSignatureFacet.setIdSignedProperties("idSignedProperties");\r
 +        this.xadesSignatureFacet.setSignaturePolicyImplied(true);\r
 +        /*\r
 +         * Work-around for Office 2010.\r
 +         */\r
 +        this.xadesSignatureFacet.setIssuerNameNoReverseOrder(true);\r
 +        setSignatureId("idPackageSignature");\r
 +        addSignatureFacet(this.xadesSignatureFacet);\r
 +        addSignatureFacet(new Office2010SignatureFacet());\r
 +    }\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
 +     * Adds a signature facet to this XML signature service.\r
 +     * \r
 +     * @param signatureFacet\r
 +     */\r
++    public void addSignatureFacet(SignatureFacet... signatureFacets) {\r
++        for (SignatureFacet sf : signatureFacets) {\r
++            this.signatureFacets.add(sf);\r
++        }\r
 +    }\r
 +\r
 +    /**\r
 +     * Gives back the signature digest algorithm. Allowed values are SHA-1,\r
 +     * SHA-256, SHA-384, SHA-512, RIPEND160. The default algorithm is SHA-1.\r
 +     * Override this method to select another signature digest algorithm.\r
 +     * \r
 +     * @return\r
 +     */\r
 +    protected HashAlgorithm getSignatureDigestAlgorithm() {\r
 +        return null != this.hashAlgo ? this.hashAlgo : HashAlgorithm.sha1;\r
 +    }\r
 +\r
 +    /**\r
 +     * Override this method to change the URI dereferener used by the signing\r
 +     * engine.\r
 +     * \r
 +     * @return\r
 +     */\r
 +    protected URIDereferencer getURIDereferencer() {\r
 +        OPCPackage ooxmlDocument = getOfficeOpenXMLDocument();\r
 +        return new OOXMLURIDereferencer(ooxmlDocument);\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 URL of the OOXML to be signed.\r
 +     * \r
 +     * @return\r
 +     */\r
 +    public OPCPackage getOfficeOpenXMLDocument() {\r
 +        return opcPackage;\r
 +    }\r
 +    \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
 +\r
 +    public DigestInfo preSign(List<DigestInfo> digestInfos,\r
 +        List<X509Certificate> signingCertificateChain,\r
 +        IdentityDTO identity, AddressDTO address, byte[] photo)\r
 +    throws NoSuchAlgorithmException {\r
 +        SignatureInfo.initXmlProvider();\r
 +    \r
 +        LOG.log(POILogger.DEBUG, "preSign");\r
 +        HashAlgorithm hashAlgo = getSignatureDigestAlgorithm();\r
 +\r
 +        byte[] digestValue;\r
 +        try {\r
 +            digestValue = getXmlSignatureDigestValue(hashAlgo, digestInfos, signingCertificateChain);\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
 +    public void postSign(byte[] signatureValue, List<X509Certificate> signingCertificateChain)\r
 +    throws IOException {\r
 +        LOG.log(POILogger.DEBUG, "postSign");\r
 +        SignatureInfo.initXmlProvider();\r
 +\r
 +        /*\r
 +         * Retrieve the intermediate XML signature document from the temporary  \r
 +         * data storage.\r
 +         */\r
 +        SignatureType sigType = sigDoc.getSignature();\r
 +\r
 +        /*\r
 +         * Check ds:Signature node.\r
 +         */\r
 +        if (!signatureId.equals(sigType.getId())) {\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
 +        SignatureValueType sigVal = sigType.getSignatureValue();\r
 +        sigVal.setByteArrayValue(signatureValue);\r
 +\r
 +        /*\r
 +         * Allow signature facets to inject their own stuff.\r
 +         */\r
 +        for (SignatureFacet signatureFacet : this.signatureFacets) {\r
 +            signatureFacet.postSign(sigType, signingCertificateChain);\r
 +        }\r
 +\r
 +        writeDocument();\r
 +    }\r
 +\r
 +    @SuppressWarnings("unchecked")\r
 +    private byte[] getXmlSignatureDigestValue(HashAlgorithm hashAlgo,\r
 +        List<DigestInfo> digestInfos,\r
 +        List<X509Certificate> signingCertificateChain)\r
 +        throws ParserConfigurationException, NoSuchAlgorithmException,\r
 +        InvalidAlgorithmParameterException, MarshalException,\r
 +        javax.xml.crypto.dsig.XMLSignatureException,\r
 +        TransformerFactoryConfigurationError, TransformerException,\r
 +        IOException, SAXException, NoSuchProviderException, XmlException {\r
 +        /*\r
 +         * DOM Document construction.\r
 +         */\r
 +        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();\r
 +        dbf.setNamespaceAware(true);\r
 +        Document doc = dbf.newDocumentBuilder().newDocument();\r
 +\r
 +        /*\r
 +         * Signature context construction.\r
 +         */\r
 +        Key key = new Key() {\r
 +            private static final long serialVersionUID = 1L;\r
 +\r
 +            public String getAlgorithm() {\r
 +                return null;\r
 +            }\r
 +\r
 +            public byte[] getEncoded() {\r
 +                return null;\r
 +            }\r
 +\r
 +            public String getFormat() {\r
 +                return null;\r
 +            }\r
 +        };\r
 +        \r
 +        // As of JDK 7, can't use sigDoc here directly, because the\r
 +        // setAttributeID will be called and it's not implemented in xmlbeans\r
 +        XMLSignContext xmlSignContext = new DOMSignContext(key, doc);\r
 +        URIDereferencer uriDereferencer = 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(\r
 +                javax.xml.crypto.dsig.XMLSignature.XMLNS,\r
 +                this.signatureNamespacePrefix);\r
 +        }\r
 +\r
 +        XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM", "XMLDSig");\r
 +\r
 +        /*\r
 +         * Add ds:References that come from signing client local files.\r
 +         */\r
 +        List<Reference> references = new LinkedList<Reference>();\r
 +        addDigestInfosAsReferences(digestInfos, signatureFactory, references);\r
 +\r
 +        /*\r
 +         * Invoke the signature facets.\r
 +         */\r
 +        String localSignatureId;\r
 +        if (null == this.signatureId) {\r
 +            localSignatureId = "xmldsig-" + UUID.randomUUID().toString();\r
 +        } else {\r
 +            localSignatureId = this.signatureId;\r
 +        }\r
 +        List<XMLObject> objects = new LinkedList<XMLObject>();\r
 +        for (SignatureFacet signatureFacet : this.signatureFacets) {\r
 +            LOG.log(POILogger.DEBUG, "invoking signature facet: "\r
 +                + signatureFacet.getClass().getSimpleName());\r
 +            signatureFacet.preSign(signatureFactory, localSignatureId, signingCertificateChain, references, objects);\r
 +        }\r
 +\r
 +        /*\r
 +         * ds:SignedInfo\r
 +         */\r
 +        SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(\r
 +            getSignatureMethod(hashAlgo), 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
 +        DOMXMLSignatureIf domXmlSignature;\r
 +        try {\r
 +            domXmlSignature = HorribleProxy.newProxy(DOMXMLSignatureIf.class, xmlSignature);\r
 +        } catch (Exception e) {\r
 +            throw new RuntimeException("DomXmlSignature instance error: " + e.getMessage(), e);\r
 +        }\r
 +        \r
 +        domXmlSignature.marshal(doc, this.signatureNamespacePrefix, (DOMCryptoContext) xmlSignContext);\r
 +\r
 +        registerIds(doc);\r
 +        Element el = doc.getElementById("idPackageObject");\r
 +        assert (el != null);\r
 +        el.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:mdssi", PackageNamespaces.DIGITAL_SIGNATURE);\r
 +\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
 +                    DOMReferenceIf manifestDOMReference;\r
 +                    try {\r
 +                        manifestDOMReference = HorribleProxy.newProxy(DOMReferenceIf.class, manifestReference);\r
 +                    } catch (Exception e) {\r
 +                        throw new RuntimeException("DOMReference instance error: " + e.getMessage(), e);\r
 +                    }\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
 +            DOMReferenceIf domReference;\r
 +            try {\r
 +                domReference = HorribleProxy.newProxy(DOMReferenceIf.class, signedInfoReference);\r
 +            } catch (Exception e) {\r
 +                throw new RuntimeException("DOMReference instance error: " + e.getMessage(), e);\r
 +            }\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
 +        DOMSignedInfoIf domSignedInfo;\r
 +        try {\r
 +            domSignedInfo = HorribleProxy.newProxy(DOMSignedInfoIf.class, signedInfo); \r
 +        } catch (Exception e) {\r
 +            throw new RuntimeException("DOMSignedInfo instance error: " + e.getMessage(), e);\r
 +        }\r
 +        \r
 +        ByteArrayOutputStream dataStream = new ByteArrayOutputStream();\r
 +        domSignedInfo.canonicalize(xmlSignContext, dataStream);\r
 +        byte[] octets = dataStream.toByteArray();\r
 +\r
 +        sigDoc = SignatureDocument.Factory.parse(doc.getDocumentElement());\r
 +        \r
 +        \r
 +        /*\r
 +         * TODO: we could be using DigestOutputStream here to optimize memory\r
 +         * usage.\r
 +         */\r
 +\r
 +        MessageDigest jcaMessageDigest = CryptoFunctions.getMessageDigest(hashAlgo);\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 void registerIds(Document doc) {\r
 +        NodeList nl = doc.getElementsByTagNameNS("http://www.w3.org/2000/09/xmldsig#", "Object");\r
 +        registerIdAttribute(nl);\r
 +        nl = doc.getElementsByTagNameNS("http://uri.etsi.org/01903/v1.3.2#", "SignedProperties");\r
 +        registerIdAttribute(nl);\r
 +    }\r
 +    \r
 +    protected 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,\r
 +        XMLSignatureFactory signatureFactory, List<Reference> references)\r
 +        throws NoSuchAlgorithmException,\r
 +        InvalidAlgorithmParameterException, MalformedURLException {\r
 +        if (digestInfos == null) return;\r
 +        for (DigestInfo digestInfo : 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
 +        XMLSignatureIf XmlSignature;\r
 +        try {\r
 +            XmlSignature = HorribleProxy.newProxy(XMLSignatureIf.class);\r
 +        } catch (Exception e) {\r
 +            throw new RuntimeException("JDK doesn't support XmlSignature", e);\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
 +    /**\r
 +     * Gives back the used XAdES signature facet.\r
 +     * \r
 +     * @return\r
 +     */\r
 +    protected XAdESSignatureFacet getXAdESSignatureFacet() {\r
 +        return this.xadesSignatureFacet;\r
 +    }\r
 +\r
 +    public String getFilesDigestAlgorithm() {\r
 +        return null;\r
 +    }\r
 +\r
 +    protected String getCanonicalizationMethod() {\r
 +        return CanonicalizationMethod.INCLUSIVE;\r
 +    }\r
 +\r
 +    protected void writeDocument() throws IOException {\r
 +        XmlOptions xo = new XmlOptions();\r
 +        Map<String,String> namespaceMap = new HashMap<String,String>();\r
 +        for (SignatureFacet sf : this.signatureFacets) {\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.getOfficeOpenXMLDocument();\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
 +        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
index 4243f6b1f57a02530aa08f99c2825ffc7dbbb13a,0000000000000000000000000000000000000000..b3f08b3c8ba6b76ed5432ceff0e23552e182b169
mode 100644,000000..100644
--- /dev/null
@@@ -1,267 -1,0 +1,342 @@@
 +/* ====================================================================\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
 +package org.apache.poi.poifs.crypt;\r
 +\r
 +import static org.junit.Assert.assertEquals;\r
 +import static org.junit.Assert.assertNotNull;\r
 +import static org.junit.Assert.assertTrue;\r
++import static org.mockito.Matchers.any;\r
++import static org.mockito.Matchers.eq;\r
++import static org.mockito.Mockito.mock;\r
++import static org.mockito.Mockito.when;\r
 +\r
 +import java.io.ByteArrayOutputStream;\r
 +import java.io.File;\r
 +import java.io.FileInputStream;\r
 +import java.io.FileOutputStream;\r
 +import java.io.IOException;\r
 +import java.net.MalformedURLException;\r
 +import java.net.URL;\r
 +import java.net.URLClassLoader;\r
 +import java.security.Key;\r
 +import java.security.KeyPair;\r
 +import java.security.KeyStore;\r
 +import java.security.PrivateKey;\r
 +import java.security.cert.Certificate;\r
++import java.security.cert.X509CRL;\r
 +import java.security.cert.X509Certificate;\r
++import java.util.ArrayList;\r
 +import java.util.Calendar;\r
 +import java.util.Collections;\r
 +import java.util.Date;\r
 +import java.util.List;\r
 +import java.util.TimeZone;\r
 +\r
 +import javax.crypto.Cipher;\r
 +\r
 +import org.apache.poi.POIDataSamples;\r
 +import org.apache.poi.openxml4j.opc.OPCPackage;\r
 +import org.apache.poi.openxml4j.opc.PackageAccess;\r
 +import org.apache.poi.poifs.crypt.dsig.HorribleProxies.KeyUsageIf;\r
++import org.apache.poi.poifs.crypt.dsig.HorribleProxies.OCSPRespIf;\r
 +import org.apache.poi.poifs.crypt.dsig.HorribleProxy;\r
 +import org.apache.poi.poifs.crypt.dsig.SignatureInfo;\r
++import org.apache.poi.poifs.crypt.dsig.facets.EnvelopedSignatureFacet;\r
++import org.apache.poi.poifs.crypt.dsig.facets.KeyInfoSignatureFacet;\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.facets.XAdESXLSignatureFacet;\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
 +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.IOUtils;\r
 +import org.apache.poi.util.POILogFactory;\r
 +import org.apache.poi.util.POILogger;\r
 +import org.junit.BeforeClass;\r
 +import org.junit.Test;\r
++import org.mockito.invocation.InvocationOnMock;\r
++import org.mockito.stubbing.Answer;\r
 +\r
 +public class TestSignatureInfo {\r
 +    private static final POILogger LOG = POILogFactory.getLogger(TestSignatureInfo.class);\r
 +    private static final POIDataSamples testdata = POIDataSamples.getXmlDSignInstance();\r
 +\r
 +    private KeyPair keyPair = null;\r
 +    private X509Certificate x509 = null;\r
 +    \r
 +\r
 +    \r
 +    @BeforeClass\r
 +    public static void initBouncy() throws MalformedURLException {\r
 +        File bcJar = testdata.getFile("bcprov-ext-jdk15on-1.49.jar");\r
 +        ClassLoader cl = Thread.currentThread().getContextClassLoader();\r
 +        URLClassLoader ucl = new URLClassLoader(new URL[]{bcJar.toURI().toURL()}, cl);\r
 +        Thread.currentThread().setContextClassLoader(ucl);\r
 +    }\r
 +    \r
 +    @Test\r
 +    public void getSignerUnsigned() throws Exception {\r
 +        String testFiles[] = { \r
 +            "hello-world-unsigned.docx",\r
 +            "hello-world-unsigned.pptx",\r
 +            "hello-world-unsigned.xlsx",\r
 +            "hello-world-office-2010-technical-preview-unsigned.docx"\r
 +        };\r
 +        \r
 +        for (String testFile : testFiles) {\r
 +            OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ);\r
 +            SignatureInfo si = new SignatureInfo(pkg);\r
 +            List<X509Certificate> result = si.getSigners();\r
 +            pkg.revert();\r
 +            pkg.close();\r
 +            assertNotNull(result);\r
 +            assertTrue(result.isEmpty());\r
 +        }\r
 +    }\r
 +    \r
 +    @Test\r
 +    public void getSigner() throws Exception {\r
 +        String testFiles[] = { \r
 +            "hyperlink-example-signed.docx",\r
 +            "hello-world-signed.docx",\r
 +            "hello-world-signed.pptx",\r
 +            "hello-world-signed.xlsx",\r
 +            "hello-world-office-2010-technical-preview.docx",\r
 +            "ms-office-2010-signed.docx",\r
 +            "ms-office-2010-signed.pptx",\r
 +            "ms-office-2010-signed.xlsx",\r
 +            "Office2010-SP1-XAdES-X-L.docx",\r
 +            "signed.docx",\r
 +        };\r
 +        \r
 +        for (String testFile : testFiles) {\r
 +            OPCPackage pkg = OPCPackage.open(testdata.getFile(testFile), PackageAccess.READ);\r
 +            SignatureInfo si = new SignatureInfo(pkg);\r
 +            List<X509Certificate> result = si.getSigners();\r
 +\r
 +            assertNotNull(result);\r
 +            assertEquals("test-file: "+testFile, 1, result.size());\r
 +            X509Certificate signer = result.get(0);\r
 +            LOG.log(POILogger.DEBUG, "signer: " + signer.getSubjectX500Principal());\r
 +\r
 +            boolean b = si.verifySignature();\r
 +            assertTrue("test-file: "+testFile, b);\r
 +            pkg.revert();\r
 +        }\r
 +    }\r
 +\r
 +    @Test\r
 +    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
 +        List<X509Certificate> result = si.getSigners();\r
 +\r
 +        assertNotNull(result);\r
 +        assertEquals("test-file: "+testFile, 2, result.size());\r
 +        X509Certificate signer1 = result.get(0);\r
 +        X509Certificate signer2 = result.get(1);\r
 +        LOG.log(POILogger.DEBUG, "signer 1: " + signer1.getSubjectX500Principal());\r
 +        LOG.log(POILogger.DEBUG, "signer 2: " + signer2.getSubjectX500Principal());\r
 +\r
 +        boolean b = si.verifySignature();\r
 +        assertTrue("test-file: "+testFile, b);\r
 +        pkg.revert();\r
 +    }\r
 +    \r
 +    @Test\r
 +    public void testSignSpreadsheet() throws Exception {\r
 +        String testFile = "hello-world-unsigned.xlsx";\r
 +        OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE);\r
 +        sign(pkg, "Test", "CN=Test", 1);\r
 +        pkg.close();\r
 +    }\r
 +\r
 +    @Test\r
 +    public void testSignSpreadsheetWithSignatureInfo() throws Exception {\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
 +        // hash > sha1 doesn't work in excel viewer ...\r
 +        si.confirmSignature(keyPair.getPrivate(), x509, HashAlgorithm.sha1);\r
 +        List<X509Certificate> signer = si.getSigners();\r
 +        assertEquals(1, signer.size());\r
 +        pkg.close();\r
 +    }\r
 +\r
++    @Test\r
++    public void testSignEnvelopingDocument() throws Exception {\r
++        String testFile = "hello-world-unsigned.xlsx";\r
++        OPCPackage pkg = OPCPackage.open(copy(testdata.getFile(testFile)), PackageAccess.READ_WRITE);\r
++\r
++        // setup\r
++        EnvelopedSignatureFacet envelopedSignatureFacet = new EnvelopedSignatureFacet();\r
++        KeyInfoSignatureFacet keyInfoSignatureFacet = new KeyInfoSignatureFacet(true, false, false);\r
++        SignaturePolicyService signaturePolicyService = null;\r
++        XAdESSignatureFacet xadesSignatureFacet = new XAdESSignatureFacet(null, null, signaturePolicyService);\r
++\r
++        \r
++        TimeStampService mockTimeStampService = mock(TimeStampService.class);\r
++        RevocationDataService mockRevocationDataService = mock(RevocationDataService.class);\r
++\r
++        XAdESXLSignatureFacet xadesXLSignatureFacet = new XAdESXLSignatureFacet(\r
++                mockTimeStampService, mockRevocationDataService);\r
++        XmlSignatureService testedInstance = new XmlSignatureService(HashAlgorithm.sha1, pkg);\r
++        testedInstance.addSignatureFacet(envelopedSignatureFacet, keyInfoSignatureFacet,\r
++                xadesSignatureFacet, xadesXLSignatureFacet);\r
++        \r
++        initKeyPair("Test", "CN=Test");\r
++        List<X509Certificate> certificateChain = new ArrayList<X509Certificate>();\r
++        /*\r
++         * We need at least 2 certificates for the XAdES-C complete certificate\r
++         * refs construction.\r
++         */\r
++        certificateChain.add(x509);\r
++        certificateChain.add(x509);\r
++        \r
++        RevocationData revocationData = new RevocationData();\r
++        final X509CRL crl = PkiTestUtils.generateCrl(x509, keyPair.getPrivate());\r
++        revocationData.addCRL(crl);\r
++        OCSPRespIf ocspResp = PkiTestUtils.createOcspResp(x509, false,\r
++                x509, x509, keyPair.getPrivate(), "SHA1withRSA");\r
++        revocationData.addOCSP(ocspResp.getEncoded());\r
++        \r
++        when(mockTimeStampService.timeStamp(any(byte[].class), any(RevocationData.class)))\r
++        .thenAnswer(new Answer<byte[]>(){\r
++            public byte[] answer(InvocationOnMock invocation) throws Throwable {\r
++                Object[] arguments = invocation.getArguments();\r
++                RevocationData revocationData = (RevocationData) arguments[1];\r
++                revocationData.addCRL(crl);\r
++                return "time-stamp-token".getBytes();\r
++            }            \r
++        });\r
++        \r
++        when(mockRevocationDataService.getRevocationData(eq(certificateChain)))\r
++        .thenReturn(revocationData);\r
++        \r
++        // operate\r
++        DigestInfo digestInfo = testedInstance.preSign(null, certificateChain, null, null, null);\r
++\r
++        // verify\r
++        assertNotNull(digestInfo);\r
++        assertEquals("SHA-1", digestInfo.hashAlgo);\r
++        assertNotNull(digestInfo.digestValue);\r
++    }\r
 +    \r
 +    private OPCPackage sign(OPCPackage pkgCopy, String alias, String signerDn, int signerCount) throws Exception {\r
 +        /*** TODO : set cal to now ... only set to fixed date for debugging ... */ \r
 +        Calendar cal = Calendar.getInstance();\r
 +        cal.clear();\r
 +        cal.setTimeZone(TimeZone.getTimeZone("UTC"));\r
 +        cal.set(2014, 7, 6, 21, 42, 12);\r
 +        \r
 +        XmlSignatureService signatureService = new XmlSignatureService(HashAlgorithm.sha1, pkgCopy);\r
 +        signatureService.initFacets(cal.getTime());\r
 +        initKeyPair(alias, signerDn);\r
 +\r
 +        // operate\r
 +        List<X509Certificate> x509Chain = Collections.singletonList(x509);\r
 +        DigestInfo digestInfo = signatureService.preSign(null, x509Chain, null, null, null);\r
 +\r
 +        // verify\r
 +        assertNotNull(digestInfo);\r
 +        LOG.log(POILogger.DEBUG, "digest algo: " + digestInfo.hashAlgo);\r
 +        LOG.log(POILogger.DEBUG, "digest description: " + digestInfo.description);\r
 +        assertEquals("Office OpenXML Document", digestInfo.description);\r
 +        assertNotNull(digestInfo.hashAlgo);\r
 +        assertNotNull(digestInfo.digestValue);\r
 +\r
 +        // setup: key material, signature value\r
 +\r
 +        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");\r
 +        cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());\r
 +        ByteArrayOutputStream digestInfoValueBuf = new ByteArrayOutputStream();\r
 +        digestInfoValueBuf.write(SignatureInfo.SHA1_DIGEST_INFO_PREFIX);\r
 +        digestInfoValueBuf.write(digestInfo.digestValue);\r
 +        byte[] digestInfoValue = digestInfoValueBuf.toByteArray();\r
 +        byte[] signatureValue = cipher.doFinal(digestInfoValue);\r
 +\r
 +        // operate: postSign\r
 +        signatureService.postSign(signatureValue, Collections.singletonList(x509));\r
 +\r
 +        // verify: signature\r
 +        SignatureInfo si = new SignatureInfo(pkgCopy);\r
 +        List<X509Certificate> signers = si.getSigners();\r
 +        assertEquals(signerCount, signers.size());\r
 +\r
 +        return pkgCopy;\r
 +    }\r
 +\r
 +    private void initKeyPair(String alias, String subjectDN) throws Exception {\r
 +        final char password[] = "test".toCharArray();\r
 +        File file = new File("build/test.pfx");\r
 +\r
 +        KeyStore keystore = KeyStore.getInstance("PKCS12");\r
 +\r
 +        if (file.exists()) {\r
 +            FileInputStream fis = new FileInputStream(file);\r
 +            keystore.load(fis, password);\r
 +            fis.close();\r
 +        } else {\r
 +            keystore.load(null, password);\r
 +        }\r
 +\r
 +        if (keystore.isKeyEntry(alias)) {\r
 +            Key key = keystore.getKey(alias, password);\r
 +            x509 = (X509Certificate)keystore.getCertificate(alias);\r
 +            keyPair = new KeyPair(x509.getPublicKey(), (PrivateKey)key);\r
 +        } else {\r
 +            keyPair = PkiTestUtils.generateKeyPair();\r
 +            Calendar cal = Calendar.getInstance();\r
 +            Date notBefore = cal.getTime();\r
 +            cal.add(Calendar.YEAR, 1);\r
 +            Date notAfter = cal.getTime();\r
 +            KeyUsageIf keyUsage = HorribleProxy.newProxy(KeyUsageIf.class);\r
 +            keyUsage = HorribleProxy.newProxy(KeyUsageIf.class, keyUsage.digitalSignature());\r
 +            \r
 +            x509 = PkiTestUtils.generateCertificate(keyPair.getPublic(), subjectDN\r
 +                , notBefore, notAfter, null, keyPair.getPrivate(), true, 0, null, null, keyUsage);\r
 +\r
 +            keystore.setKeyEntry(alias, keyPair.getPrivate(), password, new Certificate[]{x509});\r
 +            FileOutputStream fos = new FileOutputStream(file);\r
 +            keystore.store(fos, password);\r
 +            fos.close();\r
 +        }\r
 +    }\r
 +\r
 +    private static File copy(File input) throws IOException {\r
 +        String extension = input.getName().replaceAll(".*?(\\.[^.]+)?$", "$1");\r
 +        if (extension == null || "".equals(extension)) extension = ".zip";\r
 +        File tmpFile = new File("build", "sigtest"+extension);\r
 +        FileOutputStream fos = new FileOutputStream(tmpFile);\r
 +        FileInputStream fis = new FileInputStream(input);\r
 +        IOUtils.copy(fis, fos);\r
 +        fis.close();\r
 +        fos.close();\r
 +        return tmpFile;\r
 +    }\r
 +}\r