You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ug...@apache.org on 2009/10/13 18:31:30 UTC

svn commit: r824836 [3/3] - in /poi/trunk: ./ legal/ ooxml-lib/ src/ooxml/java/org/apache/poi/ooxml/ src/ooxml/java/org/apache/poi/ooxml/signature/ src/ooxml/java/org/apache/poi/ooxml/signature/service/ src/ooxml/java/org/apache/poi/ooxml/signature/ser...

Added: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/PkiTestUtils.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/PkiTestUtils.java?rev=824836&view=auto
==============================================================================
--- poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/PkiTestUtils.java (added)
+++ poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/PkiTestUtils.java Tue Oct 13 16:31:28 2009
@@ -0,0 +1,199 @@
+
+/* ====================================================================
+   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.
+==================================================================== */
+
+/*
+ * Based on the eID Applet Project code.
+ * Original Copyright (C) 2008-2009 FedICT.
+ */
+
+package org.apache.poi.ooxml.signature.service.signer;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.SignatureException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.security.spec.RSAKeyGenParameterSpec;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.bouncycastle.asn1.ASN1InputStream;
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DERIA5String;
+import org.bouncycastle.asn1.DERSequence;
+import org.bouncycastle.asn1.x509.AuthorityInformationAccess;
+import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.DistributionPoint;
+import org.bouncycastle.asn1.x509.DistributionPointName;
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.bouncycastle.asn1.x509.GeneralNames;
+import org.bouncycastle.asn1.x509.KeyUsage;
+import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.asn1.x509.X509Extensions;
+import org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
+import org.bouncycastle.jce.X509Principal;
+import org.bouncycastle.x509.X509V3CertificateGenerator;
+import org.joda.time.DateTime;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+public class PkiTestUtils {
+
+    public static final byte[] SHA1_DIGEST_INFO_PREFIX = new byte[] { 0x30, 0x1f, 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x04, 0x14 };
+
+    private PkiTestUtils() {
+        super();
+    }
+
+    static KeyPair generateKeyPair() throws Exception {
+        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
+        SecureRandom random = new SecureRandom();
+        keyPairGenerator.initialize(new RSAKeyGenParameterSpec(1024, RSAKeyGenParameterSpec.F4), random);
+        KeyPair keyPair = keyPairGenerator.generateKeyPair();
+        return keyPair;
+    }
+
+    private static SubjectKeyIdentifier createSubjectKeyId(PublicKey publicKey) throws IOException {
+        ByteArrayInputStream bais = new ByteArrayInputStream(publicKey.getEncoded());
+        SubjectPublicKeyInfo info = new SubjectPublicKeyInfo((ASN1Sequence) new ASN1InputStream(bais).readObject());
+        return new SubjectKeyIdentifier(info);
+    }
+
+    private static AuthorityKeyIdentifier createAuthorityKeyId(PublicKey publicKey) throws IOException {
+
+        ByteArrayInputStream bais = new ByteArrayInputStream(publicKey.getEncoded());
+        SubjectPublicKeyInfo info = new SubjectPublicKeyInfo((ASN1Sequence) new ASN1InputStream(bais).readObject());
+
+        return new AuthorityKeyIdentifier(info);
+    }
+
+    static X509Certificate generateCertificate(PublicKey subjectPublicKey, String subjectDn, DateTime notBefore, DateTime notAfter,
+                                    X509Certificate issuerCertificate, PrivateKey issuerPrivateKey, boolean caFlag, int pathLength, String crlUri,
+                                    String ocspUri, KeyUsage keyUsage) throws IOException, InvalidKeyException, IllegalStateException,
+                                    NoSuchAlgorithmException, SignatureException, CertificateException {
+        String signatureAlgorithm = "SHA1withRSA";
+        X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator();
+        certificateGenerator.reset();
+        certificateGenerator.setPublicKey(subjectPublicKey);
+        certificateGenerator.setSignatureAlgorithm(signatureAlgorithm);
+        certificateGenerator.setNotBefore(notBefore.toDate());
+        certificateGenerator.setNotAfter(notAfter.toDate());
+        X509Principal issuerDN;
+        if (null != issuerCertificate) {
+            issuerDN = new X509Principal(issuerCertificate.getSubjectX500Principal().toString());
+        } else {
+            issuerDN = new X509Principal(subjectDn);
+        }
+        certificateGenerator.setIssuerDN(issuerDN);
+        certificateGenerator.setSubjectDN(new X509Principal(subjectDn));
+        certificateGenerator.setSerialNumber(new BigInteger(128, new SecureRandom()));
+
+        certificateGenerator.addExtension(X509Extensions.SubjectKeyIdentifier, false, createSubjectKeyId(subjectPublicKey));
+        PublicKey issuerPublicKey;
+        issuerPublicKey = subjectPublicKey;
+        certificateGenerator.addExtension(X509Extensions.AuthorityKeyIdentifier, false, createAuthorityKeyId(issuerPublicKey));
+
+        if (caFlag) {
+            if (-1 == pathLength) {
+                certificateGenerator.addExtension(X509Extensions.BasicConstraints, false, new BasicConstraints(true));
+            } else {
+                certificateGenerator.addExtension(X509Extensions.BasicConstraints, false, new BasicConstraints(pathLength));
+            }
+        }
+
+        if (null != crlUri) {
+            GeneralName gn = new GeneralName(GeneralName.uniformResourceIdentifier, new DERIA5String(crlUri));
+            GeneralNames gns = new GeneralNames(new DERSequence(gn));
+            DistributionPointName dpn = new DistributionPointName(0, gns);
+            DistributionPoint distp = new DistributionPoint(dpn, null, null);
+            certificateGenerator.addExtension(X509Extensions.CRLDistributionPoints, false, new DERSequence(distp));
+        }
+
+        if (null != ocspUri) {
+            GeneralName ocspName = new GeneralName(GeneralName.uniformResourceIdentifier, ocspUri);
+            AuthorityInformationAccess authorityInformationAccess = new AuthorityInformationAccess(X509ObjectIdentifiers.ocspAccessMethod, ocspName);
+            certificateGenerator.addExtension(X509Extensions.AuthorityInfoAccess.getId(), false, authorityInformationAccess);
+        }
+
+        if (null != keyUsage) {
+            certificateGenerator.addExtension(X509Extensions.KeyUsage, true, keyUsage);
+        }
+
+        X509Certificate certificate;
+        certificate = certificateGenerator.generate(issuerPrivateKey);
+
+        /*
+         * Next certificate factory trick is needed to make sure that the
+         * certificate delivered to the caller is provided by the default
+         * security provider instead of BouncyCastle. If we don't do this trick
+         * we might run into trouble when trying to use the CertPath validator.
+         */
+        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
+        certificate = (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(certificate.getEncoded()));
+        return certificate;
+    }
+
+    static Document loadDocument(InputStream documentInputStream) throws ParserConfigurationException, SAXException, IOException {
+        InputSource inputSource = new InputSource(documentInputStream);
+        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+        documentBuilderFactory.setNamespaceAware(true);
+        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+        Document document = documentBuilder.parse(inputSource);
+        return document;
+    }
+
+    static String toString(Node dom) throws TransformerException {
+        Source source = new DOMSource(dom);
+        StringWriter stringWriter = new StringWriter();
+        Result result = new StreamResult(stringWriter);
+        TransformerFactory transformerFactory = TransformerFactory.newInstance();
+        Transformer transformer = transformerFactory.newTransformer();
+        /*
+         * We have to omit the ?xml declaration if we want to embed the
+         * document.
+         */
+        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+        transformer.transform(source, result);
+        return stringWriter.getBuffer().toString();
+    }
+}

