⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pdfpkcs7.java

📁 iText是一个能够快速产生PDF文件的java类库。iText的java类对于那些要产生包含文本
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/*
 * 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 + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -