【Java 添加、验证PDF 数字签名】

在设置文档内容保护的方法中,除了对文档加密、添加水印外,应用数字签名也是一种有效的文档防伪、保护手段。数字签名的文件很容易验证,并且具有较高的权威性和可信度。在Adobe PDF文档中,有直接添加或验证数字签名的功能和方法,下面的文章中,将通过Java程序来介绍添加数字签名到PDF文档,以及验证签名是否有效。

使用工具:Spire.PDF for Java

Jar文件获取及导入方法:各种文件

		<dependency>
			<groupId>e-iceblue</groupId>
			<artifactId>spire.doc.free</artifactId>
			<version>5.2.0</version>
		</dependency>

    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.pdf.free</artifactId>
        <version>5.1.0</version>
    </dependency>


	
    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.xls.free</artifactId>
        <version>5.1.0</version>
    </dependency>

    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.presentation.free</artifactId>
        <version>5.1.0</version>
    	</dependency>
	</dependencies>
	
	<dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.office.free</artifactId>
        <version>5.3.1</version>
    </dependency>

Java代码示例
【示例1】添加数字签名到PDF

import com.spire.pdf.*;
import com.spire.pdf.graphics.PdfImage;
import com.spire.pdf.graphics.PdfTrueTypeFont;
import com.spire.pdf.security.GraphicMode;
import com.spire.pdf.security.PdfCertificate;
import com.spire.pdf.security.PdfCertificationFlags;
import com.spire.pdf.security.PdfSignature;

import java.awt.*;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

public class AddCertificate {
 public static void main(String[]args){
        //加载PDF文档
        PdfDocument doc = new PdfDocument();
        doc.loadFromFile("test.pdf");

        //加载pfx证书,及证书秘钥
        PdfCertificate cert = new PdfCertificate("Cermia.pfx","123654yes!");

        //添加数字签名到指定页面,并设置其位置和大小
        PdfSignature signature = new PdfSignature(doc, doc.getPages().get(2), cert, "MySignature");
        Rectangle2D rect = new Rectangle2D.Float();
        rect.setFrame(new Point2D.Float((float) doc.getPages().get(0).getActualSize().getWidth() - 340, (float) doc.getPages().get(0).getActualSize().getHeight() - 230), new Dimension(280, 150));
        signature.setBounds(rect);

        //设置签名为图片加文本模式
        signature.setGraphicMode(GraphicMode.Sign_Image_And_Sign_Detail);

        //设置签名的内容
        signature.setNameLabel("签字者:");
        signature.setName("Mia");
        signature.setContactInfoLabel("联系电话:");
        signature.setContactInfo("02881705109");
        signature.setDateLabel("日期:");
        signature.setDate(new java.util.Date());
        signature.setLocationInfoLabel("地点:");
        signature.setLocationInfo("成都");
        signature.setReasonLabel("原因:");
        signature.setReason("文档所有者");
        signature.setDistinguishedNameLabel("DN: ");
        signature.setDistinguishedName(signature.getCertificate().get_IssuerName().getName());
        signature.setSignImageSource(PdfImage.fromFile("sign.png"));

        //设置签名的字体
        signature.setSignDetailsFont(new PdfTrueTypeFont(new Font("Arial Unicode MS", Font.PLAIN, 9)));

        //设置文档权限为禁止更改
        signature.setDocumentPermissions(PdfCertificationFlags.Forbid_Changes);
        signature.setCertificated(true);

        //保存文档
        doc.saveToFile("AddSignature.pdf");
        doc.close();
    }
}

数字签名添加效果:
在这里插入图片描述
【示例2】验证数字签名有效性

import com.spire.pdf.*;
import com.spire.pdf.security.PdfSignature;
import com.spire.pdf.widget.PdfFormFieldWidgetCollection;
import com.spire.pdf.widget.PdfFormWidget;
import com.spire.pdf.widget.PdfSignatureFieldWidget;

import javax.swing.*;

public class ValidateSignature {
 public static void main(String[]args){
       //创建PdfDocument实例
       PdfDocument doc = new PdfDocument();
       //加载含有签名的PDF文件
       doc.loadFromFile("SignnedFile.pdf");

       //获取域集合
       PdfFormWidget pdfFormWidget = (PdfFormWidget) doc.getForm();
       PdfFormFieldWidgetCollection pdfFormFieldWidgetCollection = pdfFormWidget.getFieldsWidget();

       //遍历域
       for (int i = 0; i < pdfFormFieldWidgetCollection.getCount(); i++) {
            //判定是否为签名域
            if (pdfFormFieldWidgetCollection.get(i) instanceof PdfSignatureFieldWidget) {
            //获取签名域
                PdfSignatureFieldWidget signatureFieldWidget = (PdfSignatureFieldWidget) pdfFormFieldWidgetCollection.get(i);
                //获取签名
                PdfSignature signature = signatureFieldWidget.getSignature();

                //判定签名是否有效
                boolean result = signature.verifySignature();
                   if (result) {
                    String str1 =" 有效签名";
                    JOptionPane.showMessageDialog(null,str1);
                      } else {
                      String str2 =" 无效签名";
                    JOptionPane.showMessageDialog(null,str2);
                }
            }
        }

    }
}

验证结果:

在这里插入图片描述

示例三:阿里oss地址转换实例