Propchange: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/PkiTestUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/PkiTestUtils.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/PkiTestUtils.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TemporaryTestDataStorage.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TemporaryTestDataStorage.java?rev=824836&view=auto
==============================================================================
--- poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TemporaryTestDataStorage.java (added)
+++ poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TemporaryTestDataStorage.java Tue Oct 13 16:31:28 2009
@@ -0,0 +1,66 @@
+
+/* ====================================================================
+   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.
+==================================================================== */
+
+/*
+ * Based on the eID Applet Project code.
+ * Original Copyright (C) 2008-2009 FedICT.
+ */
+
+package org.apache.poi.ooxml.signature.service.signer;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.poi.ooxml.signature.service.signer.TemporaryDataStorage;
+
+
+
+class TemporaryTestDataStorage implements TemporaryDataStorage {
+
+    private ByteArrayOutputStream outputStream;
+
+    private Map<String, Serializable> attributes;
+
+    public TemporaryTestDataStorage() {
+        this.outputStream = new ByteArrayOutputStream();
+        this.attributes = new HashMap<String, Serializable>();
+    }
+
+    public InputStream getTempInputStream() {
+        byte[] data = this.outputStream.toByteArray();
+        ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
+        return inputStream;
+    }
+
+    public OutputStream getTempOutputStream() {
+        return this.outputStream;
+    }
+
+    public Serializable getAttribute(String attributeName) {
+        return this.attributes.get(attributeName);
+    }
+
+    public void setAttribute(String attributeName, Serializable attributeValue) {
+        this.attributes.put(attributeName, attributeValue);
+    }
+}
\ No newline at end of file

