当前位置: 首页 > news >正文

通过数字证书对PDF电子文件进行数字签名/盖章

以下代码详细说明如何使用数字证书对PDF电子文件进行数字签名/盖章。PDF文件签署主要传递PDF文件,数字证书信息,签章图片3个信息。代码中需要的文件、数字证书、签章图片可访问开放签电子签章开源系统详细了解系统的实现与效果。也可通过gitee开源社区下载开放签开源电子签章系统,获取所有开源代码。

1、数字签名/盖章类SignService.java

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.security.*;
import com.resrun.service.pojo.CertificateProperty;
import com.resrun.service.pojo.RealPositionProperty;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.stereotype.Service;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
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;/*** @Description: 签署业务* @Package: com.resrun.service.pdf* @ClassName: SignService* @copyright 北京资源律动科技有限公司 www.kaifangqian.com*/
@Service
public class SignService {public byte[] signingContract(byte[] pdfFile, byte[] signBadge, CertificateProperty cert,RealPositionProperty position) throws GeneralSecurityException, IOException, DocumentException {System.setProperty("javax.xml.parsers.DocumentBuilderFactory","com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");Security.addProvider(new BouncyCastleProvider());//1、解析证书// Java 安全属性文件中指定的默认 keystore 类型;如果不存在此类属性,则返回字符串 "jks"。 PKCS12KeyStore ks = KeyStore.getInstance(cert.getCertType());try {char[] chars = cert.getPassword().toCharArray();ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(cert.getCertFile());ks.load(byteArrayInputStream, chars);} catch (Exception e) {e.printStackTrace();}// 获取keystore中的所有别名String alias = (String) ks.aliases().nextElement();// 返回:请求的密钥, 入力参数:别名,用于恢复密钥的密码PrivateKey pk = (PrivateKey) ks.getKey(alias, cert.getPassword().toCharArray());// 证书链(按用户证书在前,根证书授权在后的顺序)Certificate[] chain = ks.getCertificateChain(alias);byte[] signedFileByte = null ;PdfReader reader = null ;ByteArrayOutputStream signedFile = null ;PdfStamper stamper = null ;try {//2、读取PDF文件reader = new PdfReader(pdfFile);signedFile = new ByteArrayOutputStream();stamper = PdfStamper.createSignature(reader, signedFile, '\0', null, true);//3、给签署属性服务PdfSignatureAppearance appearance = stamper.getSignatureAppearance();if (signBadge == null || position == null) {appearance.setCertificationLevel(certificationLevel);} else {int pageNum = 0;if (inspect) {//如果检查就会抛出检查异常pageNum = position.getPageNum();if (pageNum == 0)throw new IllegalArgumentException("Pdf page number must be greater than one....!!!");} else {pageNum = position.getPageNum() <= 0 ? 1 : position.getPageNum();}appearance.setVisibleSignature(new Rectangle(position.getStartx(), position.getStarty(), position.getEndx(), position.getEndy()), pageNum, null);// 添加签章图片Image img = Image.getInstance(signBadge);appearance.setSignatureGraphic(img);appearance.setImageScale(-1);appearance.setCertificationLevel(certificationLevel);appearance.setRenderingMode(renderingMode);}appearance.setReason(reason);appearance.setLocation(location);//4、调用签署  Creating the signatureExternalSignature pks = new PrivateKeySignature(pk, hashAlgorithm, BouncyCastleProvider.PROVIDER_NAME);ExternalDigest digest = new BouncyCastleDigest();MakeSignature.signDetached(appearance, digest, pks, chain, null, ocspClient, tsaClient, 0, cryptoStandard);signedFileByte = signedFile.toByteArray();} catch (Exception e){e.printStackTrace();}finally {// 关闭流if (stamper != null) stamper.close();if (signedFile != null) signedFile.close();if (reader != null) reader.close();}return signedFileByte ;}//是否判断校验不校验PDF页码private boolean inspect = true;private int certificationLevel = PdfSignatureAppearance.NOT_CERTIFIED;private PdfSignatureAppearance.RenderingMode renderingMode = PdfSignatureAppearance.RenderingMode.GRAPHIC;private String hashAlgorithm = DigestAlgorithms.SHA256;private MakeSignature.CryptoStandard cryptoStandard = MakeSignature.CryptoStandard.CMS;private String reason = "防伪造防篡改数字校验"; //原因private String location; //位置private TSAClient tsaClient; //时间戳服务private OcspClient ocspClient;public boolean isInspect() {return inspect;}public void setInspect(boolean inspect) {this.inspect = inspect;}public int getCertificationLevel() {return certificationLevel;}public void setCertificationLevel(int certificationLevel) {this.certificationLevel = certificationLevel;}public PdfSignatureAppearance.RenderingMode getRenderingMode() {return renderingMode;}public void setRenderingMode(PdfSignatureAppearance.RenderingMode renderingMode) {this.renderingMode = renderingMode;}public String getHashAlgorithm() {return hashAlgorithm;}public void setHashAlgorithm(String hashAlgorithm) {this.hashAlgorithm = hashAlgorithm;}public MakeSignature.CryptoStandard getCryptoStandard() {return cryptoStandard;}public void setCryptoStandard(MakeSignature.CryptoStandard cryptoStandard) {this.cryptoStandard = cryptoStandard;}public String getReason() {return reason;}public void setReason(String reason) {this.reason = reason;}public String getLocation() {return location;}public void setLocation(String location) {this.location = location;}public TSAClient getTsaClient() {return tsaClient;}public void setTsaClient(TSAClient tsaClient) {this.tsaClient = tsaClient;}public OcspClient getOcspClient() {return ocspClient;}public void setOcspClient(OcspClient ocspClient) {this.ocspClient = ocspClient;}}

2、证书文件属性类,主要存储证书信息CertificateProperty.java

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;/*** @Description: 证书文件属性类* @Package: com.resrun.service.pojo* @ClassName: CertificateProperty* @copyright 北京资源律动科技有限公司*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class CertificateProperty implements Serializable {private static final long serialVersionUID = -2073805779543816269L;private  byte[] certFile;/** 证书的类型 比如:PKCS12和jks*/private  String certType;/** 证书密码 */private  String password;}

3、签署位置信息类

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;/*** @Description: 经过计算后的文件签署位置属性类* @Package: com.resrun.service.pojo* @ClassName: PositionProperty* @copyright 北京资源律动科技有限公司*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class RealPositionProperty implements Serializable {private static final long serialVersionUID = 8586984409612483553L;/** 签章左下角x坐标 */private  float startx;/** 签章左下角y坐标*/private  float starty;/** 签章右上角x坐标*/private  float endx;/** 签章右上角x坐标*/private  float endy;private  int pageNum;// 填写值,填写专用private String value ;//对齐方式private String align ;//字体private String fontFamily ;//文字大小private Integer fontSize ;
}

