001/*
002 * $Id: PdfSigGenericPKCS.java 4790 2011-04-01 20:49:40Z psoares33 $
003 *
004 * This file is part of the iText (R) project.
005 * Copyright (c) 1998-2011 1T3XT BVBA
006 * Authors: Bruno Lowagie, Paulo Soares, et al.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU Affero General Public License version 3
010 * as published by the Free Software Foundation with the addition of the
011 * following permission added to Section 15 as permitted in Section 7(a):
012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT,
013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
014 *
015 * This program is distributed in the hope that it will be useful, but
016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
017 * or FITNESS FOR A PARTICULAR PURPOSE.
018 * See the GNU Affero General Public License for more details.
019 * You should have received a copy of the GNU Affero General Public License
020 * along with this program; if not, see http://www.gnu.org/licenses or write to
021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
022 * Boston, MA, 02110-1301 USA, or download the license from the following URL:
023 * http://itextpdf.com/terms-of-use/
024 *
025 * The interactive user interfaces in modified source and object code versions
026 * of this program must display Appropriate Legal Notices, as required under
027 * Section 5 of the GNU Affero General Public License.
028 *
029 * In accordance with Section 7(b) of the GNU Affero General Public License,
030 * a covered work must retain the producer line in every PDF that is created
031 * or manipulated using iText.
032 *
033 * You can be released from the requirements of the license by purchasing
034 * a commercial license. Buying such a license is mandatory as soon as you
035 * develop commercial activities involving the iText software without
036 * disclosing the source code of your own applications.
037 * These activities include: offering paid services to customers as an ASP,
038 * serving PDFs on the fly in a web application, shipping iText with a closed
039 * source product.
040 *
041 * For more information, please contact iText Software Corp. at this
042 * address: sales@itextpdf.com
043 */
044package com.itextpdf.text.pdf;
045
046import java.io.ByteArrayOutputStream;
047import java.security.PrivateKey;
048import java.security.cert.CRL;
049import java.security.cert.Certificate;
050
051import com.itextpdf.text.ExceptionConverter;
052
053/**
054 * A signature dictionary representation for the standard filters.
055 */
056public abstract class PdfSigGenericPKCS extends PdfSignature {
057    /**
058     * The hash algorithm, for example "SHA1"
059     */    
060    protected String hashAlgorithm;
061    /**
062     * The crypto provider
063     */    
064    protected String provider = null;
065    /**
066     * The class instance that calculates the PKCS#1 and PKCS#7
067     */    
068    protected PdfPKCS7 pkcs;
069    /**
070     * The subject name in the signing certificate (the element "CN")
071     */    
072    protected String   name;
073
074    private byte externalDigest[];
075    private byte externalRSAdata[];
076    private String digestEncryptionAlgorithm;
077
078    /**
079     * Creates a generic standard filter.
080     * @param filter the filter name
081     * @param subFilter the sub-filter name
082     */    
083    public PdfSigGenericPKCS(PdfName filter, PdfName subFilter) {
084        super(filter, subFilter);
085    }
086
087    /**
088     * Sets the crypto information to sign.
089     * @param privKey the private key
090     * @param certChain the certificate chain
091     * @param crlList the certificate revocation list. It can be <CODE>null</CODE>
092     */    
093    public void setSignInfo(PrivateKey privKey, Certificate[] certChain, CRL[] crlList) {
094        try {
095            pkcs = new PdfPKCS7(privKey, certChain, crlList, hashAlgorithm, provider, PdfName.ADBE_PKCS7_SHA1.equals(get(PdfName.SUBFILTER)));
096            pkcs.setExternalDigest(externalDigest, externalRSAdata, digestEncryptionAlgorithm);
097            if (PdfName.ADBE_X509_RSA_SHA1.equals(get(PdfName.SUBFILTER))) {
098                if (certChain.length > 1) {
099                    PdfArray arr = new PdfArray();
100                    for (int ii = 0; ii < certChain.length; ii++) {
101                        arr.add(new PdfString(certChain[ii].getEncoded()));
102                    }
103                    put(PdfName.CERT, arr);
104                }
105                else {
106                    ByteArrayOutputStream bout = new ByteArrayOutputStream();
107                    for (int k = 0; k < certChain.length; ++k) {
108                        bout.write(certChain[k].getEncoded());
109                    }
110                    bout.close();
111                    setCert(bout.toByteArray());
112                }
113                setContents(pkcs.getEncodedPKCS1());
114            }
115            else
116                setContents(pkcs.getEncodedPKCS7());
117            name = PdfPKCS7.getSubjectFields(pkcs.getSigningCertificate()).getField("CN");
118            if (name != null)
119                put(PdfName.NAME, new PdfString(name, PdfObject.TEXT_UNICODE));
120            pkcs = new PdfPKCS7(privKey, certChain, crlList, hashAlgorithm, provider, PdfName.ADBE_PKCS7_SHA1.equals(get(PdfName.SUBFILTER)));
121            pkcs.setExternalDigest(externalDigest, externalRSAdata, digestEncryptionAlgorithm);
122        }
123        catch (Exception e) {
124            throw new ExceptionConverter(e);
125        }
126    }
127
128    /**
129     * Sets the digest/signature to an external calculated value.
130     * @param digest the digest. This is the actual signature
131     * @param RSAdata the extra data that goes into the data tag in PKCS#7
132     * @param digestEncryptionAlgorithm the encryption algorithm. It may must be <CODE>null</CODE> if the <CODE>digest</CODE>
133     * is also <CODE>null</CODE>. If the <CODE>digest</CODE> is not <CODE>null</CODE>
134     * then it may be "RSA" or "DSA"
135     */    
136    public void setExternalDigest(byte digest[], byte RSAdata[], String digestEncryptionAlgorithm) {
137        externalDigest = digest;
138        externalRSAdata = RSAdata;
139        this.digestEncryptionAlgorithm = digestEncryptionAlgorithm;
140    }
141
142    /**
143     * Gets the subject name in the signing certificate (the element "CN")
144     * @return the subject name in the signing certificate (the element "CN")
145     */    
146    public String getName() {
147        return name;
148    }
149
150    /**
151     * Gets the class instance that does the actual signing.
152     * @return the class instance that does the actual signing
153     */    
154    public PdfPKCS7 getSigner() {
155        return pkcs;
156    }
157
158    /**
159     * Gets the signature content. This can be a PKCS#1 or a PKCS#7. It corresponds to
160     * the /Contents key.
161     * @return the signature content
162     */    
163    public byte[] getSignerContents() {
164        if (PdfName.ADBE_X509_RSA_SHA1.equals(get(PdfName.SUBFILTER)))
165            return pkcs.getEncodedPKCS1();
166        else
167            return pkcs.getEncodedPKCS7();
168    }
169
170    /**
171     * Creates a standard filter of the type VeriSign.
172     */    
173    public static class VeriSign extends PdfSigGenericPKCS {
174        /**
175         * The constructor for the default provider.
176         */        
177        public VeriSign() {
178            super(PdfName.VERISIGN_PPKVS, PdfName.ADBE_PKCS7_DETACHED);
179            hashAlgorithm = "MD5";
180            put(PdfName.R, new PdfNumber(65537));
181        }
182
183        /**
184         * The constructor for an explicit provider.
185         * @param provider the crypto provider
186         */        
187        public VeriSign(String provider) {
188            this();
189            this.provider = provider;
190        }
191    }
192
193    /**
194     * Creates a standard filter of the type self signed.
195     */    
196    public static class PPKLite extends PdfSigGenericPKCS {
197        /**
198         * The constructor for the default provider.
199         */        
200        public PPKLite() {
201            super(PdfName.ADOBE_PPKLITE, PdfName.ADBE_X509_RSA_SHA1);
202            hashAlgorithm = "SHA1";
203            put(PdfName.R, new PdfNumber(65541));
204        }
205
206        /**
207         * The constructor for an explicit provider.
208         * @param provider the crypto provider
209         */        
210        public PPKLite(String provider) {
211            this();
212            this.provider = provider;
213        }
214    }
215
216    /**
217     * Creates a standard filter of the type Windows Certificate.
218     */    
219    public static class PPKMS extends PdfSigGenericPKCS {
220        /**
221         * The constructor for the default provider.
222         */        
223        public PPKMS() {
224            super(PdfName.ADOBE_PPKMS, PdfName.ADBE_PKCS7_SHA1);
225            hashAlgorithm = "SHA1";
226        }
227
228        /**
229         * The constructor for an explicit provider.
230         * @param provider the crypto provider
231         */        
232        public PPKMS(String provider) {
233            this();
234            this.provider = provider;
235        }
236    }
237}