Propchange: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TemporaryTestDataStorage.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TemporaryTestDataStorage.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TemporaryTestDataStorage.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestAbstractOOXMLSignatureService.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestAbstractOOXMLSignatureService.java?rev=824836&view=auto
==============================================================================
--- poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestAbstractOOXMLSignatureService.java (added)
+++ poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestAbstractOOXMLSignatureService.java Tue Oct 13 16:31:28 2009
@@ -0,0 +1,214 @@
+
+/* ====================================================================
+   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.
+==================================================================== */
+
+/*
+ * Based on the eID Applet Project code.
+ * Original Copyright (C) 2008-2009 FedICT.
+ */
+
+package org.apache.poi.ooxml.signature.service.signer;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.OutputStream;
+import java.net.URL;
+import java.security.KeyPair;
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+import java.util.List;
+
+import javax.crypto.Cipher;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.poi.ooxml.signature.service.signer.TemporaryDataStorage;
+import org.apache.poi.ooxml.signature.service.signer.ooxml.AbstractOOXMLSignatureService;
+import org.apache.poi.ooxml.signature.service.signer.ooxml.OOXMLProvider;
+import org.apache.poi.ooxml.signature.service.signer.ooxml.OOXMLSignatureVerifier;
+import org.apache.poi.ooxml.signature.service.spi.DigestInfo;
+import org.bouncycastle.asn1.x509.KeyUsage;
+import org.joda.time.DateTime;
+
+
+
+public class TestAbstractOOXMLSignatureService extends TestCase {
+
+    private static final Log LOG = LogFactory.getLog(TestAbstractOOXMLSignatureService.class);
+
+    static {
+        OOXMLProvider.install();
+    }
+
+    private static class OOXMLTestSignatureService extends AbstractOOXMLSignatureService {
+
+        private final URL ooxmlUrl;
+
+        private final TemporaryTestDataStorage temporaryDataStorage;
+
+        private final ByteArrayOutputStream signedOOXMLOutputStream;
+
+        public OOXMLTestSignatureService(URL ooxmlUrl) {
+            this.temporaryDataStorage = new TemporaryTestDataStorage();
+            this.signedOOXMLOutputStream = new ByteArrayOutputStream();
+            this.ooxmlUrl = ooxmlUrl;
+        }
+
+        @Override
+        protected URL getOfficeOpenXMLDocumentURL() {
+            return this.ooxmlUrl;
+        }
+
+        @Override
+        protected OutputStream getSignedOfficeOpenXMLDocumentOutputStream() {
+            return this.signedOOXMLOutputStream;
+        }
+
+        public byte[] getSignedOfficeOpenXMLDocumentData() {
+            return this.signedOOXMLOutputStream.toByteArray();
+        }
+
+        @Override
+        protected TemporaryDataStorage getTemporaryDataStorage() {
+            return this.temporaryDataStorage;
+        }
+    }
+
+    public void testPreSign() throws Exception {
+        // setup
+        URL ooxmlUrl = TestAbstractOOXMLSignatureService.class.getResource("/hello-world-unsigned.docx");
+        assertNotNull(ooxmlUrl);
+
+        OOXMLTestSignatureService signatureService = new OOXMLTestSignatureService(ooxmlUrl);
+
+        // operate
+        DigestInfo digestInfo = signatureService.preSign(null, null);
+
+        // verify
+        assertNotNull(digestInfo);
+        LOG.debug("digest algo: " + digestInfo.digestAlgo);
+        LOG.debug("digest description: " + digestInfo.description);
+        assertEquals("Office OpenXML Document", digestInfo.description);
+        assertNotNull(digestInfo.digestAlgo);
+        assertNotNull(digestInfo.digestValue);
+
+        TemporaryDataStorage temporaryDataStorage = signatureService.getTemporaryDataStorage();
+        String preSignResult = IOUtils.toString(temporaryDataStorage.getTempInputStream());
+        LOG.debug("pre-sign result: " + preSignResult);
+        File tmpFile = File.createTempFile("ooxml-pre-sign-", ".xml");
+        FileUtils.writeStringToFile(tmpFile, preSignResult);
+        LOG.debug("tmp pre-sign file: " + tmpFile.getAbsolutePath());
+    }
+
+    public void testPostSign() throws Exception {
+        sign("/hello-world-unsigned.docx");
+    }
+
+    public void testSignOffice2010() throws Exception {
+        sign("/hello-world-office-2010-technical-preview-unsigned.docx");
+    }
+
+    public void testSignTwice() throws Exception {
+        sign("/hello-world-signed.docx", 2);
+    }
+
+    public void testSignTwiceHere() throws Exception {
+        File tmpFile = sign("/hello-world-unsigned.docx", 1);
+        sign(tmpFile.toURI().toURL(), "CN=Test2", 2);
+    }
+
+    public void testSignPowerpoint() throws Exception {
+        sign("/hello-world-unsigned.pptx");
+    }
+
+    public void testSignSpreadsheet() throws Exception {
+        sign("/hello-world-unsigned.xlsx");
+    }
+
+    private void sign(String documentResourceName) throws Exception {
+        sign(documentResourceName, 1);
+    }
+
+    private File sign(String documentResourceName, int signerCount) throws Exception {
+        URL ooxmlUrl = TestAbstractOOXMLSignatureService.class.getResource(documentResourceName);
+        return sign(ooxmlUrl, signerCount);
+    }
+
+    private File sign(URL ooxmlUrl, int signerCount) throws Exception {
+        return sign(ooxmlUrl, "CN=Test", signerCount);
+    }
+
+    private File sign(URL ooxmlUrl, String signerDn, int signerCount) throws Exception {
+        // setup
+        assertNotNull(ooxmlUrl);
+
+        OOXMLTestSignatureService signatureService = new OOXMLTestSignatureService(ooxmlUrl);
+
+        // operate
+        DigestInfo digestInfo = signatureService.preSign(null, null);
+
+        // verify
+        assertNotNull(digestInfo);
+        LOG.debug("digest algo: " + digestInfo.digestAlgo);
+        LOG.debug("digest description: " + digestInfo.description);
+        assertEquals("Office OpenXML Document", digestInfo.description);
+        assertNotNull(digestInfo.digestAlgo);
+        assertNotNull(digestInfo.digestValue);
+
+        TemporaryDataStorage temporaryDataStorage = signatureService.getTemporaryDataStorage();
+        String preSignResult = IOUtils.toString(temporaryDataStorage.getTempInputStream());
+        LOG.debug("pre-sign result: " + preSignResult);
+        File tmpFile = File.createTempFile("ooxml-pre-sign-", ".xml");
+        FileUtils.writeStringToFile(tmpFile, preSignResult);
+        LOG.debug("tmp pre-sign file: " + tmpFile.getAbsolutePath());
+
+        // setup: key material, signature value
+        KeyPair keyPair = PkiTestUtils.generateKeyPair();
+        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+        cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
+        byte[] digestInfoValue = ArrayUtils.addAll(PkiTestUtils.SHA1_DIGEST_INFO_PREFIX, digestInfo.digestValue);
+        byte[] signatureValue = cipher.doFinal(digestInfoValue);
+
+        DateTime notBefore = new DateTime();
+        DateTime notAfter = notBefore.plusYears(1);
+        X509Certificate certificate = PkiTestUtils.generateCertificate(keyPair.getPublic(), signerDn, notBefore, notAfter, null, keyPair.getPrivate(), true, 0,
+                                        null, null, new KeyUsage(KeyUsage.nonRepudiation));
+
+        // operate: postSign
+        signatureService.postSign(signatureValue, Collections.singletonList(certificate));
+
+        // verify: signature
+        byte[] signedOOXMLData = signatureService.getSignedOfficeOpenXMLDocumentData();
+        assertNotNull(signedOOXMLData);
+        LOG.debug("signed OOXML size: " + signedOOXMLData.length);
+        String extension = FilenameUtils.getExtension(ooxmlUrl.getFile());
+        tmpFile = File.createTempFile("ooxml-signed-", "." + extension);
+        FileUtils.writeByteArrayToFile(tmpFile, signedOOXMLData);
+        LOG.debug("signed OOXML file: " + tmpFile.getAbsolutePath());
+        List<X509Certificate> signers = OOXMLSignatureVerifier.getSigners(tmpFile.toURI().toURL());
+        assertEquals(signerCount, signers.size());
+        // assertEquals(certificate, signers.get(0));
+        LOG.debug("signed OOXML file: " + tmpFile.getAbsolutePath());
+        return tmpFile;
+    }
+}

