]> source.dussan.org Git - poi.git/blob
d6cc51c65a372e9f46782e0a893a6c6e3b5bb085
[poi.git] /
1
2 /* ====================================================================
3    Licensed to the Apache Software Foundation (ASF) under one or more
4    contributor license agreements.  See the NOTICE file distributed with
5    this work for additional information regarding copyright ownership.
6    The ASF licenses this file to You under the Apache License, Version 2.0
7    (the "License"); you may not use this file except in compliance with
8    the License.  You may obtain a copy of the License at
9
10        http://www.apache.org/licenses/LICENSE-2.0
11
12    Unless required by applicable law or agreed to in writing, software
13    distributed under the License is distributed on an "AS IS" BASIS,
14    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15    See the License for the specific language governing permissions and
16    limitations under the License.
17 ==================================================================== */
18
19 /*
20  * Based on the eID Applet Project code.
21  * Original Copyright (C) 2008-2009 FedICT.
22  */
23
24 package org.apache.poi.ooxml.signature.service.signer;
25
26 import java.io.ByteArrayOutputStream;
27 import java.io.File;
28 import java.io.OutputStream;
29 import java.net.URL;
30 import java.security.KeyPair;
31 import java.security.cert.X509Certificate;
32 import java.util.Collections;
33 import java.util.List;
34
35 import javax.crypto.Cipher;
36
37 import junit.framework.TestCase;
38
39 import org.apache.commons.io.FileUtils;
40 import org.apache.commons.io.FilenameUtils;
41 import org.apache.commons.io.IOUtils;
42 import org.apache.commons.lang.ArrayUtils;
43 import org.apache.commons.logging.Log;
44 import org.apache.commons.logging.LogFactory;
45 import org.apache.poi.ooxml.signature.service.signer.TemporaryDataStorage;
46 import org.apache.poi.ooxml.signature.service.signer.ooxml.AbstractOOXMLSignatureService;
47 import org.apache.poi.ooxml.signature.service.signer.ooxml.OOXMLProvider;
48 import org.apache.poi.ooxml.signature.service.signer.ooxml.OOXMLSignatureVerifier;
49 import org.apache.poi.ooxml.signature.service.spi.DigestInfo;
50 import org.bouncycastle.asn1.x509.KeyUsage;
51 import org.joda.time.DateTime;
52
53
54
55 public class TestAbstractOOXMLSignatureService extends TestCase {
56
57     private static final Log LOG = LogFactory.getLog(TestAbstractOOXMLSignatureService.class);
58
59     static {
60         OOXMLProvider.install();
61     }
62
63     private static class OOXMLTestSignatureService extends AbstractOOXMLSignatureService {
64
65         private final URL ooxmlUrl;
66
67         private final TemporaryTestDataStorage temporaryDataStorage;
68
69         private final ByteArrayOutputStream signedOOXMLOutputStream;
70
71         public OOXMLTestSignatureService(URL ooxmlUrl) {
72             this.temporaryDataStorage = new TemporaryTestDataStorage();
73             this.signedOOXMLOutputStream = new ByteArrayOutputStream();
74             this.ooxmlUrl = ooxmlUrl;
75         }
76
77         @Override
78         protected URL getOfficeOpenXMLDocumentURL() {
79             return this.ooxmlUrl;
80         }
81
82         @Override
83         protected OutputStream getSignedOfficeOpenXMLDocumentOutputStream() {
84             return this.signedOOXMLOutputStream;
85         }
86
87         public byte[] getSignedOfficeOpenXMLDocumentData() {
88             return this.signedOOXMLOutputStream.toByteArray();
89         }
90
91         @Override
92         protected TemporaryDataStorage getTemporaryDataStorage() {
93             return this.temporaryDataStorage;
94         }
95     }
96
97     public void testPreSign() throws Exception {
98         // setup
99         URL ooxmlUrl = TestAbstractOOXMLSignatureService.class.getResource("/hello-world-unsigned.docx");
100         assertNotNull(ooxmlUrl);
101
102         OOXMLTestSignatureService signatureService = new OOXMLTestSignatureService(ooxmlUrl);
103
104         // operate
105         DigestInfo digestInfo = signatureService.preSign(null, null);
106
107         // verify
108         assertNotNull(digestInfo);
109         LOG.debug("digest algo: " + digestInfo.digestAlgo);
110         LOG.debug("digest description: " + digestInfo.description);
111         assertEquals("Office OpenXML Document", digestInfo.description);
112         assertNotNull(digestInfo.digestAlgo);
113         assertNotNull(digestInfo.digestValue);
114
115         TemporaryDataStorage temporaryDataStorage = signatureService.getTemporaryDataStorage();
116         String preSignResult = IOUtils.toString(temporaryDataStorage.getTempInputStream());
117         LOG.debug("pre-sign result: " + preSignResult);
118         File tmpFile = File.createTempFile("ooxml-pre-sign-", ".xml");
119         FileUtils.writeStringToFile(tmpFile, preSignResult);
120         LOG.debug("tmp pre-sign file: " + tmpFile.getAbsolutePath());
121     }
122
123     public void testPostSign() throws Exception {
124         sign("/hello-world-unsigned.docx");
125     }
126
127     public void testSignOffice2010() throws Exception {
128         sign("/hello-world-office-2010-technical-preview-unsigned.docx");
129     }
130
131     public void testSignTwice() throws Exception {
132         sign("/hello-world-signed.docx", 2);
133     }
134
135     public void testSignTwiceHere() throws Exception {
136         File tmpFile = sign("/hello-world-unsigned.docx", 1);
137         sign(tmpFile.toURI().toURL(), "CN=Test2", 2);
138     }
139
140     public void testSignPowerpoint() throws Exception {
141         sign("/hello-world-unsigned.pptx");
142     }
143
144     public void testSignSpreadsheet() throws Exception {
145         sign("/hello-world-unsigned.xlsx");
146     }
147
148     private void sign(String documentResourceName) throws Exception {
149         sign(documentResourceName, 1);
150     }
151
152     private File sign(String documentResourceName, int signerCount) throws Exception {
153         URL ooxmlUrl = TestAbstractOOXMLSignatureService.class.getResource(documentResourceName);
154         return sign(ooxmlUrl, signerCount);
155     }
156
157     private File sign(URL ooxmlUrl, int signerCount) throws Exception {
158         return sign(ooxmlUrl, "CN=Test", signerCount);
159     }
160
161     private File sign(URL ooxmlUrl, String signerDn, int signerCount) throws Exception {
162         // setup
163         assertNotNull(ooxmlUrl);
164
165         OOXMLTestSignatureService signatureService = new OOXMLTestSignatureService(ooxmlUrl);
166
167         // operate
168         DigestInfo digestInfo = signatureService.preSign(null, null);
169
170         // verify
171         assertNotNull(digestInfo);
172         LOG.debug("digest algo: " + digestInfo.digestAlgo);
173         LOG.debug("digest description: " + digestInfo.description);
174         assertEquals("Office OpenXML Document", digestInfo.description);
175         assertNotNull(digestInfo.digestAlgo);
176         assertNotNull(digestInfo.digestValue);
177
178         TemporaryDataStorage temporaryDataStorage = signatureService.getTemporaryDataStorage();
179         String preSignResult = IOUtils.toString(temporaryDataStorage.getTempInputStream());
180         LOG.debug("pre-sign result: " + preSignResult);
181         File tmpFile = File.createTempFile("ooxml-pre-sign-", ".xml");
182         FileUtils.writeStringToFile(tmpFile, preSignResult);
183         LOG.debug("tmp pre-sign file: " + tmpFile.getAbsolutePath());
184
185         // setup: key material, signature value
186         KeyPair keyPair = PkiTestUtils.generateKeyPair();
187         Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
188         cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPrivate());
189         byte[] digestInfoValue = ArrayUtils.addAll(PkiTestUtils.SHA1_DIGEST_INFO_PREFIX, digestInfo.digestValue);
190         byte[] signatureValue = cipher.doFinal(digestInfoValue);
191
192         DateTime notBefore = new DateTime();
193         DateTime notAfter = notBefore.plusYears(1);
194         X509Certificate certificate = PkiTestUtils.generateCertificate(keyPair.getPublic(), signerDn, notBefore, notAfter, null, keyPair.getPrivate(), true, 0,
195                                         null, null, new KeyUsage(KeyUsage.nonRepudiation));
196
197         // operate: postSign
198         signatureService.postSign(signatureValue, Collections.singletonList(certificate));
199
200         // verify: signature
201         byte[] signedOOXMLData = signatureService.getSignedOfficeOpenXMLDocumentData();
202         assertNotNull(signedOOXMLData);
203         LOG.debug("signed OOXML size: " + signedOOXMLData.length);
204         String extension = FilenameUtils.getExtension(ooxmlUrl.getFile());
205         tmpFile = File.createTempFile("ooxml-signed-", "." + extension);
206         FileUtils.writeByteArrayToFile(tmpFile, signedOOXMLData);
207         LOG.debug("signed OOXML file: " + tmpFile.getAbsolutePath());
208         List<X509Certificate> signers = OOXMLSignatureVerifier.getSigners(tmpFile.toURI().toURL());
209         assertEquals(signerCount, signers.size());
210         // assertEquals(certificate, signers.get(0));
211         LOG.debug("signed OOXML file: " + tmpFile.getAbsolutePath());
212         return tmpFile;
213     }
214 }