相关文章:

通过数字证书对PDF电子文件进行数字签名/盖章

以下代码详细说明如何使用数字证书对PDF电子文件进行数字签名/盖章。PDF文件签署主要传递PDF文件&#xff0c;数字证书信息&#xff0c;签章图片3个信息。代码中需要的文件、数字证书、签章图片可访问开放签电子签章开源系统详细了解系统的实现与效果。也可通过gitee开源社区下…...

2007~2016 年税调经纬度及其所处的省市区县乡镇数据

之前给大家分享过一份税调企业经纬度及其所处的省市区县数据: 2007~2016 年税调企业地理信息数据(含经纬度及其所处的省市区县):https://rstata.duanshu.com/#/course/76d38022cd004b09b2aa09647936beb0 最近有培训班的小伙伴提出是否能根据税调企业经纬度来判断其所属的乡…...

SLAM学习入门--编程语言

文章目录 编程语言一、C/C++C 与 C++ 的区别(面向对象的特点)C++ 与 Python的区别判断struct的字节数static 作用Const 作用extern "C"的作用多态如何实现多态?虚函数虚函数怎么实现的?析构函数虚析构函数的作用virtual函数能不能用在构造函数中&#...

Go语言程序设计-第6章--方法

Go语言程序设计-第6章–方法 对象就是简单的一个值或者变量&#xff0c;并且拥有其方法&#xff0c;而方法是某种特定类型的函数。 6.1 方法的声明 方法的声明和普通函数的声明类似&#xff0c;只是在函数名字前面多了一个参数。这个参数把这个方法绑定到这个参数对应的类型…...

AI按理说应该最擅长理工,为啥先冲击文艺行业?

介绍 本人数据AI工程师&#xff0c;我的观点对全行业都有冲击&#xff0c;当AI大模型持续进化之时&#xff0c;没有一家公司能独善其身。 本文从产业架构上、论文体量、基础Pass能力、通用大模型、AI开源社区、业务属性大模型、内容消费工具、创作工具赛道、企业服务这些板块…...

蓝牙物联网移动硬件数据传输系统解决方案

随着传感器技术、网络技术和数据传输技术的不断发展&#xff0c;人们对智能设备的需求日渐增强,利用传感器技术可以对周围环境进行准确和全面的感知&#xff0c;获取到实时信息&#xff0c;从而在网络中进行传输和共享&#xff0c;再通过服务器对各种数据进行保存、分析和挖掘等…...

Linux下Web服务器工作模型及Nginx工作原理详解

文章目录 1. 工作模型概述1.1 阻塞、非阻塞、同步、异步浅析1.2 Web服务器处理并发请求的方式 2. Linux下的I/O模型2.1 常用I/O模型2.2 对比以上模型 3. Nginx工作原理3.1 Nginx基本架构3.2 Nginx代码结构3.3 Nginx工作流程3.4 Nginx缓存机制3.5 Nginx缓存工具&#xff1a;Memc…...