Propchange: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestAbstractOOXMLSignatureService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestAbstractOOXMLSignatureService.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestAbstractOOXMLSignatureService.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestAbstractXmlSignatureService.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestAbstractXmlSignatureService.java?rev=824836&view=auto
==============================================================================
--- poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestAbstractXmlSignatureService.java (added)
+++ poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestAbstractXmlSignatureService.java Tue Oct 13 16:31:28 2009
@@ -0,0 +1,560 @@
+
+/* ====================================================================
+   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.
+==================================================================== */
+
+/*
+ * Based on the eID Applet Project code.
+ * Original Copyright (C) 2008-2009 FedICT.
+ */
+
+package org.apache.poi.ooxml.signature.service.signer;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.KeyPair;
+import java.security.MessageDigest;
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.crypto.Cipher;
+import javax.xml.crypto.Data;
+import javax.xml.crypto.KeySelector;
+import javax.xml.crypto.OctetStreamData;
+import javax.xml.crypto.URIDereferencer;
+import javax.xml.crypto.URIReference;
+import javax.xml.crypto.URIReferenceException;
+import javax.xml.crypto.XMLCryptoContext;
+import javax.xml.crypto.dom.DOMCryptoContext;
+import javax.xml.crypto.dsig.CanonicalizationMethod;
+import javax.xml.crypto.dsig.DigestMethod;
+import javax.xml.crypto.dsig.Reference;
+import javax.xml.crypto.dsig.SignatureMethod;
+import javax.xml.crypto.dsig.SignedInfo;
+import javax.xml.crypto.dsig.XMLSignContext;
+import javax.xml.crypto.dsig.XMLSignature;
+import javax.xml.crypto.dsig.XMLSignatureFactory;
+import javax.xml.crypto.dsig.dom.DOMSignContext;
+import javax.xml.crypto.dsig.dom.DOMValidateContext;
+import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.poi.ooxml.signature.service.spi.DigestInfo;
+import org.apache.xml.security.utils.Constants;
+import org.apache.xpath.XPathAPI;
+import org.bouncycastle.asn1.x509.KeyUsage;
+import org.jcp.xml.dsig.internal.dom.DOMReference;
+import org.jcp.xml.dsig.internal.dom.DOMXMLSignature;
+import org.joda.time.DateTime;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+
+
+public class TestAbstractXmlSignatureService extends TestCase {
+
+    private static final Log LOG = LogFactory.getLog(TestAbstractXmlSignatureService.class);
+
+    private static class XmlSignatureTestService extends AbstractXmlSignatureService {
+
+        private Document envelopingDocument;
+
+        private List<String> referenceUris;
+
+        private TemporaryTestDataStorage temporaryDataStorage;
+
+        private String signatureDescription;
+
+        private ByteArrayOutputStream signedDocumentOutputStream;
+
+        private URIDereferencer uriDereferencer;
+
+        public XmlSignatureTestService() {
+            super();
+            this.referenceUris = new LinkedList<String>();
+            this.temporaryDataStorage = new TemporaryTestDataStorage();
+            this.signedDocumentOutputStream = new ByteArrayOutputStream();
+        }
+
+        public byte[] getSignedDocumentData() {
+            return this.signedDocumentOutputStream.toByteArray();
+        }
+
+        public void setEnvelopingDocument(Document envelopingDocument) {
+            this.envelopingDocument = envelopingDocument;
+        }
+
+        @Override
+        protected Document getEnvelopingDocument() {
+            return this.envelopingDocument;
+        }
+
+        @Override
+        protected String getSignatureDescription() {
+            return this.signatureDescription;
+        }
+
+        public void setSignatureDescription(String signatureDescription) {
+            this.signatureDescription = signatureDescription;
+        }
+
+        @Override
+        protected List<String> getReferenceUris() {
+            return this.referenceUris;
+        }
+
+        public void addReferenceUri(String referenceUri) {
+            this.referenceUris.add(referenceUri);
+        }
+
+        @Override
+        protected OutputStream getSignedDocumentOutputStream() {
+            return this.signedDocumentOutputStream;
+        }
+
+        @Override
+        protected TemporaryDataStorage getTemporaryDataStorage() {
+            return this.temporaryDataStorage;
+        }
+
+        public String getFilesDigestAlgorithm() {
+            return null;
+        }
+
+        @Override
+        protected URIDereferencer getURIDereferencer() {
+            return this.uriDereferencer;
+        }
+
+        public void setUriDereferencer(URIDereferencer uriDereferencer) {
+            this.uriDereferencer = uriDereferencer;
+        }
+    }
+
+    public void testSignEnvelopingDocument() throws Exception {
+        // setup
+        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+        documentBuilderFactory.setNamespaceAware(true);
+        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+        Document document = documentBuilder.newDocument();
+        Element rootElement = document.createElementNS("urn:test", "tns:root");
+        rootElement.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:tns", "urn:test");
+        document.appendChild(rootElement);
+        Element dataElement = document.createElementNS("urn:test", "tns:data");
+        dataElement.setAttributeNS(null, "Id", "id-1234");
+        dataElement.setTextContent("data to be signed");
+        rootElement.appendChild(dataElement);
+
+        XmlSignatureTestService testedInstance = new XmlSignatureTestService();
+        testedInstance.setEnvelopingDocument(document);
+        testedInstance.addReferenceUri("#id-1234");
+        testedInstance.setSignatureDescription("test-signature-description");
+
+        // operate
+        DigestInfo digestInfo = testedInstance.preSign(null, null);
+
+        // verify
+        assertNotNull(digestInfo);
+        LOG.debug("digest info description: " + digestInfo.description);
+        assertEquals("test-signature-description", digestInfo.description);
+        assertNotNull(digestInfo.digestValue);
+        LOG.debug("digest algo: " + digestInfo.digestAlgo);
+        assertEquals("SHA-1", digestInfo.digestAlgo);
+
+        TemporaryTestDataStorage temporaryDataStorage = (TemporaryTestDataStorage) testedInstance.getTemporaryDataStorage();
+        assertNotNull(temporaryDataStorage);
+        InputStream tempInputStream = temporaryDataStorage.getTempInputStream();
+        assertNotNull(tempInputStream);
+        Document tmpDocument = PkiTestUtils.loadDocument(tempInputStream);
+
+        LOG.debug("tmp document: " + PkiTestUtils.toString(tmpDocument));
+        Element nsElement = tmpDocument.createElement("ns");
+        nsElement.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:ds", Constants.SignatureSpecNS);
+        Node digestValueNode = XPathAPI.selectSingleNode(tmpDocument, "//ds:DigestValue", nsElement);
+        assertNotNull(digestValueNode);
+        String digestValueTextContent = digestValueNode.getTextContent();
+        LOG.debug("digest value text content: " + digestValueTextContent);
+        assertFalse(digestValueTextContent.isEmpty());
+
+        /*
+         * Sign the received XML signature digest value.
+         */
+        KeyPair keyPair = PkiTestUtils.generateKeyPair();
+        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+        cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
+        byte[] digestInfoValue = ArrayUtils.addAll(PkiTestUtils.SHA1_DIGEST_INFO_PREFIX, digestInfo.digestValue);
+        byte[] signatureValue = cipher.doFinal(digestInfoValue);
+
+        DateTime notBefore = new DateTime();
+        DateTime notAfter = notBefore.plusYears(1);
+        X509Certificate certificate = PkiTestUtils.generateCertificate(keyPair.getPublic(), "CN=Test", notBefore, notAfter, null, keyPair.getPrivate(), true,
+                                        0, null, null, new KeyUsage(KeyUsage.nonRepudiation));
+
+        /*
+         * Operate: postSign
+         */
+        testedInstance.postSign(signatureValue, Collections.singletonList(certificate));
+
+        byte[] signedDocumentData = testedInstance.getSignedDocumentData();
+        assertNotNull(signedDocumentData);
+        Document signedDocument = PkiTestUtils.loadDocument(new ByteArrayInputStream(signedDocumentData));
+        LOG.debug("signed document: " + PkiTestUtils.toString(signedDocument));
+
+        NodeList signatureNodeList = signedDocument.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
+        assertEquals(1, signatureNodeList.getLength());
+        Node signatureNode = signatureNodeList.item(0);
+
+        DOMValidateContext domValidateContext = new DOMValidateContext(KeySelector.singletonKeySelector(keyPair.getPublic()), signatureNode);
+        XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance();
+        XMLSignature xmlSignature = xmlSignatureFactory.unmarshalXMLSignature(domValidateContext);
+        boolean validity = xmlSignature.validate(domValidateContext);
+        assertTrue(validity);
+    }
+
+    public static class UriTestDereferencer implements URIDereferencer {
+
+        private final Map<String, byte[]> resources;
+
+        public UriTestDereferencer() {
+            this.resources = new HashMap<String, byte[]>();
+        }
+
+        public void addResource(String uri, byte[] data) {
+            this.resources.put(uri, data);
+        }
+
+        public Data dereference(URIReference uriReference, XMLCryptoContext xmlCryptoContext) throws URIReferenceException {
+            String uri = uriReference.getURI();
+            byte[] data = this.resources.get(uri);
+            if (null == data) {
+                return null;
+            }
+            return new OctetStreamData(new ByteArrayInputStream(data));
+        }
+    }
+
+    public void testSignExternalUri() throws Exception {
+        // setup
+        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+        documentBuilderFactory.setNamespaceAware(true);
+        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+        Document document = documentBuilder.newDocument();
+
+        XmlSignatureTestService testedInstance = new XmlSignatureTestService();
+        testedInstance.setEnvelopingDocument(document);
+        testedInstance.addReferenceUri("external-uri");
+        testedInstance.setSignatureDescription("test-signature-description");
+        UriTestDereferencer uriDereferencer = new UriTestDereferencer();
+        uriDereferencer.addResource("external-uri", "hello world".getBytes());
+        testedInstance.setUriDereferencer(uriDereferencer);
+
+        // operate
+        DigestInfo digestInfo = testedInstance.preSign(null, null);
+
+        // verify
+        assertNotNull(digestInfo);
+        LOG.debug("digest info description: " + digestInfo.description);
+        assertEquals("test-signature-description", digestInfo.description);
+        assertNotNull(digestInfo.digestValue);
+        LOG.debug("digest algo: " + digestInfo.digestAlgo);
+        assertEquals("SHA-1", digestInfo.digestAlgo);
+
+        TemporaryTestDataStorage temporaryDataStorage = (TemporaryTestDataStorage) testedInstance.getTemporaryDataStorage();
+        assertNotNull(temporaryDataStorage);
+        InputStream tempInputStream = temporaryDataStorage.getTempInputStream();
+        assertNotNull(tempInputStream);
+        Document tmpDocument = PkiTestUtils.loadDocument(tempInputStream);
+
+        LOG.debug("tmp document: " + PkiTestUtils.toString(tmpDocument));
+        Element nsElement = tmpDocument.createElement("ns");
+        nsElement.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:ds", Constants.SignatureSpecNS);
+        Node digestValueNode = XPathAPI.selectSingleNode(tmpDocument, "//ds:DigestValue", nsElement);
+        assertNotNull(digestValueNode);
+        String digestValueTextContent = digestValueNode.getTextContent();
+        LOG.debug("digest value text content: " + digestValueTextContent);
+        assertFalse(digestValueTextContent.isEmpty());
+
+        /*
+         * Sign the received XML signature digest value.
+         */
+        KeyPair keyPair = PkiTestUtils.generateKeyPair();
+        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+        cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
+        byte[] digestInfoValue = ArrayUtils.addAll(PkiTestUtils.SHA1_DIGEST_INFO_PREFIX, digestInfo.digestValue);
+        byte[] signatureValue = cipher.doFinal(digestInfoValue);
+
+        DateTime notBefore = new DateTime();
+        DateTime notAfter = notBefore.plusYears(1);
+        X509Certificate certificate = PkiTestUtils.generateCertificate(keyPair.getPublic(), "CN=Test", notBefore, notAfter, null, keyPair.getPrivate(), true,
+                                        0, null, null, new KeyUsage(KeyUsage.nonRepudiation));
+
+        /*
+         * Operate: postSign
+         */
+        testedInstance.postSign(signatureValue, Collections.singletonList(certificate));
+
+        byte[] signedDocumentData = testedInstance.getSignedDocumentData();
+        assertNotNull(signedDocumentData);
+        Document signedDocument = PkiTestUtils.loadDocument(new ByteArrayInputStream(signedDocumentData));
+        LOG.debug("signed document: " + PkiTestUtils.toString(signedDocument));
+
+        NodeList signatureNodeList = signedDocument.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
+        assertEquals(1, signatureNodeList.getLength());
+        Node signatureNode = signatureNodeList.item(0);
+
+        DOMValidateContext domValidateContext = new DOMValidateContext(KeySelector.singletonKeySelector(keyPair.getPublic()), signatureNode);
+        domValidateContext.setURIDereferencer(uriDereferencer);
+        XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance();
+        XMLSignature xmlSignature = xmlSignatureFactory.unmarshalXMLSignature(domValidateContext);
+        boolean validity = xmlSignature.validate(domValidateContext);
+        assertTrue(validity);
+    }
+
+    public void testSignEnvelopingDocumentWithExternalDigestInfo() throws Exception {
+        // setup
+        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+        documentBuilderFactory.setNamespaceAware(true);
+        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+        Document document = documentBuilder.newDocument();
+        Element rootElement = document.createElementNS("urn:test", "tns:root");
+        rootElement.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:tns", "urn:test");
+        document.appendChild(rootElement);
+
+        XmlSignatureTestService testedInstance = new XmlSignatureTestService();
+        testedInstance.setEnvelopingDocument(document);
+        testedInstance.setSignatureDescription("test-signature-description");
+
+        byte[] refData = "hello world".getBytes();
+        MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
+        messageDigest.update(refData);
+        byte[] digestValue = messageDigest.digest();
+        DigestInfo refDigestInfo = new DigestInfo(digestValue, "SHA-1", "urn:test:ref");
+
+        // operate
+        DigestInfo digestInfo = testedInstance.preSign(Collections.singletonList(refDigestInfo), null);
+
+        // verify
+        assertNotNull(digestInfo);
+        LOG.debug("digest info description: " + digestInfo.description);
+        assertEquals("test-signature-description", digestInfo.description);
+        assertNotNull(digestInfo.digestValue);
+        LOG.debug("digest algo: " + digestInfo.digestAlgo);
+        assertEquals("SHA-1", digestInfo.digestAlgo);
+
+        TemporaryTestDataStorage temporaryDataStorage = (TemporaryTestDataStorage) testedInstance.getTemporaryDataStorage();
+        assertNotNull(temporaryDataStorage);
+        InputStream tempInputStream = temporaryDataStorage.getTempInputStream();
+        assertNotNull(tempInputStream);
+        Document tmpDocument = PkiTestUtils.loadDocument(tempInputStream);
+
+        LOG.debug("tmp document: " + PkiTestUtils.toString(tmpDocument));
+        Element nsElement = tmpDocument.createElement("ns");
+        nsElement.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:ds", Constants.SignatureSpecNS);
+        Node digestValueNode = XPathAPI.selectSingleNode(tmpDocument, "//ds:DigestValue", nsElement);
+        assertNotNull(digestValueNode);
+        String digestValueTextContent = digestValueNode.getTextContent();
+        LOG.debug("digest value text content: " + digestValueTextContent);
+        assertFalse(digestValueTextContent.isEmpty());
+
+        /*
+         * Sign the received XML signature digest value.
+         */
+        KeyPair keyPair = PkiTestUtils.generateKeyPair();
+        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+        cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
+        byte[] digestInfoValue = ArrayUtils.addAll(PkiTestUtils.SHA1_DIGEST_INFO_PREFIX, digestInfo.digestValue);
+        byte[] signatureValue = cipher.doFinal(digestInfoValue);
+
+        DateTime notBefore = new DateTime();
+        DateTime notAfter = notBefore.plusYears(1);
+        X509Certificate certificate = PkiTestUtils.generateCertificate(keyPair.getPublic(), "CN=Test", notBefore, notAfter, null, keyPair.getPrivate(), true,
+                                        0, null, null, new KeyUsage(KeyUsage.nonRepudiation));
+
+        /*
+         * Operate: postSign
+         */
+        testedInstance.postSign(signatureValue, Collections.singletonList(certificate));
+
+        byte[] signedDocumentData = testedInstance.getSignedDocumentData();
+        assertNotNull(signedDocumentData);
+        Document signedDocument = PkiTestUtils.loadDocument(new ByteArrayInputStream(signedDocumentData));
+        LOG.debug("signed document: " + PkiTestUtils.toString(signedDocument));
+
+        NodeList signatureNodeList = signedDocument.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
+        assertEquals(1, signatureNodeList.getLength());
+        Node signatureNode = signatureNodeList.item(0);
+
+        DOMValidateContext domValidateContext = new DOMValidateContext(KeySelector.singletonKeySelector(keyPair.getPublic()), signatureNode);
+        URIDereferencer dereferencer = new URITest2Dereferencer();
+        domValidateContext.setURIDereferencer(dereferencer);
+        XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance();
+        XMLSignature xmlSignature = xmlSignatureFactory.unmarshalXMLSignature(domValidateContext);
+        boolean validity = xmlSignature.validate(domValidateContext);
+        assertTrue(validity);
+    }
+
+    public void testSignExternalDigestInfo() throws Exception {
+        // setup
+        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+        documentBuilderFactory.setNamespaceAware(true);
+        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+        Document document = documentBuilder.newDocument();
+
+        XmlSignatureTestService testedInstance = new XmlSignatureTestService();
+        testedInstance.setEnvelopingDocument(document);
+        testedInstance.setSignatureDescription("test-signature-description");
+
+        byte[] refData = "hello world".getBytes();
+        MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
+        messageDigest.update(refData);
+        byte[] digestValue = messageDigest.digest();
+        DigestInfo refDigestInfo = new DigestInfo(digestValue, "SHA-1", "urn:test:ref");
+
+        // operate
+        DigestInfo digestInfo = testedInstance.preSign(Collections.singletonList(refDigestInfo), null);
+
+        // verify
+        assertNotNull(digestInfo);
+        LOG.debug("digest info description: " + digestInfo.description);
+        assertEquals("test-signature-description", digestInfo.description);
+        assertNotNull(digestInfo.digestValue);
+        LOG.debug("digest algo: " + digestInfo.digestAlgo);
+        assertEquals("SHA-1", digestInfo.digestAlgo);
+
+        TemporaryTestDataStorage temporaryDataStorage = (TemporaryTestDataStorage) testedInstance.getTemporaryDataStorage();
+        assertNotNull(temporaryDataStorage);
+        InputStream tempInputStream = temporaryDataStorage.getTempInputStream();
+        assertNotNull(tempInputStream);
+        Document tmpDocument = PkiTestUtils.loadDocument(tempInputStream);
+
+        LOG.debug("tmp document: " + PkiTestUtils.toString(tmpDocument));
+        Element nsElement = tmpDocument.createElement("ns");
+        nsElement.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:ds", Constants.SignatureSpecNS);
+        Node digestValueNode = XPathAPI.selectSingleNode(tmpDocument, "//ds:DigestValue", nsElement);
+        assertNotNull(digestValueNode);
+        String digestValueTextContent = digestValueNode.getTextContent();
+        LOG.debug("digest value text content: " + digestValueTextContent);
+        assertFalse(digestValueTextContent.isEmpty());
+
+        /*
+         * Sign the received XML signature digest value.
+         */
+        KeyPair keyPair = PkiTestUtils.generateKeyPair();
+        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+        cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
+        byte[] digestInfoValue = ArrayUtils.addAll(PkiTestUtils.SHA1_DIGEST_INFO_PREFIX, digestInfo.digestValue);
+        byte[] signatureValue = cipher.doFinal(digestInfoValue);
+
+        DateTime notBefore = new DateTime();
+        DateTime notAfter = notBefore.plusYears(1);
+        X509Certificate certificate = PkiTestUtils.generateCertificate(keyPair.getPublic(), "CN=Test", notBefore, notAfter, null, keyPair.getPrivate(), true,
+                                        0, null, null, new KeyUsage(KeyUsage.nonRepudiation));
+
+        /*
+         * Operate: postSign
+         */
+        testedInstance.postSign(signatureValue, Collections.singletonList(certificate));
+
+        byte[] signedDocumentData = testedInstance.getSignedDocumentData();
+        assertNotNull(signedDocumentData);
+        Document signedDocument = PkiTestUtils.loadDocument(new ByteArrayInputStream(signedDocumentData));
+        LOG.debug("signed document: " + PkiTestUtils.toString(signedDocument));
+
+        NodeList signatureNodeList = signedDocument.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
+        assertEquals(1, signatureNodeList.getLength());
+        Node signatureNode = signatureNodeList.item(0);
+
+        DOMValidateContext domValidateContext = new DOMValidateContext(KeySelector.singletonKeySelector(keyPair.getPublic()), signatureNode);
+        URIDereferencer dereferencer = new URITest2Dereferencer();
+        domValidateContext.setURIDereferencer(dereferencer);
+        XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance();
+        XMLSignature xmlSignature = xmlSignatureFactory.unmarshalXMLSignature(domValidateContext);
+        boolean validity = xmlSignature.validate(domValidateContext);
+        assertTrue(validity);
+    }
+
+    private static class URITest2Dereferencer implements URIDereferencer {
+
+        private static final Log LOG = LogFactory.getLog(URITest2Dereferencer.class);
+
+        public Data dereference(URIReference uriReference, XMLCryptoContext context) throws URIReferenceException {
+            LOG.debug("dereference: " + uriReference.getURI());
+            return new OctetStreamData(new ByteArrayInputStream("hello world".getBytes()));
+        }
+    }
+
+    public void testJsr105Signature() throws Exception {
+        KeyPair keyPair = PkiTestUtils.generateKeyPair();
+
+        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+        documentBuilderFactory.setNamespaceAware(true);
+        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+        Document document = documentBuilder.newDocument();
+        Element rootElement = document.createElementNS("urn:test", "tns:root");
+        rootElement.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:tns", "urn:test");
+        document.appendChild(rootElement);
+        Element dataElement = document.createElementNS("urn:test", "tns:data");
+        dataElement.setAttributeNS(null, "Id", "id-1234");
+        dataElement.setTextContent("data to be signed");
+        rootElement.appendChild(dataElement);
+
+        XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM", new org.jcp.xml.dsig.internal.dom.XMLDSigRI());
+
+        XMLSignContext signContext = new DOMSignContext(keyPair.getPrivate(), document.getDocumentElement());
+        signContext.putNamespacePrefix(javax.xml.crypto.dsig.XMLSignature.XMLNS, "ds");
+
+        DigestMethod digestMethod = signatureFactory.newDigestMethod(DigestMethod.SHA1, null);
+        Reference reference = signatureFactory.newReference("#id-1234", digestMethod);
+        DOMReference domReference = (DOMReference) reference;
+        assertNull(domReference.getCalculatedDigestValue());
+        assertNull(domReference.getDigestValue());
+
+        SignatureMethod signatureMethod = signatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null);
+        CanonicalizationMethod canonicalizationMethod = signatureFactory.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE_WITH_COMMENTS,
+                                        (C14NMethodParameterSpec) null);
+        SignedInfo signedInfo = signatureFactory.newSignedInfo(canonicalizationMethod, signatureMethod, Collections.singletonList(reference));
+
+        javax.xml.crypto.dsig.XMLSignature xmlSignature = signatureFactory.newXMLSignature(signedInfo, null);
+
+        DOMXMLSignature domXmlSignature = (DOMXMLSignature) xmlSignature;
+        domXmlSignature.marshal(document.getDocumentElement(), "ds", (DOMCryptoContext) signContext);
+        domReference.digest(signContext);
+        // xmlSignature.sign(signContext);
+        // LOG.debug("signed document: " + toString(document));
+
+        Element nsElement = document.createElement("ns");
+        nsElement.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:ds", Constants.SignatureSpecNS);
+        Node digestValueNode = XPathAPI.selectSingleNode(document, "//ds:DigestValue", nsElement);
+        assertNotNull(digestValueNode);
+        String digestValueTextContent = digestValueNode.getTextContent();
+        LOG.debug("digest value text content: " + digestValueTextContent);
+        assertFalse(digestValueTextContent.isEmpty());
+    }
+}

