Java 执行程序时出现Itext签名pdf错误

Java 执行程序时出现Itext签名pdf错误,java,itext,digital-signature,Java,Itext,Digital Signature,我想执行数字签名程序并制作签名pdf。 为此 1.我使用以下源代码 2.对于证书,使用此链接创建自签名证书并导出到pfx。 3.现在尝试执行以下程序,但仍然给出以下错误 /* * This class is part of the book "iText in Action - 2nd Edition" * written by Bruno Lowagie (ISBN: 9781935182610) * For more info, go to: http://itextpdf.c

我想执行数字签名程序并制作签名pdf。 为此 1.我使用以下源代码 2.对于证书,使用此链接创建自签名证书并导出到pfx。 3.现在尝试执行以下程序,但仍然给出以下错误

    /*
 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to: http://itextpdf.com/examples/
 * This example only works with the AGPL version of iText.
 */
package iText;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Properties;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.security.BouncyCastleDigest;
import com.itextpdf.text.pdf.security.CertificateInfo;
import com.itextpdf.text.pdf.security.CertificateVerification;
import com.itextpdf.text.pdf.security.ExternalDigest;
import com.itextpdf.text.pdf.security.ExternalSignature;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.itextpdf.text.pdf.security.PrivateKeySignature;
import com.itextpdf.text.pdf.security.MakeSignature;
import com.itextpdf.text.pdf.security.PdfPKCS7;
import com.itextpdf.text.pdf.security.VerificationException;

public class Signatures {

    /**
     * The resulting PDF
     */
    public static String ORIGINAL = "C:\\Users\\02948\\Desktop\\hello.pdf";
    /**
     * The resulting PDF
     */
    public static String SIGNED1 = "C:\\Users\\02948\\Desktop\\signature_1.pdf";
    /**
     * The resulting PDF
     */
    public static String SIGNED2 = "C:\\Users\\02948\\Desktop\\signature_2.pdf";
    /**
     * Info after verification of a signed PDF
     */
    public static String VERIFICATION = "C:\\Users\\02948\\Desktop\\verify.txt";
    /**
     * The resulting PDF
     */
    public static String REVISION = "C:\\Users\\02948\\Desktop\\revision_1.pdf";

    /**
     * A properties file that is PRIVATE. You should make your own properties
     * file and adapt this line.
     */
    public static String PATH = "C:\\Users\\02948\\Documents\\NetBeansProjects\\DigiSig\\src\\digisig\\key.properties";
    /**
     * Some properties used when signing.
     */
    public static Properties properties = new Properties();

    /**
     * One of the resources.
     */
    //   public static final String RESOURCE = "resources/img/logo.gif";
    /**
     * Creates a PDF document.
     *
     * @param filename the path to the new PDF document
     * @throws DocumentException
     * @throws IOException
     */
    public void createPdf(String filename) throws IOException, DocumentException {
        Document document = new Document();
        PdfWriter.getInstance(document, new FileOutputStream(filename));
        document.open();
        document.add(new Paragraph("Hello World!"));
        document.close();
    }

    /**
     * Manipulates a PDF file src with the file dest as result
     *
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     * @throws GeneralSecurityException
     */
    public void signPdfFirstTime(String src, String dest)
            throws IOException, DocumentException, GeneralSecurityException {
//        String path = properties.getProperty("PRIVATE");
//        String keystore_password = properties.getProperty("PASSWORD");
//        String key_password = properties.getProperty("PASSWORD");
        String path = "C:\\Users\\02948\\Desktop\\kandarp.pfx";
        String keystore_password = "kandarp";
        String key_password = "kandarp";

        KeyStore ks = KeyStore.getInstance("pkcs12", "BC");
        ks.load(new FileInputStream(path), keystore_password.toCharArray());
        String alias = (String) ks.aliases().nextElement();
        PrivateKey pk = (PrivateKey) ks.getKey(alias, key_password.toCharArray());
        Certificate[] chain = ks.getCertificateChain(alias);
        // reader and stamper
        PdfReader reader = new PdfReader(src);
        FileOutputStream os = new FileOutputStream(dest);
        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0');
        // appearance
        PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
//        appearance.setImage(Image.getInstance(RESOURCE));
        appearance.setReason("I've written this.");
        appearance.setLocation("Foobar");
        appearance.setVisibleSignature(new Rectangle(72, 732, 144, 780), 1, "first");
        // digital signature
        ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC");
        ExternalDigest digest = new BouncyCastleDigest();
        MakeSignature.signDetached(appearance, digest, es, chain, null, null, null, 0, CryptoStandard.CMS);
    }