import com.cnmyhr.base.exception.BaseBusinessException;
import com.cnmyhr.base.util.FileUtil;
import com.cnmyhr.base.vo.contract.PDFContractValidateSignatureVO;
import com.cnmyhr.contract.service.HandleContractService;
import com.cnmyhr.contract.service.ValidateSignatureService;
import com.spire.pdf.PdfDocument;
import com.spire.pdf.security.PdfSignature;
import com.spire.pdf.widget.PdfFormFieldWidgetCollection;
import com.spire.pdf.widget.PdfFormWidget;
import com.spire.pdf.widget.PdfSignatureFieldWidget;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public boolean validatePDFContract(String signUrl){
        File file = null;
        try {
            int indexOf = signUrl.lastIndexOf(".");
            String substring = signUrl.substring(indexOf);
            if(!".pdf".equals(substring)){
                throw new BaseBusinessException("不是PDF合同文件!");
            }
            long currentTimeMillis = System.currentTimeMillis();
            String temporaryDirectory = FileUtil.getTemporaryDirectory();
            String filePath = temporaryDirectory + currentTimeMillis + substring;
            URL url = new URL(signUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            int responseCode = conn.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                InputStream is = conn.getInputStream();
                file = new File(filePath); // 指定保存文件的路径和名称
                if(!file.exists()){
                    File temporaryDirectoryFile = new File(temporaryDirectory);
                    temporaryDirectoryFile.mkdirs();
                    file.createNewFile();
                }
                FileOutputStream fos = new FileOutputStream(file);
                byte[] buffer = new byte[4096];
                int len;
                while ((len = is.read(buffer)) > 0) {
                    fos.write(buffer, 0, len);
                }
                fos.close();
                is.close();
            } else {
                throw new BaseBusinessException("文件地址不正确!");
            }
            //创建PdfDocument实例
            PdfDocument doc = new PdfDocument();
            //加载含有签名的PDF文件
            doc.loadFromFile(filePath);
            //获取域集合
            PdfFormWidget pdfFormWidget = (PdfFormWidget) doc.getForm();
            PdfFormFieldWidgetCollection pdfFormFieldWidgetCollection = pdfFormWidget.getFieldsWidget();
            //遍历域
            for (int i = 0; i < pdfFormFieldWidgetCollection.getCount(); i++) {
                //判定是否为签名域
                if (pdfFormFieldWidgetCollection.get(i) instanceof PdfSignatureFieldWidget) {
                    //获取签名域
                    PdfSignatureFieldWidget signatureFieldWidget = (PdfSignatureFieldWidget) pdfFormFieldWidgetCollection.get(i);
                    //获取签名
                    PdfSignature signature = signatureFieldWidget.getSignature();
                    //判定签名是否有效
                    try {
                        boolean result = signature.verifySignature();
                        if (result) {
                            return true;
                        } else {
                            return false;
                        }
                    }catch (Exception e){
                        return false;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BaseBusinessException("文件核验失败 请重试!");
        }finally {
            file.delete();
        }
        return false;
   }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要在Java中将数字签名添加PDF,可以使用以下步骤: 1. 安装Bouncy Castle库,它是一个Java密码学库,提供了数字签名和加密等功能。 2. 创建一个KeyStore对象,用于存储数字证书和私钥。 3. 加载证书和私钥到KeyStore对象中。 4. 创建一个PdfReader对象,以便读取PDF文档。 5. 创建PdfStamper对象,以便向PDF文档添加数字签名。 6. 创建PdfSignatureAppearance对象,设置签名的外观,如位置、大小和颜色等。 7. 创建一个Bouncy Castle的实现类,用于数字签名的生成和验证。 8. 生成数字签名,并将其添加PDF文档中。 以下是一个简单的Java代码示例,用于将数字签名添加PDF: ``` // 加载Bouncy Castle库 Security.addProvider(new BouncyCastleProvider()); // 创建KeyStore对象 KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); ks.load(new FileInputStream("keystore.jks"), "password".toCharArray()); // 加载证书和私钥 String alias = (String) ks.aliases().nextElement(); PrivateKey key = (PrivateKey) ks.getKey(alias, "password".toCharArray()); Certificate[] chain = ks.getCertificateChain(alias); // 创建PdfReader对象 PdfReader reader = new PdfReader("input.pdf"); // 创建PdfStamper对象 PdfStamper stamper = PdfStamper.createSignature(reader, new FileOutputStream("output.pdf"), '\0', null, true); // 创建PdfSignatureAppearance对象 PdfSignatureAppearance appearance = stamper.getSignatureAppearance(); appearance.setReason("Digital signature"); appearance.setLocation("China"); appearance.setVisibleSignature(new Rectangle(100, 100, 200, 200), 1, "signature"); // 创建Bouncy Castle实现类 ExternalDigest digest = new BouncyCastleDigest(); ExternalSignature signature = new PrivateKeySignature(key, "SHA-256", "BC"); // 生成数字签名 MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0, MakeSignature.CryptoStandard.CMS); // 关闭PdfStamper对象和PdfReader对象 stamper.close(); reader.close(); ``` 请注意,此代码示例仅提供了一种可能的实现方式,具体实现方式可能因不同的应用场景而有所不同。在实际应用中,还需要考虑数字证书的验证PDF文档的安全性等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值