001: /**
002: * Copyright (c) 2003-2006, www.pdfbox.org
003: * All rights reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions are met:
007: *
008: * 1. Redistributions of source code must retain the above copyright notice,
009: * this list of conditions and the following disclaimer.
010: * 2. Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: * 3. Neither the name of pdfbox; nor the names of its
014: * contributors may be used to endorse or promote products derived from this
015: * software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
020: * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
021: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
024: * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: *
028: * http://www.pdfbox.org
029: *
030: */package test.pdfbox.encryption;
031:
032: import java.io.File;
033: import java.io.FileInputStream;
034: import java.io.InputStream;
035: import java.security.KeyStore;
036: import java.security.cert.CertificateFactory;
037: import java.security.cert.X509Certificate;
038:
039: import junit.framework.Assert;
040: import junit.framework.Test;
041: import junit.framework.TestCase;
042: import junit.framework.TestSuite;
043:
044: import org.pdfbox.exceptions.CryptographyException;
045: import org.pdfbox.pdmodel.PDDocument;
046: import org.pdfbox.pdmodel.encryption.AccessPermission;
047: import org.pdfbox.pdmodel.encryption.PublicKeyDecryptionMaterial;
048: import org.pdfbox.pdmodel.encryption.PublicKeyProtectionPolicy;
049: import org.pdfbox.pdmodel.encryption.PublicKeyRecipient;
050:
051: /**
052: * Tests for public key encryption.
053: *
054: * @author <a href="mailto:ben@benlitchfield.com">Ben Litchfield</a>
055: * @version $Revision: 1.3 $
056: */
057: public class TestPublicKeyEncryption extends TestCase {
058:
059: private AccessPermission accessPermission;
060: private AccessPermission accessPermission2;
061:
062: private File publicCert1;
063: private File privateCert1;
064: private File publicCert2;
065: private File privateCert2;
066: private File input;
067: private File output;
068:
069: private String password1 = "test1";
070: private String password2 = "test2";
071:
072: /**
073: * Constructor.
074: *
075: * @param name The junit test class name.
076: */
077: public TestPublicKeyEncryption(String name) {
078: super (name);
079: accessPermission = new AccessPermission();
080: accessPermission.setCanAssembleDocument(false);
081: accessPermission.setCanExtractContent(false);
082: accessPermission.setCanExtractForAccessibility(true);
083: accessPermission.setCanFillInForm(false);
084: accessPermission.setCanModify(false);
085: accessPermission.setCanModifyAnnotations(false);
086: accessPermission.setCanPrint(false);
087: accessPermission.setCanPrintDegraded(false);
088:
089: accessPermission2 = new AccessPermission();
090: accessPermission2.setCanAssembleDocument(false);
091: accessPermission2.setCanExtractContent(false);
092: accessPermission2.setCanExtractForAccessibility(true);
093: accessPermission2.setCanFillInForm(false);
094: accessPermission2.setCanModify(false);
095: accessPermission2.setCanModifyAnnotations(false);
096: accessPermission2.setCanPrint(true); // it is true now !
097: accessPermission2.setCanPrintDegraded(false);
098:
099: publicCert1 = new File("test/encryption/test1.der");
100: privateCert1 = new File("test/encryption/test1.pfx");
101: publicCert2 = new File("test/encryption/test2.der");
102: privateCert2 = new File("test/encryption/test2.pfx");
103: input = new File("test/input/Exolab.pdf");
104: output = new File("test/encryption/output.pdf");
105:
106: Assert.assertTrue(publicCert1.exists() && publicCert1.isFile());
107: Assert.assertTrue(privateCert1.exists()
108: && privateCert1.isFile());
109:
110: Assert.assertTrue(publicCert2.exists() && publicCert2.isFile());
111: Assert.assertTrue(privateCert2.exists()
112: && privateCert2.isFile());
113:
114: Assert.assertTrue(input.exists() && input.isFile());
115:
116: }
117:
118: /**
119: * This will get the suite of test that this class holds.
120: *
121: * @return All of the tests that this class holds.
122: */
123: public static Test suite() {
124: return new TestSuite(TestPublicKeyEncryption.class);
125: }
126:
127: /**
128: * Protect a document with certificate 1 and try to open it with certificate 2
129: * and catch the exception.
130: *
131: * @throws Exception If there is an error during the test.
132: */
133: public void testProtectionError() throws Exception {
134:
135: PDDocument doc = PDDocument.load(input);
136: protect(doc, publicCert1.getAbsolutePath());
137:
138: doc.save(output.getAbsolutePath());
139:
140: doc.close();
141:
142: PDDocument doc2 = PDDocument.load(output);
143:
144: Exception e = null;
145:
146: try {
147: open(doc2, privateCert2.getAbsolutePath(), password2);
148: } catch (CryptographyException ex) {
149: e = ex;
150: System.out.println(ex.getMessage());
151: } finally {
152: Assert.assertNotNull(e);
153: }
154: }
155:
156: /**
157: * Protect a document with the public certificate and try to open it with
158: * the private certificate.
159: *
160: * @throws Exception If there is an error during the test.
161: */
162: public void testProtection() throws Exception {
163: PDDocument doc = PDDocument.load(input);
164: protect(doc, publicCert1.getAbsolutePath());
165:
166: //Assert.assertTrue(doc.isEncrypted());
167:
168: doc.save(output.getAbsolutePath());
169:
170: doc.close();
171:
172: PDDocument doc2 = PDDocument.load(output);
173:
174: Assert.assertNotNull(doc2);
175:
176: open(doc2, privateCert1.getAbsolutePath(), password1);
177:
178: Assert.assertTrue(doc2.isEncrypted());
179:
180: AccessPermission currentAp = doc2.getCurrentAccessPermission();
181:
182: Assert.assertFalse(currentAp.canAssembleDocument());
183: Assert.assertFalse(currentAp.canExtractContent());
184: Assert.assertTrue(currentAp.canExtractForAccessibility());
185: Assert.assertFalse(currentAp.canFillInForm());
186: Assert.assertFalse(currentAp.canModify());
187: Assert.assertFalse(currentAp.canModifyAnnotations());
188: Assert.assertFalse(currentAp.canPrint());
189: Assert.assertFalse(currentAp.canPrintDegraded());
190:
191: doc2.close();
192:
193: }
194:
195: /**
196: * Protect the document for 2 recipients and try to open it.
197: *
198: * @throws Exception If there is an error during the test.
199: */
200: public void testMultipleRecipients() throws Exception {
201:
202: CertificateFactory cf = CertificateFactory.getInstance("X.509");
203:
204: PDDocument doc = PDDocument.load(input);
205:
206: PublicKeyProtectionPolicy ppp = new PublicKeyProtectionPolicy();
207:
208: PublicKeyRecipient recip1 = new PublicKeyRecipient();
209: PublicKeyRecipient recip2 = new PublicKeyRecipient();
210:
211: recip1.setPermission(accessPermission);
212: recip2.setPermission(accessPermission2);
213:
214: InputStream inStream = new FileInputStream(publicCert1);
215: Assert.assertNotNull(cf);
216: X509Certificate certificate1 = (X509Certificate) cf
217: .generateCertificate(inStream);
218: inStream.close();
219:
220: InputStream inStream2 = new FileInputStream(publicCert2);
221: Assert.assertNotNull(cf);
222: X509Certificate certificate2 = (X509Certificate) cf
223: .generateCertificate(inStream2);
224: inStream.close();
225:
226: recip1.setX509(certificate1);
227: recip2.setX509(certificate2);
228:
229: ppp.addRecipient(recip1);
230: ppp.addRecipient(recip2);
231:
232: doc.protect(ppp);
233: doc.save(output.getAbsolutePath());
234: doc.close();
235:
236: /* open first time */
237:
238: PDDocument docOpen1 = PDDocument.load(output);
239:
240: KeyStore ks1 = KeyStore.getInstance("PKCS12");
241: ks1.load(new FileInputStream(privateCert1), password1
242: .toCharArray());
243: PublicKeyDecryptionMaterial pdm = new PublicKeyDecryptionMaterial(
244: ks1, null, password1);
245: docOpen1.openProtection(pdm);
246: docOpen1.close();
247:
248: /* open second time */
249:
250: PDDocument docOpen2 = PDDocument.load(output);
251:
252: KeyStore ks2 = KeyStore.getInstance("PKCS12");
253: ks2.load(new FileInputStream(privateCert2), password2
254: .toCharArray());
255: PublicKeyDecryptionMaterial pdm2 = new PublicKeyDecryptionMaterial(
256: ks2, null, password2);
257: docOpen2.openProtection(pdm2);
258: docOpen2.close();
259:
260: }
261:
262: private void protect(PDDocument doc, String certPath)
263: throws Exception {
264: InputStream inStream = new FileInputStream(certPath);
265: CertificateFactory cf = CertificateFactory.getInstance("X.509");
266: Assert.assertNotNull(cf);
267: X509Certificate certificate = (X509Certificate) cf
268: .generateCertificate(inStream);
269: Assert.assertNotNull(certificate);
270: inStream.close();
271:
272: PublicKeyProtectionPolicy ppp = new PublicKeyProtectionPolicy();
273: PublicKeyRecipient recip = new PublicKeyRecipient();
274: recip.setPermission(accessPermission);
275: recip.setX509(certificate);
276:
277: ppp.addRecipient(recip);
278:
279: doc.protect(ppp);
280:
281: }
282:
283: private void open(PDDocument doc, String certPath, String password)
284: throws Exception {
285: KeyStore ks = KeyStore.getInstance("PKCS12");
286: ks.load(new FileInputStream(certPath), password.toCharArray());
287:
288: PublicKeyDecryptionMaterial pdm = new PublicKeyDecryptionMaterial(
289: ks, null, password);
290:
291: doc.openProtection(pdm);
292:
293: }
294:
295: }
|