    /**
     * Manipulates a PDF file src with the file dest as result
     *
     * @param src the original PDF
     * @param dest the resulting PDF
     * @throws IOException
     * @throws DocumentException
     * @throws GeneralSecurityException
     */
    public void signPdfSecondTime(String src, String dest)
            throws IOException, DocumentException, GeneralSecurityException {
        String path = "resources/encryption/.keystore";
        String keystore_password = "f00b4r";
        String key_password = "f1lmf3st";
        String alias = "foobar";
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(new FileInputStream(path), keystore_password.toCharArray());
        PrivateKey pk = (PrivateKey) ks.getKey(alias, key_password.toCharArray());
        Certificate[] chain = ks.getCertificateChain(alias);
        // reader / stamper
        PdfReader reader = new PdfReader(src);
        FileOutputStream os = new FileOutputStream(dest);
        PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);
        // appearance
        PdfSignatureAppearance appearance = stamper
                .getSignatureAppearance();
        appearance.setReason("I'm approving this.");
        appearance.setLocation("Foobar");
        appearance.setVisibleSignature(new Rectangle(160, 732, 232, 780), 1, "second");
        // digital signature
        ExternalSignature es = new PrivateKeySignature(pk, "SHA-256", "BC");
        ExternalDigest digest = new BouncyCastleDigest();
        MakeSignature.signDetached(appearance, digest, es, chain, null, null, null, 0, CryptoStandard.CMS);

    }

    /**
     * Verifies the signatures of a PDF we've signed twice.
     *
     * @throws GeneralSecurityException
     * @throws IOException
     */
    public void verifySignatures() throws GeneralSecurityException, IOException {
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(null, null);
        CertificateFactory cf = CertificateFactory.getInstance("X509");
        FileInputStream is1 = new FileInputStream(properties.getProperty("ROOTCERT"));
        X509Certificate cert1 = (X509Certificate) cf.generateCertificate(is1);
        ks.setCertificateEntry("cacert", cert1);
        FileInputStream is2 = new FileInputStream("resources/encryption/foobar.cer");
        X509Certificate cert2 = (X509Certificate) cf.generateCertificate(is2);
        ks.setCertificateEntry("foobar", cert2);

        PrintWriter out = new PrintWriter(new FileOutputStream(VERIFICATION));
        PdfReader reader = new PdfReader(SIGNED2);
        AcroFields af = reader.getAcroFields();
        ArrayList<String> names = af.getSignatureNames();
        for (String name : names) {
            out.println("Signature name: " + name);
            out.println("Signature covers whole document: " + af.signatureCoversWholeDocument(name));
            out.println("Document revision: " + af.getRevision(name) + " of " + af.getTotalRevisions());
            PdfPKCS7 pk = af.verifySignature(name);
            Calendar cal = pk.getSignDate();
            Certificate[] pkc = pk.getCertificates();
            out.println("Subject: " + CertificateInfo.getSubjectFields(pk.getSigningCertificate()));
            out.println("Revision modified: " + !pk.verify());
            List<VerificationException> errors = CertificateVerification.verifyCertificates(pkc, ks, null, cal);
            if (errors.size() == 0) {
                out.println("Certificates verified against the KeyStore");
            } else {
                out.println(errors);
            }
        }
        out.flush();
        out.close();
    }

    /**
     * Extracts the first revision of a PDF we've signed twice.
     *
     * @throws IOException
     */
    public void extractFirstRevision() throws IOException {
        PdfReader reader = new PdfReader(SIGNED2);
        AcroFields af = reader.getAcroFields();
        FileOutputStream os = new FileOutputStream(REVISION);
        byte bb[] = new byte[1028];
        InputStream ip = af.extractRevision("first");
        int n = 0;
        while ((n = ip.read(bb)) > 0) {
            os.write(bb, 0, n);
        }
        os.close();
        ip.close();
    }

    /**
     * Main method.
     *
     * @param args no arguments needed
     * @throws DocumentException
     * @throws IOException
     * @throws GeneralSecurityException
     */
    public static void main(String[] args)
            throws IOException, DocumentException, GeneralSecurityException {
        Security.addProvider(new BouncyCastleProvider());
        FileInputStream fis = new FileInputStream("C:\\Users\\02948\\Desktop\\kandarp.pfx");
        String password = "kandarp";
        properties.load(new FileInputStream(PATH));
        Signatures signatures = new Signatures();
        signatures.createPdf(ORIGINAL);
        signatures.signPdfFirstTime(ORIGINAL, SIGNED1);
        signatures.signPdfSecondTime(SIGNED1, SIGNED2);
        signatures.verifySignatures();
        signatures.extractFirstRevision();
    }
}
/*
*本课程是《iText行动-第二版》一书的一部分
*布鲁诺·洛瓦吉撰写(ISBN:9781935182610)
*有关更多信息,请转到:http://itextpdf.com/examples/
*此示例仅适用于iText的AGPL版本。
*/
包iText;
导入java.io.FileInputStream;
导入java.io.FileOutputStream;
导入java.io.IOException;
导入java.io.InputStream;
导入java.io.PrintWriter;
导入java.security.GeneralSecurityException;
导入java.security.KeyStore;
导入java.security.PrivateKey;
导入java.security.security;
导入java.security.cert.Certificate;
导入java.security.cert.CertificateFactory;
导入java.security.cert.x509证书;
导入java.util.ArrayList;
导入java.util.Calendar;
导入java.util.List;
导入java.util.Properties;
导入org.bouncycastle.jce.provider.BouncyCastleProvider;
导入com.itextpdf.text.Document;
导入com.itextpdf.text.DocumentException;
导入com.itextpdf.text.Image;
导入com.itextpdf.text.paragration;
导入com.itextpdf.text.Rectangle;
导入com.itextpdf.text.pdf.AcroFields;
导入com.itextpdf.text.pdf.PdfReader;
导入com.itextpdf.text.pdf.pdfsignaturepearance;
导入com.itextpdf.text.pdf.PdfStamper;
导入com.itextpdf.text.pdf.PdfWriter;
导入com.itextpdf.text.pdf.security.BouncyCastleDigest;
导入com.itextpdf.text.pdf.security.CertificateInfo;
导入com.itextpdf.text.pdf.security.CertificateVerification;
导入com.itextpdf.text.pdf.security.ExternalDigest;
导入com.itextpdf.text.pdf.security.ExternalSignature;
导入com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
导入com.itextpdf.text.pdf.security.PrivateKeySignature;
导入com.itextpdf.text.pdf.security.MakeSignature;
导入com.itextpdf.text.pdf.security.PdfPKCS7;
导入com.itextpdf.text.pdf.security.VerificationException;
公共类签名{
/**
*生成的PDF
*/
公共静态字符串ORIGINAL=“C:\\Users\\02948\\Desktop\\hello.pdf”;
/**
*生成的PDF
*/
公共静态字符串SIGNED1=“C:\\Users\\02948\\Desktop\\signature\u 1.pdf”;
/**
*生成的PDF
*/
公共静态字符串SIGNED2=“C:\\Users\\02948\\Desktop\\signature\u 2.pdf”;
/**
*签名PDF验证后的信息
*/
公共静态字符串验证=“C:\\Users\\02948\\Desktop\\verify.txt”;
/**
*生成的PDF
*/
公共静态字符串REVISION=“C:\\Users\\02948\\Desktop\\REVISION\u 1.pdf”;
/**
*一个私有的属性文件。您应该创建自己的属性
*归档并调整此行。
*/
公共静态字符串PATH=“C:\\Users\\02948\\Documents\\NetBeansProjects\\DigiSig\\src\\DigiSig\\key.properties”;
/**
*签名时使用的某些属性。
*/
公共静态属性=新属性();
/**
*资源之一。
*/
//公共静态最终字符串RESOURCE=“resources/img/logo.gif”;
/**
*创建PDF文档。
*
*@param filename新PDF文档的路径
*@DocumentException
*@抛出异常
*/
public void createPdf(字符串文件名)引发IOException、DocumentException{
文档=新文档();
getInstance(文档,新文件输出流(文件名));
document.open();
添加(新段落(“你好,世界!”);
document.close();
}
/**
*操作PDF文件src,结果为文件dest
*
*@param src原始PDF
*@param dest生成的PDF
*@抛出异常
*@DocumentException
*@throws-GeneralSecurityException
*/
public void signPdfFirstTime(String src,String dest)
抛出IOException、DocumentException、GeneralSecurityException{
//字符串路径=properties.getProperty(“PRIVATE”);
//字符串keystore_password=properties.getProperty(“密码”);
//字符串key_password=properties.getProperty(“密码”);
String path=“C:\\Users\\02948\\Desktop\\kandarp.pfx”;
字符串keystore_password=“kandarp”;
字符串键\u password=“kandarp”;
KeyStore ks=KeyStore.getInstance(“pkcs12”、“BC”);
load(新文件输入流(路径),keystore_password.toCharArray());
字符串别名=(字符串)ks.alias().nextElement();
PrivateKey pk=(PrivateKey)ks.getKey(别名,key_password.tocharray());
证书[]链=ks.getCertificateChain(别名);
//读卡器和压模
PdfReader读取器=新PdfReader(src);
FileOutputStream os=新的FileOutputStream(dest);
PdfStamper stamper=PdfStamper.createSignature(读卡器,操作系统,'\0');
//外表
PdfSignatureAppearance外观=母版。getSignatureAppearance();
//setImage(Image.getInstance(RESOURCE));
setReason(“我写了这个。”);
外观。设置位置(“Foobar”);
外观。setVisibleSignature(新矩形(72732144780),1,“第一”);
//数字签名
外部签名es=新的私有密钥签名(pk,“SHA-256”,“BC”);
ExternalDigest=新的BouncyCastleDigest();
签名分离(外观、摘要、es、链、null、null、null、null、0、CryptoStandard.CMS);
}
/**
*操作PDF文件src,结果为文件dest
*
*@param src原始PDF
*@param dest生成的PDF
*@抛出异常
*@DocumentException
*@throws-GeneralSecurityException
*/
public void signPdfSecondTime(String src,String dest)
T
Exception in thread "main" java.lang.NullPointerException
at com.itextpdf.text.pdf.security.PrivateKeySignature.<init>(PrivateKeySignature.java:77)
at iText.Signatures.signPdfFirstTime(Signatures.java:135)
at iText.Signatures.main(Signatures.java:252)
KeyStore ks = KeyStore.getInstance("pkcs12", "BC");
KeyStore ks = KeyStore.getInstance("pkcs12");