pdfpkcs7.java

来自「有关对pdf操作的代码」· Java 代码 · 共 1,297 行 · 第 1/4 页

JAVA
1,297
字号
/* * Copyright 2004 by Paulo Soares. * * The contents of this file are subject to the Mozilla Public License Version 1.1 * (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.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the License. * * The Original Code is 'iText, a free JAVA-PDF library'. * * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie. * All Rights Reserved. * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved. * * Contributor(s): all the names of the contributors are added in the source code * where applicable. * * Alternatively, the contents of this file may be used under the terms of the * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the * provisions of LGPL are applicable instead of those above.  If you wish to * allow use of your version of this file only under the terms of the LGPL * License and not to allow others to use your version of this file under * the MPL, indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by the LGPL. * If you do not delete the provisions above, a recipient may use your version * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE. * * This library is free software; you can redistribute it and/or modify it * under the terms of the MPL as stated above or under the terms of the GNU * Library General Public License as published by the Free Software Foundation; * either version 2 of the License, or any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more * details. * * If you didn't download this code from the following link, you should check if * you aren't using an obsolete version: * http://www.lowagie.com/iText/ */package com.lowagie.text.pdf;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.security.InvalidKeyException;import java.security.KeyStore;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.security.NoSuchProviderException;import java.security.PrivateKey;import java.security.Signature;import java.security.SignatureException;import java.security.cert.CRL;import java.security.cert.CRLException;import java.security.cert.Certificate;import java.security.cert.CertificateException;import java.security.cert.X509CRL;import java.security.cert.X509Certificate;import java.util.ArrayList;import java.util.Arrays;import java.util.Calendar;import java.util.Collection;import java.util.Enumeration;import java.util.GregorianCalendar;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.Set;import com.lowagie.text.ExceptionConverter;import java.math.BigInteger;import org.bouncycastle.asn1.ASN1EncodableVector;import org.bouncycastle.asn1.ASN1InputStream;import org.bouncycastle.asn1.ASN1OutputStream;import org.bouncycastle.asn1.ASN1Sequence;import org.bouncycastle.asn1.ASN1Set;import org.bouncycastle.asn1.ASN1TaggedObject;import org.bouncycastle.asn1.DERConstructedSet;import org.bouncycastle.asn1.DERInteger;import org.bouncycastle.asn1.DERNull;import org.bouncycastle.asn1.DERObject;import org.bouncycastle.asn1.DERObjectIdentifier;import org.bouncycastle.asn1.DEROctetString;import org.bouncycastle.asn1.DERSequence;import org.bouncycastle.asn1.DERSet;import org.bouncycastle.asn1.DERString;import org.bouncycastle.asn1.DERTaggedObject;import org.bouncycastle.asn1.DERUTCTime;import org.bouncycastle.jce.provider.X509CRLParser;import org.bouncycastle.jce.provider.X509CertParser;import org.bouncycastle.util.StreamParsingException;/** * This class does all the processing related to signing and verifying a PKCS#7 * signature. * <p> * It's based in code found at org.bouncycastle. */public class PdfPKCS7 {    private byte sigAttr[];    private byte digestAttr[];    private int version, signerversion;    private Set digestalgos;    private Collection certs, crls;    private X509Certificate signCert;    private byte[] digest;    private MessageDigest messageDigest;    private String digestAlgorithm, digestEncryptionAlgorithm;    private Signature sig;    private transient PrivateKey privKey;    private byte RSAdata[];    private boolean verified;    private boolean verifyResult;    private byte externalDigest[];    private byte externalRSAdata[];        private static final String ID_PKCS7_DATA = "1.2.840.113549.1.7.1";    private static final String ID_PKCS7_SIGNED_DATA = "1.2.840.113549.1.7.2";    private static final String ID_MD5 = "1.2.840.113549.2.5";    private static final String ID_MD2 = "1.2.840.113549.2.2";    private static final String ID_SHA1 = "1.3.14.3.2.26";    private static final String ID_RSA = "1.2.840.113549.1.1.1";    private static final String ID_DSA = "1.2.840.10040.4.1";    private static final String ID_CONTENT_TYPE = "1.2.840.113549.1.9.3";    private static final String ID_MESSAGE_DIGEST = "1.2.840.113549.1.9.4";    private static final String ID_SIGNING_TIME = "1.2.840.113549.1.9.5";    private static final String ID_MD2RSA = "1.2.840.113549.1.1.2";    private static final String ID_MD5RSA = "1.2.840.113549.1.1.4";    private static final String ID_SHA1RSA = "1.2.840.113549.1.1.5";    private static final String ID_ADBE_REVOCATION = "1.2.840.113583.1.1.8";    /**     * Holds value of property reason.     */    private String reason;        /**     * Holds value of property location.     */    private String location;        /**     * Holds value of property signDate.     */    private Calendar signDate;        /**     * Holds value of property signName.     */    private String signName;        /**     * Verifies a signature using the sub-filter adbe.x509.rsa_sha1.     * @param contentsKey the /Contents key     * @param certsKey the /Cert key     * @param provider the provider or <code>null</code> for the default provider     * @throws SecurityException on error     * @throws InvalidKeyException on error     * @throws CertificateException on error     * @throws NoSuchProviderException on error     * @throws NoSuchAlgorithmException on error     * @throws IOException on error     */        public PdfPKCS7(byte[] contentsKey, byte[] certsKey, String provider) throws SecurityException, InvalidKeyException, CertificateException, NoSuchProviderException, NoSuchAlgorithmException, IOException, StreamParsingException {        X509CertParser cr = new X509CertParser();        cr.engineInit(new ByteArrayInputStream(certsKey));        certs = cr.engineReadAll();        signCert = (X509Certificate)certs.iterator().next();        crls = new ArrayList();        ASN1InputStream in = new ASN1InputStream(new ByteArrayInputStream(contentsKey));        digest = ((DEROctetString)in.readObject()).getOctets();        if (provider == null)            sig = Signature.getInstance("SHA1withRSA");        else            sig = Signature.getInstance("SHA1withRSA", provider);        sig.initVerify(signCert.getPublicKey());    }        /**     * Verifies a signature using the sub-filter adbe.pkcs7.detached or     * adbe.pkcs7.sha1.     * @param contentsKey the /Contents key     * @param provider the provider or <code>null</code> for the default provider     * @throws SecurityException on error     * @throws CRLException on error     * @throws InvalidKeyException on error     * @throws CertificateException on error     * @throws NoSuchProviderException on error     * @throws NoSuchAlgorithmException on error     */        public PdfPKCS7(byte[] contentsKey, String provider) throws SecurityException, CRLException, InvalidKeyException, CertificateException, NoSuchProviderException, NoSuchAlgorithmException, StreamParsingException {        ASN1InputStream din = new ASN1InputStream(new ByteArrayInputStream(contentsKey));                //        // Basic checks to make sure it's a PKCS#7 SignedData Object        //        DERObject pkcs;                try {            pkcs = din.readObject();        }        catch (IOException e) {            throw new SecurityException("can't decode PKCS7SignedData object");        }        if (!(pkcs instanceof ASN1Sequence)) {            throw new SecurityException("Not a valid PKCS#7 object - not a sequence");        }        ASN1Sequence signedData = (ASN1Sequence)pkcs;        DERObjectIdentifier objId = (DERObjectIdentifier)signedData.getObjectAt(0);        if (!objId.getId().equals(ID_PKCS7_SIGNED_DATA))            throw new SecurityException("Not a valid PKCS#7 object - not signed data");        ASN1Sequence content = (ASN1Sequence)((DERTaggedObject)signedData.getObjectAt(1)).getObject();        // the positions that we care are:        //     0 - version        //     1 - digestAlgorithms        //     2 - possible ID_PKCS7_DATA        //     (the certificates and crls are taken out by other means)        //     last - signerInfos                // the version        version = ((DERInteger)content.getObjectAt(0)).getValue().intValue();                // the digestAlgorithms        digestalgos = new HashSet();        Enumeration e = ((ASN1Set)content.getObjectAt(1)).getObjects();        while (e.hasMoreElements())        {            ASN1Sequence s = (ASN1Sequence)e.nextElement();            DERObjectIdentifier o = (DERObjectIdentifier)s.getObjectAt(0);            digestalgos.add(o.getId());        }                // the certificates and crls        X509CertParser cr = new X509CertParser();        cr.engineInit(new ByteArrayInputStream(contentsKey));        certs = cr.engineReadAll();        X509CRLParser cl = new X509CRLParser();        cl.engineInit(new ByteArrayInputStream(contentsKey));        crls = cl.engineReadAll();                // the possible ID_PKCS7_DATA        ASN1Sequence rsaData = (ASN1Sequence)content.getObjectAt(2);        if (rsaData.size() > 1) {            DEROctetString rsaDataContent = (DEROctetString)((DERTaggedObject)rsaData.getObjectAt(1)).getObject();            RSAdata = rsaDataContent.getOctets();        }                // the signerInfos        int next = 3;        while (content.getObjectAt(next) instanceof DERTaggedObject)            ++next;        ASN1Set signerInfos = (ASN1Set)content.getObjectAt(next);        if (signerInfos.size() != 1)            throw new SecurityException("This PKCS#7 object has multiple SignerInfos - only one is supported at this time");        ASN1Sequence signerInfo = (ASN1Sequence)signerInfos.getObjectAt(0);        // the positions that we care are        //     0 - version        //     1 - the signing certificate serial number        //     2 - the digest algorithm        //     3 or 4 - digestEncryptionAlgorithm        //     4 or 5 - encryptedDigest        signerversion = ((DERInteger)signerInfo.getObjectAt(0)).getValue().intValue();        // Get the signing certificate        ASN1Sequence issuerAndSerialNumber = (ASN1Sequence)signerInfo.getObjectAt(1);        BigInteger serialNumber = ((DERInteger)issuerAndSerialNumber.getObjectAt(1)).getValue();        for (Iterator i = certs.iterator(); i.hasNext();) {            X509Certificate cert = (X509Certificate)i.next();            if (serialNumber.equals(cert.getSerialNumber())) {                signCert = cert;                break;            }        }        if (signCert == null) {            throw new SecurityException("Can't find signing certificate with serial " + serialNumber.toString(16));        }        digestAlgorithm = ((DERObjectIdentifier)((ASN1Sequence)signerInfo.getObjectAt(2)).getObjectAt(0)).getId();        next = 3;        if (signerInfo.getObjectAt(next) instanceof ASN1TaggedObject) {            ASN1TaggedObject tagsig = (ASN1TaggedObject)signerInfo.getObjectAt(next);            ASN1Sequence sseq = (ASN1Sequence)tagsig.getObject();            ByteArrayOutputStream bOut = new ByteArrayOutputStream();                        ASN1OutputStream dout = new ASN1OutputStream(bOut);            try {                ASN1EncodableVector attribute = new ASN1EncodableVector();                for (int k = 0; k < sseq.size(); ++k) {                    attribute.add(sseq.getObjectAt(k));                }                dout.writeObject(new DERSet(attribute));                dout.close();            }            catch (IOException ioe){}            sigAttr = bOut.toByteArray();                        for (int k = 0; k < sseq.size(); ++k) {                ASN1Sequence seq2 = (ASN1Sequence)sseq.getObjectAt(k);                if (((DERObjectIdentifier)seq2.getObjectAt(0)).getId().equals(ID_MESSAGE_DIGEST)) {                    ASN1Set set = (ASN1Set)seq2.getObjectAt(1);                    digestAttr = ((DEROctetString)set.getObjectAt(0)).getOctets();                    break;                }            }            if (digestAttr == null)                throw new SecurityException("Authenticated attribute is missing the digest.");            ++next;        }        digestEncryptionAlgorithm = ((DERObjectIdentifier)((ASN1Sequence)signerInfo.getObjectAt(next++)).getObjectAt(0)).getId();        digest = ((DEROctetString)signerInfo.getObjectAt(next)).getOctets();        if (RSAdata != null || digestAttr != null) {            if (provider == null || provider.startsWith("SunPKCS11"))                messageDigest = MessageDigest.getInstance(getHashAlgorithm());            else                messageDigest = MessageDigest.getInstance(getHashAlgorithm(), provider);        }        if (provider == null)            sig = Signature.getInstance(getDigestAlgorithm());        else

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?