一、制作公章
在线网站:印章生成器 - Kalvin在线工具 (kalvinbg.cn)
然后对公章进行下载保存
盖章图片:
二、生成数字签名
2.1: java工具keytool生成p12数字证书文件
Keytool是用于管理和证书的工具,位于%JAVA_HOME%/bin目录。
使用JDK的keytool工具
- keytool在jdk的bin目录下
2.2:启动黑窗命令
2.3:生成数字文件
D:\keystore\server.keystore : 就是生成的文件地址
keytool -genkeypair -alias whj -keypass 111111 -storepass 111111 -dname “C=CN,ST=SD,L=QD,O=haier,OU=dev,CN=haier.com” -keyalg RSA -keysize 2048 -validity 3650 -keystore D:\keystore\server.keystore
2.4:转换为p12格式,在命令行输入
注意:这里的路径和上面的路径要保持一直,不能就转不了P12 格式
keytool -importkeystore -srckeystore D:\keystore\server.keystore -destkeystore D:\keystore\whj.p12 -srcalias whj -destalias serverkey -srcstoretype jks -deststoretype pkcs12 -srcstorepass 111111 -deststorepass 111111 -noprompt
三、代码部分
3.1:添加依赖:
<!-- itextpdf依赖 --><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.10</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version></dependency><dependency><!-- 摘要算法 --><dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.49</version></dependency><dependency><groupId>org.bouncycastle</groupId><artifactId>bcpkix-jdk15on</artifactId><version>1.49</version></dependency>
3.2:盖章功能工具类
功能:
对传入的pdf 文件进行盖章处理
public class ItextUtil {/**** 功能: keystory密码*/public static final char[] PASSWORD = "111111".toCharArray();/*** 单多次签章通用** @param src 盖章文件路径* @param target 盖章文件输出目标路径* @param signatureInfo 盖章实体*/public void sign(String src, String target, SignatureInfo signatureInfo) {InputStream inputStream = null;FileOutputStream outputStream = null;ByteArrayOutputStream result = new ByteArrayOutputStream();try {inputStream = Files.newInputStream(Paths.get(src));ByteArrayOutputStream tempArrayOutputStream = new ByteArrayOutputStream();PdfReader reader = new PdfReader(inputStream);// 创建签章工具PdfStamper ,最后一个boolean参数是否允许被追加签名// false的话,pdf文件只允许被签名一次,多次签名,最后一次有效// true的话,pdf可以被追加签名,验签工具可以识别出每次签名之后文档是否被修改PdfStamper stamper = PdfStamper.createSignature(reader,tempArrayOutputStream, '\0', null, true);// 获取数字签章属性对象PdfSignatureAppearance appearance = stamper.getSignatureAppearance();appearance.setReason(signatureInfo.getReason());appearance.setLocation(signatureInfo.getLocation());// 设置签名的位置,页码,签名域名称,多次追加签名的时候,签名预名称不能一样 图片大小受表单域大小影响(过小导致压缩)// 签名的位置,是图章相对于pdf页面的位置坐标,原点为pdf页面左下角// 四个参数的分别是,图章左下角x,图章左下角y,图章右上角x,图章右上角y//四个参数的分别是,图章左下角x,图章左下角y,图章右上角x,图章右上角yappearance.setVisibleSignature(new Rectangle(280, 220, 140, 600), 1, "sig1");// 读取图章图片Image image = Image.getInstance(signatureInfo.getImagePath());appearance.setSignatureGraphic(image);appearance.setCertificationLevel(signatureInfo.getCertificationLevel());// 设置图章的显示方式,如下选择的是只显示图章(还有其他的模式,可以图章和签名描述一同显示)appearance.setRenderingMode(signatureInfo.getRenderingMode());// 这里的itext提供了2个用于签名的接口,可以自己实现,后边着重说这个实现// 摘要算法ExternalDigest digest = new BouncyCastleDigest();// 签名算法ExternalSignature signature = new PrivateKeySignature(signatureInfo.getPk(), signatureInfo.getDigestAlgorithm(),null);// 调用itext签名方法完成pdf签章 //数字签名格式,CMS,CADEMakeSignature.signDetached(appearance, digest, signature,signatureInfo.getChain(), null, null, null, 0,MakeSignature.CryptoStandard.CADES);inputStream = new ByteArrayInputStream(tempArrayOutputStream.toByteArray());// 定义输入流为生成的输出流内容,以完成多次签章的过程result = tempArrayOutputStream;outputStream = new FileOutputStream(new File(target));outputStream.write(result.toByteArray());outputStream.flush();} catch (Exception e) {e.printStackTrace();} finally {try {if (null != outputStream) {outputStream.close();}if (null != inputStream) {inputStream.close();}if (null != result) {result.close();}} catch (IOException e) {e.printStackTrace();}}}}
测试代码:
public static void main(String[] args) {try {ItextUtil app = new ItextUtil();// 将证书文件放入指定路径,并读取keystore ,获得私钥和证书链String pkPath = "src/main/resources/whj.p12";KeyStore ks = KeyStore.getInstance("PKCS12");ks.load(Files.newInputStream(Paths.get(pkPath)), PASSWORD);String alias = ks.aliases().nextElement();PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);// 得到证书链Certificate[] chain = ks.getCertificateChain(alias);//需要进行签章的pdfString path = "C:\\Users\\ASUS\\Desktop\\sq.pdf";// 封装签章信息SignatureInfo signInfo = new SignatureInfo();signInfo.setReason("牛逼");signInfo.setLocation("666");signInfo.setPk(pk);signInfo.setChain(chain);signInfo.setCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED);signInfo.setDigestAlgorithm(DigestAlgorithms.SHA1);signInfo.setFieldName("demo");// 签章图片(网上生成的)signInfo.setImagePath("C:\\Users\\ASUS\\Desktop\\字节码\\学习测试30.png");signInfo.setRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC);值越大,代表向x轴坐标平移 缩小 (反之,值越小,印章会放大)signInfo.setRectllx(100);值越大,代表向y轴坐标向上平移(大小不变)signInfo.setRectlly(200);// 值越大 代表向x轴坐标向右平移 (大小不变)signInfo.setRecturx(150);// 值越大,代表向y轴坐标向上平移(大小不变)signInfo.setRectury(150);//签章后的pdf路径app.sign(path, "C:\\Users\\ASUS\\Desktop\\字节码\\out.pdf", signInfo);} catch (Exception e) {e.printStackTrace();}}
实现对pdf 进行添加水印
一、添加水印工具类
public class WaterMark {/*** pdf生成水印** @param srcPdfPath 插入前的文件路径* @param tarPdfPath 插入后的文件路径* @param WaterMarkContent 水印文案* @param numberOfPage 每页需要插入的条数* @throws Exception*/public static void addWaterMark(String srcPdfPath, String tarPdfPath, String WaterMarkContent, int numberOfPage) throws Exception {PdfReader reader = new PdfReader(srcPdfPath);PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(tarPdfPath));PdfGState gs = new PdfGState();//设置字体BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);// 设置透明度gs.setFillOpacity(0.4f);int total = reader.getNumberOfPages() + 1;PdfContentByte content;for (int i = 1; i < total; i++) {content = stamper.getOverContent(i);content.beginText();content.setGState(gs);//水印颜色content.setColorFill(BaseColor.DARK_GRAY);//水印字体样式和大小content.setFontAndSize(font, 35);//插入水印 循环每页插入的条数for (int j = 0; j < numberOfPage; j++) {content.showTextAligned(Element.ALIGN_CENTER, WaterMarkContent, 300, 200 * (j + 1), 30);}content.endText();}stamper.close();reader.close();// 删除源文件,这个可以根据自己的需要来是否删除源文件boolean b = deleteFile(srcPdfPath);System.out.println("PDF水印添加完成!");}/**** 功能: 删除文件* @param path 需要删除的文件路径* @return {@link boolean}* @author luoheng*/public static boolean deleteFile(String path) {boolean result = false;File file = new File(path);if (file.isFile() && file.exists()) {int tryCount = 0;while (!result && tryCount++ < 10) {System.gc();result = file.delete();}}return result;}}
测试代码
我们传入需要加水印的pdf,设置对应的格式,数量,字体,以及对应输出的文件地址
public static void main(String[] args) {/*** pdf生成水印** @param srcPdfPath 需要加印的文件路径* @param tarPdfPath 加印后的文件输出路径* @param WaterMarkContent 水印文案* @param numberOfPage 每页需要插入的条数* @throws Exception*/String srcPdfPath = "C:\\Users\\ASUS\\Desktop\\字节码\\out.pdf";String tarPdfPath = "C:\\Users\\ASUS\\Desktop\\字节码\\out2.pdf";String WaterMarkContent = "程序员小王";Integer numberOfPage = 3;try {// 添加水印WaterMark.addWaterMark(srcPdfPath, tarPdfPath, WaterMarkContent, numberOfPage);} catch (Exception e) {e.printStackTrace();}}
效果图:
如果代码写的有问题,欢迎大家评论交流,进行指点!!!
也希望大家点个关注哦~~~~~~~~