PDF文件的数字签名

对PDF文件的数字签名过程不复杂,使用itext开源包即可快速完成签名并用于项目,同时支持在签名处显示图章。

一、准备好pkcs12格式的证书,可参考网上的方法。
二、准备好图章图片。
三、在项目的pom.xml文件中增加依赖


	com.itextpdf
	kernel
	7.2.5


	com.itextpdf
	sign
	7.2.5

四、运行以下代码即可对PDF文件进行签名,参考代码如下。

import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.StampingProperties;
import com.itextpdf.signatures.BouncyCastleDigest;
import com.itextpdf.signatures.DigestAlgorithms;
import com.itextpdf.signatures.IExternalDigest;
import com.itextpdf.signatures.IExternalSignature;
import com.itextpdf.signatures.PdfSignatureAppearance;
import com.itextpdf.signatures.PdfSignatureAppearance.RenderingMode;
import com.itextpdf.signatures.PdfSigner;
import com.itextpdf.signatures.PrivateKeySignature;
import com.itextpdf.text.BadElementException;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

// https://itextpdf.com/solutions/electronic-signatures-pdf
public class PdfSign {

    public static final String DEST = "C:/tmp/hello_signed1.pdf";
    public static final String KEYSTORE = "C:/tmp/cert/client.pkcs12";
    public static final String SRC = "C:/tmp/etx.pdf";
    public static final char[] PASSWORD = "changeit".toCharArray();

    public void sign(String src, String dest, Certificate[] chain, PrivateKey pk, String digestAlgorithm,
            String provider, PdfSigner.CryptoStandard signatureType, String reason, String location)
            throws GeneralSecurityException, IOException, BadElementException {
        PdfReader reader = new PdfReader(src);
        PdfSigner signer = new PdfSigner(reader, new FileOutputStream(dest), new StampingProperties());

        // Create the signature appearance
        Rectangle rect = new Rectangle(36, 648, 200, 100); // location of signature
        PdfSignatureAppearance appearance = signer.getSignatureAppearance();
        appearance.setReason(reason).setLocation(location);
        // Specify if the appearance before field is signed will be used
        // as a background for the signed field. The "false" value is the default value.
        appearance.setReuseAppearance(false).setPageRect(rect).setPageNumber(1);
        // show image for the signature
        ImageData img = ImageDataFactory.create("C:/tmp/Dummy1.png");
        appearance.setSignatureGraphic(img);
        appearance.setRenderingMode(RenderingMode.GRAPHIC);

        signer.setFieldName("sig");
        IExternalSignature pks = new PrivateKeySignature(pk, digestAlgorithm, provider);
        IExternalDigest digest = new BouncyCastleDigest();
        // Sign the document using the detached mode, CMS or CAdES equivalent.
        signer.signDetached(digest, pks, chain, null, null, null, 0, signatureType);
    }

    public static void main(String[] args) throws Exception {
        BouncyCastleProvider provider = new BouncyCastleProvider();
        Security.addProvider(provider);
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(new FileInputStream(KEYSTORE), PASSWORD);
        String alias = ks.aliases().nextElement();
        PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);
        Certificate[] chain = ks.getCertificateChain(alias);

        PdfSign app = new PdfSign();
        app.sign(SRC, DEST, chain, pk, DigestAlgorithms.SHA256, provider.getName(), PdfSigner.CryptoStandard.CMS,
                "Approved by manager", "Approved at Ghent");
        System.out.println("pdf sign success");
    }

}

你可能感兴趣的:(pdf,java,开发语言)