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

📄 publickeysecurityhandler.java

📁 非常有用的操作pdf文件的java源码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/**
 * Copyright (c) 2003-2006, www.pdfbox.org
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. Neither the name of pdfbox; nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * http://www.pdfbox.org
 *
 */

package org.pdfbox.pdmodel.encryption;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
import java.security.GeneralSecurityException;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.Iterator;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.DERObject;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DEROutputStream;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.asn1.cms.EncryptedContentInfo;
import org.bouncycastle.asn1.cms.EnvelopedData;
import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
import org.bouncycastle.asn1.cms.KeyTransRecipientInfo;
import org.bouncycastle.asn1.cms.RecipientIdentifier;
import org.bouncycastle.asn1.cms.RecipientInfo;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.TBSCertificateStructure;
import org.bouncycastle.cms.CMSEnvelopedData;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.RecipientInformation;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.pdfbox.cos.COSString;
import org.pdfbox.exceptions.CryptographyException;
import org.pdfbox.pdmodel.PDDocument;

/**
 * This class implements the public key security handler 
 * described in the PDF specification.
 * 
 * @see PDF Spec 1.6 p104
 * 
 * @see PublicKeyProtectionPolicy to see how to protect document with this security handler.
 * 
 * @author Benoit Guillon (benoit.guillon@snv.jussieu.fr)
 * @version $Revision: 1.3 $
 */
public class PublicKeySecurityHandler extends SecurityHandler 
{
    
    /**
     * The filter name.
     */
    public static final String FILTER = "Adobe.PubSec";
    
    private static final String SUBFILTER = "adbe.pkcs7.s4";
    
    private PublicKeyProtectionPolicy policy = null;
    
    /**
     * Constructor.
     */
    public PublicKeySecurityHandler()
    {
    }
    
    /**
     * Constructor used for encryption.
     * 
     * @param p The protection policy.
     */
    public PublicKeySecurityHandler(PublicKeyProtectionPolicy p)
    {
        policy = p;
        this.keyLength = policy.getEncryptionKeyLength();
    }
    
    /**
     * Decrypt the document.
     * 
     * @param doc The document to decrypt.
     * @param decryptionMaterial The data used to decrypt the document.
     * 
     * @throws CryptographyException If there is an error during decryption.
     * @throws IOException If there is an error accessing data.
     */
    public void decryptDocument(PDDocument doc, DecryptionMaterial decryptionMaterial)
        throws CryptographyException, IOException
    {
        this.document = doc;
        
        PDEncryptionDictionary dictionary = doc.getEncryptionDictionary();
        
        if(dictionary.getLength() != 0)
        {
            this.keyLength = dictionary.getLength();
        }
        
        if(!(decryptionMaterial instanceof PublicKeyDecryptionMaterial))
        {
            throw new CryptographyException(
                "Provided decryption material is not compatible with the document");
        }
        
        PublicKeyDecryptionMaterial material = (PublicKeyDecryptionMaterial)decryptionMaterial;        
        
        try
        {
            boolean foundRecipient = false;            
        
            // the decrypted content of the enveloped data that match 
            // the certificate in the decryption material provided    
            byte[] envelopedData = null;            
            
            // the bytes of each recipient in the recipients array
            byte[][] recipientFieldsBytes = new byte[dictionary.getRecipientsLength()][];
            
            int recipientFieldsLength = 0;
            
            for(int i=0; i<dictionary.getRecipientsLength(); i++)
            {
                COSString recipientFieldString = dictionary.getRecipientStringAt(i);
                byte[] recipientBytes = recipientFieldString.getBytes();
                CMSEnvelopedData data = new CMSEnvelopedData(recipientBytes);
                Iterator recipCertificatesIt = data.getRecipientInfos().getRecipients().iterator();
                while(recipCertificatesIt.hasNext())
                {
                    RecipientInformation ri = 
                        (RecipientInformation)recipCertificatesIt.next();
                    // Impl: if a matching certificate was previously found it is an error, 
                    // here we just don't care about it
                    if(ri.getRID().match(material.getCertificate()) && !foundRecipient)
                    {
                        foundRecipient = true;
                        envelopedData = ri.getContent(material.getPrivateKey(), "BC");            
                    }
                }
                recipientFieldsBytes[i] = recipientBytes;
                recipientFieldsLength += recipientBytes.length;
            }
            if(!foundRecipient || envelopedData == null)
            {
                throw new CryptographyException("The certificate matches no recipient entry");
            }
            if(envelopedData.length != 24)
            {
                throw new CryptographyException("The enveloped data does not contain 24 bytes");
            }
            // now envelopedData contains:
            // - the 20 bytes seed
            // - the 4 bytes of permission for the current user                          
            
            byte[] accessBytes = new byte[4];
            System.arraycopy(envelopedData, 20, accessBytes, 0, 4);
            
            currentAccessPermission = new AccessPermission(accessBytes);
            currentAccessPermission.setReadOnly();
            
             // what we will put in the SHA1 = the seed + each byte contained in the recipients array 
            byte[] sha1Input = new byte[recipientFieldsLength + 20];
            
            // put the seed in the sha1 input
            System.arraycopy(envelopedData, 0, sha1Input, 0, 20); 
            
            // put each bytes of the recipients array in the sha1 input
            int sha1InputOffset = 20;            
            for(int i=0; i<recipientFieldsBytes.length; i++)
            {
                System.arraycopy(

⌨️ 快捷键说明

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