KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lowagie > text > pdf > PdfPublicKeySecurityHandler


1 /*
2  * $Id: PdfPublicKeySecurityHandler.java 2655 2007-03-15 19:26:36Z xlv $
3  * $Name$
4  *
5  * Copyright 2006 Paulo Soares
6  *
7  * The contents of this file are subject to the Mozilla Public License Version 1.1
8  * (the "License"); you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the License.
14  *
15  * The Original Code is 'iText, a free JAVA-PDF library'.
16  *
17  * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
18  * the Initial Developer are Copyright (C) 1999-2007 by Bruno Lowagie.
19  * All Rights Reserved.
20  * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
21  * are Copyright (C) 2000-2007 by Paulo Soares. All Rights Reserved.
22  *
23  * Contributor(s): all the names of the contributors are added in the source code
24  * where applicable.
25  *
26  * Alternatively, the contents of this file may be used under the terms of the
27  * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
28  * provisions of LGPL are applicable instead of those above. If you wish to
29  * allow use of your version of this file only under the terms of the LGPL
30  * License and not to allow others to use your version of this file under
31  * the MPL, indicate your decision by deleting the provisions above and
32  * replace them with the notice and other provisions required by the LGPL.
33  * If you do not delete the provisions above, a recipient may use your version
34  * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
35  *
36  * This library is free software; you can redistribute it and/or modify it
37  * under the terms of the MPL as stated above or under the terms of the GNU
38  * Library General Public License as published by the Free Software Foundation;
39  * either version 2 of the License, or any later version.
40  *
41  * This library is distributed in the hope that it will be useful, but WITHOUT
42  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
43  * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
44  * details.
45  *
46  * If you didn't download this code from the following link, you should check if
47  * you aren't using an obsolete version:
48  * http://www.lowagie.com/iText/
49  */

50
51 /**
52  * The below 2 methods are from pdfbox.
53  *
54  * private DERObject createDERForRecipient(byte[] in, X509Certificate cert) ;
55  * private KeyTransRecipientInfo computeRecipientInfo(X509Certificate x509certificate, byte[] abyte0);
56  *
57  * 2006-11-22 Aiken Sam.
58  */

59
60 /**
61  * Copyright (c) 2003-2006, www.pdfbox.org
62  * All rights reserved.
63  *
64  * Redistribution and use in source and binary forms, with or without
65  * modification, are permitted provided that the following conditions are met:
66  *
67  * 1. Redistributions of source code must retain the above copyright notice,
68  * this list of conditions and the following disclaimer.
69  * 2. Redistributions in binary form must reproduce the above copyright notice,
70  * this list of conditions and the following disclaimer in the documentation
71  * and/or other materials provided with the distribution.
72  * 3. Neither the name of pdfbox; nor the names of its
73  * contributors may be used to endorse or promote products derived from this
74  * software without specific prior written permission.
75  *
76  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
77  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
78  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
79  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
80  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
81  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
82  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
83  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
84  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
85  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
86  *
87  * http://www.pdfbox.org
88  *
89  */

90
91 package com.lowagie.text.pdf;
92
93 import java.io.ByteArrayInputStream JavaDoc;
94 import java.io.ByteArrayOutputStream JavaDoc;
95 import java.io.IOException JavaDoc;
96
97 import java.security.AlgorithmParameterGenerator JavaDoc;
98 import java.security.AlgorithmParameters JavaDoc;
99 import java.security.GeneralSecurityException JavaDoc;
100 import java.security.NoSuchAlgorithmException JavaDoc;
101 import java.security.SecureRandom JavaDoc;
102 import java.security.cert.Certificate JavaDoc;
103 import java.security.cert.X509Certificate JavaDoc;
104
105 import java.util.ArrayList JavaDoc;
106
107 import javax.crypto.Cipher;
108 import javax.crypto.KeyGenerator;
109 import javax.crypto.SecretKey;
110
111 import org.bouncycastle.asn1.ASN1InputStream;
112 import org.bouncycastle.asn1.DERObject;
113 import org.bouncycastle.asn1.DERObjectIdentifier;
114 import org.bouncycastle.asn1.DEROctetString;
115 import org.bouncycastle.asn1.DEROutputStream;
116 import org.bouncycastle.asn1.DERSet;
117 import org.bouncycastle.asn1.cms.ContentInfo;
118 import org.bouncycastle.asn1.cms.EncryptedContentInfo;
119 import org.bouncycastle.asn1.cms.EnvelopedData;
120 import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
121 import org.bouncycastle.asn1.cms.KeyTransRecipientInfo;
122 import org.bouncycastle.asn1.cms.RecipientIdentifier;
123 import org.bouncycastle.asn1.cms.RecipientInfo;
124 import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
125 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
126 import org.bouncycastle.asn1.x509.TBSCertificateStructure;
127
128 /**
129  * @author Aiken Sam (aikensam@ieee.org)
130  */

131 public class PdfPublicKeySecurityHandler {
132     
133     static final int SEED_LENGTH = 20;
134     
135     private ArrayList JavaDoc recipients = null;
136     
137     private byte[] seed = new byte[SEED_LENGTH];
138
139     public PdfPublicKeySecurityHandler() {
140         KeyGenerator key;
141         try {
142             key = KeyGenerator.getInstance("AES");
143             key.init(192, new SecureRandom JavaDoc());
144             SecretKey sk = key.generateKey();
145             System.arraycopy(sk.getEncoded(), 0, seed, 0, SEED_LENGTH); // create the 20 bytes seed
146
} catch (NoSuchAlgorithmException JavaDoc e) {
147             seed = SecureRandom.getSeed(SEED_LENGTH);
148         }
149     
150         recipients = new ArrayList JavaDoc();
151     }
152
153
154     /*
155      * Routine for decode output of PdfContentByte.escapeString(byte[] bytes).
156      * It should be moved to PdfContentByte.
157      */

158      
159     static public byte[] unescapedString(byte[] bytes) throws BadPdfFormatException {
160         ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
161               
162         int index = 0;
163         
164         if (bytes[0] != '(' && bytes[bytes.length-1] != ')') throw new BadPdfFormatException("Expect '(' and ')' at begin and end of the string.");
165         
166         while (index < bytes.length) {
167             if (bytes[index] == '\\') {
168                 index++;
169                 switch (bytes[index]) {
170                 case 'b':
171                     baos.write('\b');
172                     break;
173                 case 'f':
174                     baos.write('\f');
175                     break;
176                 case 't':
177                     baos.write('\t');
178                     break;
179                 case 'n':
180                     baos.write('\n');
181                     break;
182                 case 'r':
183                     baos.write('\r');
184                     break;
185                 case '(':
186                         baos.write('(');
187                         break;
188                 case ')':
189                         baos.write(')');
190                         break;
191                 case '\\':
192                     baos.write('\\');
193                     break;
194                 }
195             } else
196                 baos.write(bytes[index]);
197             index++;
198         }
199         return baos.toByteArray();
200     }
201     
202     public void addRecipient(PdfPublicKeyRecipient recipient) {
203         recipients.add(recipient);
204     }
205     
206     protected byte[] getSeed() {
207         return (byte[])seed.clone();
208     }
209     /*
210     public PdfPublicKeyRecipient[] getRecipients() {
211         recipients.toArray();
212         return (PdfPublicKeyRecipient[])recipients.toArray();
213     }*/

214     
215     public int getRecipientsSize() {
216         return recipients.size();
217     }
218     
219     public byte[] getEncodedRecipient(int index) throws IOException JavaDoc, GeneralSecurityException JavaDoc {
220         //Certificate certificate = recipient.getX509();
221
PdfPublicKeyRecipient recipient = (PdfPublicKeyRecipient)recipients.get(index);
222         byte[] cms = recipient.getCms();
223         
224         if (cms != null) return cms;
225         
226         Certificate JavaDoc certificate = recipient.getCertificate();
227         int permission = recipient.getPermission();//PdfWriter.AllowCopy | PdfWriter.AllowPrinting | PdfWriter.AllowScreenReaders | PdfWriter.AllowAssembly;
228
int revision = 3;
229         
230         permission |= revision==3 ? 0xfffff0c0 : 0xffffffc0;
231         permission &= 0xfffffffc;
232         permission += 1;
233       
234         byte[] pkcs7input = new byte[24];
235         
236         byte one = (byte)(permission);
237         byte two = (byte)(permission >> 8);
238         byte three = (byte)(permission >> 16);
239         byte four = (byte)(permission >> 24);
240
241         System.arraycopy(seed, 0, pkcs7input, 0, 20); // put this seed in the pkcs7 input
242

243         pkcs7input[20] = four;
244         pkcs7input[21] = three;
245         pkcs7input[22] = two;
246         pkcs7input[23] = one;
247         
248         DERObject obj = createDERForRecipient(pkcs7input, (X509Certificate JavaDoc)certificate);
249             
250         ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc();
251             
252         DEROutputStream k = new DEROutputStream(baos);
253             
254         k.writeObject(obj);
255         
256         cms = baos.toByteArray();
257
258         recipient.setCms(cms);
259         
260         return cms;
261     }
262     
263     public PdfArray getEncodedRecipients() throws IOException JavaDoc,
264                                          GeneralSecurityException JavaDoc {
265         PdfArray EncodedRecipients = new PdfArray();
266         byte[] cms = null;
267         for (int i=0; i<recipients.size(); i++)
268         try {
269             cms = getEncodedRecipient(i);
270             EncodedRecipients.add(new PdfLiteral(PdfContentByte.escapeString(cms)));
271         } catch (GeneralSecurityException JavaDoc e) {
272             EncodedRecipients = null;
273         } catch (IOException JavaDoc e) {
274             EncodedRecipients = null;
275         }
276         
277         return EncodedRecipients;
278     }
279     
280     private DERObject createDERForRecipient(byte[] in, X509Certificate JavaDoc cert)
281         throws IOException JavaDoc,
282                GeneralSecurityException JavaDoc
283     {
284         
285         String JavaDoc s = "1.2.840.113549.3.2";
286         
287         AlgorithmParameterGenerator JavaDoc algorithmparametergenerator = AlgorithmParameterGenerator.getInstance(s);
288         AlgorithmParameters JavaDoc algorithmparameters = algorithmparametergenerator.generateParameters();
289         ByteArrayInputStream JavaDoc bytearrayinputstream = new ByteArrayInputStream JavaDoc(algorithmparameters.getEncoded("ASN.1"));
290         ASN1InputStream asn1inputstream = new ASN1InputStream(bytearrayinputstream);
291         DERObject derobject = asn1inputstream.readObject();
292         KeyGenerator keygenerator = KeyGenerator.getInstance(s);
293         keygenerator.init(128);
294         SecretKey secretkey = keygenerator.generateKey();
295         Cipher cipher = Cipher.getInstance(s);
296         cipher.init(1, secretkey, algorithmparameters);
297         byte[] abyte1 = cipher.doFinal(in);
298         DEROctetString deroctetstring = new DEROctetString(abyte1);
299         KeyTransRecipientInfo keytransrecipientinfo = computeRecipientInfo(cert, secretkey.getEncoded());
300         DERSet derset = new DERSet(new RecipientInfo(keytransrecipientinfo));
301         AlgorithmIdentifier algorithmidentifier = new AlgorithmIdentifier(new DERObjectIdentifier(s), derobject);
302         EncryptedContentInfo encryptedcontentinfo =
303             new EncryptedContentInfo(PKCSObjectIdentifiers.data, algorithmidentifier, deroctetstring);
304         EnvelopedData env = new EnvelopedData(null, derset, encryptedcontentinfo, null);
305         ContentInfo contentinfo =
306             new ContentInfo(PKCSObjectIdentifiers.envelopedData, env);
307         return contentinfo.getDERObject();
308     }
309     
310     private KeyTransRecipientInfo computeRecipientInfo(X509Certificate JavaDoc x509certificate, byte[] abyte0)
311         throws GeneralSecurityException JavaDoc, IOException JavaDoc
312     {
313         ASN1InputStream asn1inputstream =
314             new ASN1InputStream(new ByteArrayInputStream JavaDoc(x509certificate.getTBSCertificate()));
315         TBSCertificateStructure tbscertificatestructure =
316             TBSCertificateStructure.getInstance(asn1inputstream.readObject());
317         AlgorithmIdentifier algorithmidentifier = tbscertificatestructure.getSubjectPublicKeyInfo().getAlgorithmId();
318         IssuerAndSerialNumber issuerandserialnumber =
319             new IssuerAndSerialNumber(
320                 tbscertificatestructure.getIssuer(),
321                 tbscertificatestructure.getSerialNumber().getValue());
322         Cipher cipher = Cipher.getInstance(algorithmidentifier.getObjectId().getId());
323         cipher.init(1, x509certificate);
324         DEROctetString deroctetstring = new DEROctetString(cipher.doFinal(abyte0));
325         RecipientIdentifier recipId = new RecipientIdentifier(issuerandserialnumber);
326         return new KeyTransRecipientInfo( recipId, algorithmidentifier, deroctetstring);
327     }
328 }
329
Popular Tags