Propchange: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestAbstractXmlSignatureService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestAbstractXmlSignatureService.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestAbstractXmlSignatureService.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestOOXMLSignatureVerifier.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestOOXMLSignatureVerifier.java?rev=824836&view=auto
==============================================================================
--- poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestOOXMLSignatureVerifier.java (added)
+++ poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestOOXMLSignatureVerifier.java Tue Oct 13 16:31:28 2009
@@ -0,0 +1,238 @@
+
+/* ====================================================================
+   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.
+==================================================================== */
+
+/*
+ * Based on the eID Applet Project code.
+ * Original Copyright (C) 2008-2009 FedICT.
+ */
+
+package org.apache.poi.ooxml.signature.service.signer;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.poi.POIXMLDocument;
+import org.apache.poi.ooxml.signature.service.signer.ooxml.OOXMLProvider;
+import org.apache.poi.ooxml.signature.service.signer.ooxml.OOXMLSignatureVerifier;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.openxml4j.opc.signature.PackageDigitalSignatureManager;
+
+
+
+public class TestOOXMLSignatureVerifier extends TestCase {
+
+    private static final Log LOG = LogFactory.getLog(TestOOXMLSignatureVerifier.class);
+
+    static {
+        OOXMLProvider.install();
+    }
+
+    public void testIsOOXMLDocument() throws Exception {
+        // setup
+        URL url = TestOOXMLSignatureVerifier.class.getResource("/hello-world-unsigned.docx");
+
+        // operate
+        boolean result = OOXMLSignatureVerifier.isOOXML(url);
+
+        // verify
+        assertTrue(result);
+    }
+
+    public void testPOI() throws Exception {
+        // setup
+        InputStream inputStream = TestOOXMLSignatureVerifier.class.getResourceAsStream("/hello-world-unsigned.docx");
+
+        // operate
+        boolean result = POIXMLDocument.hasOOXMLHeader(inputStream);
+
+        // verify
+        assertTrue(result);
+    }
+
+    public void testOPC() throws Exception {
+        // setup
+        InputStream inputStream = TestOOXMLSignatureVerifier.class.getResourceAsStream("/hello-world-signed.docx");
+
+        // operate
+        OPCPackage opcPackage = OPCPackage.open(inputStream);
+
+        ArrayList<PackagePart> parts = opcPackage.getParts();
+        for (PackagePart part : parts) {
+            LOG.debug("part name: " + part.getPartName().getName());
+            LOG.debug("part content type: " + part.getContentType());
+        }
+
+        ArrayList<PackagePart> signatureParts = opcPackage.getPartsByContentType("application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml");
+        assertFalse(signatureParts.isEmpty());
+
+        PackagePart signaturePart = signatureParts.get(0);
+        LOG.debug("signature part class type: " + signaturePart.getClass().getName());
+
+        PackageDigitalSignatureManager packageDigitalSignatureManager = new PackageDigitalSignatureManager();
+        // yeah... POI implementation still missing
+    }
+
+    public void testGetSignerUnsigned() throws Exception {
+        // setup
+        URL url = TestOOXMLSignatureVerifier.class.getResource("/hello-world-unsigned.docx");
+
+        // operate
+        List<X509Certificate> result = OOXMLSignatureVerifier.getSigners(url);
+
+        // verify
+        assertNotNull(result);
+        assertTrue(result.isEmpty());
+    }
+
+    public void testGetSignerOffice2010Unsigned() throws Exception {
+        // setup
+        URL url = TestOOXMLSignatureVerifier.class.getResource("/hello-world-office-2010-technical-preview-unsigned.docx");
+
+        // operate
+        List<X509Certificate> result = OOXMLSignatureVerifier.getSigners(url);
+
+        // verify
+        assertNotNull(result);
+        assertTrue(result.isEmpty());
+    }
+
+    public void testGetSignerUnsignedPowerpoint() throws Exception {
+        // setup
+        URL url = TestOOXMLSignatureVerifier.class.getResource("/hello-world-unsigned.pptx");
+
+        // operate
+        List<X509Certificate> result = OOXMLSignatureVerifier.getSigners(url);
+
+        // verify
+        assertNotNull(result);
+        assertTrue(result.isEmpty());
+    }
+
+    public void testGetSignerUnsignedExcel() throws Exception {
+        // setup
+        URL url = TestOOXMLSignatureVerifier.class.getResource("/hello-world-unsigned.xlsx");
+
+        // operate
+        List<X509Certificate> result = OOXMLSignatureVerifier.getSigners(url);
+
+        // verify
+        assertNotNull(result);
+        assertTrue(result.isEmpty());
+    }
+
+    public void testGetSigner() throws Exception {
+        // setup
+        URL url = TestOOXMLSignatureVerifier.class.getResource("/hello-world-signed.docx");
+
+        // operate
+        List<X509Certificate> result = OOXMLSignatureVerifier.getSigners(url);
+
+        // verify
+        assertNotNull(result);
+        assertEquals(1, result.size());
+        X509Certificate signer = result.get(0);
+        LOG.debug("signer: " + signer.getSubjectX500Principal());
+    }
+
+    public void testOffice2010TechnicalPreview() throws Exception {
+        // setup
+        URL url = TestOOXMLSignatureVerifier.class.getResource("/hello-world-office-2010-technical-preview.docx");
+
+        // operate
+        List<X509Certificate> result = OOXMLSignatureVerifier.getSigners(url);
+
+        // verify
+        assertNotNull(result);
+        assertEquals(1, result.size());
+        X509Certificate signer = result.get(0);
+        LOG.debug("signer: " + signer.getSubjectX500Principal());
+    }
+
+    public void testGetSignerPowerpoint() throws Exception {
+        // setup
+        URL url = TestOOXMLSignatureVerifier.class.getResource("/hello-world-signed.pptx");
+
+        // operate
+        List<X509Certificate> result = OOXMLSignatureVerifier.getSigners(url);
+
+        // verify
+        assertNotNull(result);
+        assertEquals(1, result.size());
+        X509Certificate signer = result.get(0);
+        LOG.debug("signer: " + signer.getSubjectX500Principal());
+    }
+
+    public void testGetSignerExcel() throws Exception {
+        // setup
+        URL url = TestOOXMLSignatureVerifier.class.getResource("/hello-world-signed.xlsx");
+
+        // operate
+        List<X509Certificate> result = OOXMLSignatureVerifier.getSigners(url);
+
+        // verify
+        assertNotNull(result);
+        assertEquals(1, result.size());
+        X509Certificate signer = result.get(0);
+        LOG.debug("signer: " + signer.getSubjectX500Principal());
+    }
+
+    public void testGetSigners() throws Exception {
+        // setup
+        URL url = TestOOXMLSignatureVerifier.class.getResource("/hello-world-signed-twice.docx");
+
+        // operate
+        List<X509Certificate> result = OOXMLSignatureVerifier.getSigners(url);
+
+        // verify
+        assertNotNull(result);
+        assertEquals(2, result.size());
+        X509Certificate signer1 = result.get(0);
+        X509Certificate signer2 = result.get(1);
+        LOG.debug("signer 1: " + signer1.getSubjectX500Principal());
+        LOG.debug("signer 2: " + signer2.getSubjectX500Principal());
+    }
+
+    public void testVerifySignature() throws Exception {
+
+        java.util.logging.Logger logger = java.util.logging.Logger.getLogger("org.jcp.xml.dsig.internal.dom");
+        logger.log(Level.FINE, "test");
+
+        URL url = TestOOXMLSignatureVerifier.class.getResource("/hello-world-signed.docx");
+        boolean validity = OOXMLSignatureVerifier.verifySignature(url);
+        assertTrue(validity);
+    }
+
+    public void testTamperedFile() throws Exception {
+
+        java.util.logging.Logger logger = java.util.logging.Logger.getLogger("org.jcp.xml.dsig.internal.dom");
+        logger.log(Level.FINE, "test");
+
+        URL url = TestOOXMLSignatureVerifier.class.getResource("/invalidsig.docx");
+        boolean validity = OOXMLSignatureVerifier.verifySignature(url);
+        assertFalse(validity);
+    }
+}

Propchange: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestOOXMLSignatureVerifier.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestOOXMLSignatureVerifier.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: poi/trunk/src/ooxml/testcases/org/apache/poi/ooxml/signature/service/signer/TestOOXMLSignatureVerifier.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



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