AJAX: 整理2:学习原生的AJAX,这边借助express框架

1. npm install express 终端直接安装 2. 测试案例&#xff1a;Hello World&#xff01; 新建一个express.js的文件&#xff0c;写入下方的内容 // 1. 引入express const express require(express)// 2. 创建服务器 const app express()// 3.创建路由规则 // request 是对请…...

二、计算机软件及其使用-文字处理软件 Word 2016

Word 2016 的功能&#xff1b;Word 2016 的启动方法和工作窗口 Word 2016 的功能 编辑功能、排版功能、表格处理功能、图形与公式处理功能、文档管理功能 Word 2016 的启动方法 桌面有就单击、任务栏有就单击、开始菜单中单击 Word 2016 的工作窗口 标题栏、功能区、工作区、状…...

Linux LVM逻辑卷

一、LVM的定义 LVM 是 Logical Volume Manager 的简称&#xff0c;译为中文就是逻辑卷管理。它是 Linux 下对硬盘分区的一种管理机制。LVM 适合于管理大存储设备&#xff0c;并允许用户动态调整文件系统的大小。此外&#xff0c;LVM 的快照功能可以帮助我们快速备份数据。LVM 为…...

Hive生产调优介绍

1.Fetch抓取 Fetch抓取是指&#xff0c;Hive中对某些情况的查询可以不必使用MapReduce计算。例如&#xff1a;SELECT * FROM employees;在这种情况下&#xff0c;Hive可以简单地读取employee对应的存储目录下的文件&#xff0c;然后输出查询结果到控制台。 在hive-default.xml…...

如何理解鼠标点击事件在程序中的处理

在计算机用户界面中&#xff0c;鼠标点击是一个常见的交互动作。那么&#xff0c;当你按下鼠标时&#xff0c;程序是如何知道这个点击是否针对它自己的按钮的呢&#xff1f;本文将探讨鼠标点击事件在操作系统和应用程序之间的传递过程。 鼠标点击事件的捕获 当你按下鼠标按钮…...

基于JWT的用户token验证

1. 基于session的用户验证 2. 基于token的用户身份验证 3. jwt jwt代码实现方式 1. 导包 <dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.18.2</version> </dependency> 2. 在登录…...

通过 conda 安装 的 detectron2

从 detectron2官网 发现预编译的版本最高支持 pytorch1.10、cuda11.3。&#xff08;2023-12-26&#xff09; 1、安装 conda 环境。 conda create --name detectron2 python3.8 2、安装 pytorch1.10 和 cuda11.3。 pip3 install torch1.10.0cu113 torchvision0.11.1cu113 torc…...

嵌入式开发——SPI OLED屏幕案例

学习目标 掌握移植方法掌握调试方式学习内容 需求 官方测试示例 选择对应的平台 测试示例中,找到芯片对应平台,我们选择的是STM32F407 修改例程 已知错误修改:...

ibm上电时序(视频内容)

...

如何在Vue.js中使用$emit进行组件通信

Vue.js是一个渐进式JavaScript框架&#xff0c;它以其简洁的数据绑定和组件系统而闻名。在构建具有多个组件层次的Vue应用时&#xff0c;组件间的通信成为一个关键的话题。Vue提供了一种名为$emit的方法&#xff0c;允许子组件向父组件发送消息。本文将详细介绍如何在Vue中使用…...

SPSS相关统计学知识精要回顾-大家都来做做

很多学生问我&#xff0c;学SPSS如果想深入学&#xff0c;那么统计学原理应该掌握到什么样的水准&#xff0c;我想说的是&#xff0c;如果真的想融会贯通&#xff0c;而不是短暂过关&#xff0c;那么应该具备一定的统计学基础&#xff0c;但是统计学知识也不是面面俱到都要去学…...

React Native 从类组件到函数组件

1. 发展趋势 React Native社区中的趋势是朝向使用函数组件&#xff08;Functional Components&#xff09;和Hooks的方向发展&#xff0c;而不是使用类组件&#xff08;Class Components&#xff09;。 React Native自推出Hooks API以来&#xff0c;函数组件和Hooks的使用变得…...

Redis 快速搭建与使用

文章目录 1. Redis 特性1.1 多种数据类型支持1.2 功能完善1.3 高性能1.4 广泛的编程语言支持1.5 使用简单1.6 活跃性高/版本迭代快1.7 I/O 多路复用模型 2. Redis发展历程3. Redis 安装3.1 源码安装3.1.1 下载源码包3.1.2 解压安装包3.1.3 切换到 Redis 目录3.1.4 编译安装 3.2…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...

人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent

安全大模型训练计划&#xff1a;基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标&#xff1a;为安全大模型创建高质量、去偏、符合伦理的训练数据集&#xff0c;涵盖安全相关任务&#xff08;如有害内容检测、隐私保护、道德推理等&#xff09;。 1.1 数据收集 描…...