2018-8-10

Java

Java iText 操作PDF

官页

嵌入 javascript

OutputStream os;//pdf out stream
PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null,true);
String jsString = "app.alert(event.change);";
stamper.addJavaScript( jsString);

adobe 官方关于acrobat javascript主页 adobe 官方使用文档 adobe 官方使用文档下载

实例数字签名 + 弹窗警告

  /**
     * @param password 秘钥密码
     * @param keyStorePath 秘钥文件路径
     * @param signPdfSrc  签名的PDF文件
     * @param signImage 签名图片文件
     * @param x x坐标
     * @param y y坐标
     * @return
     */
    public static byte[] sign(String password, String keyStorePath, String signPdfSrc, String signImage,  float x, float y) {
        File signPdfSrcFile = new File(signPdfSrc);
        PdfReader reader = null;
        ByteArrayOutputStream signPDFData = null;
        PdfStamper stp = null;
        FileInputStream fos = null;
        try {
            BouncyCastleProvider provider = new BouncyCastleProvider();
            Security.addProvider(provider);
            KeyStore ks = KeyStore.getInstance("PKCS12", new BouncyCastleProvider());
            fos = new FileInputStream(keyStorePath);
            // 私钥密码 为Pkcs生成证书 是的私钥密码 
            ks.load(fos, password.toCharArray()); 
            String alias = (String) ks.aliases().nextElement();
            PrivateKey key = (PrivateKey) ks.getKey(alias, password.toCharArray());
            Certificate[] chain = ks.getCertificateChain(alias);
            reader = new PdfReader(signPdfSrc);
            signPDFData = new ByteArrayOutputStream();
            // 临时pdf文件
            File temp = new File(signPdfSrcFile.getParent(), UUID.randomUUID() + ".pdf");
            stp = PdfStamper.createSignature(reader, signPDFData, '\0', temp, true);
             stp.setFullCompression();
            PdfSignatureAppearance sap = stp.getSignatureAppearance();
            sap.setReason("数字签名, 不可改变");//签名原因
            // 使用png格式透明图片
            Image image = Image.getInstance(signImage);
            sap.setImageScale(0);
            sap.setSignatureGraphic(image);
            sap.setRenderingMode(RenderingMode.GRAPHIC);
            // 是对应x轴和y轴坐标 和字段名
            sap.setVisibleSignature(new Rectangle(x, y, x + image.getWidth(), y + image.getHeight() ), 1,
                    "field_name");
           
    		///注入脚本
    		String jsString = ""
    				+ "var sign =  this.getField(\"field_name\");\r\n" + //根据字段 获得
    				"var stat =  sign.signatureValidate();\r\n" +  //验证 
    				"app.alert( \"签名状态: \" + stat);";//参考: js_api_reference.rar 文档 Field -> field methods -> signatureValidate
    		stp.addJavaScript( jsString);
    		
            stp.getWriter().setCompressionLevel(5);
            ExternalDigest digest = new BouncyCastleDigest();
            ExternalSignature signature = new PrivateKeySignature(key, DigestAlgorithms.SHA512, provider.getName());
            MakeSignature.signDetached(sap, digest, signature, chain, null, null, null, 0, CryptoStandard.CADES);
            stp.close();
            reader.close();
            return signPDFData.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (signPDFData != null) {
                try {
                    signPDFData.close();
                } catch (IOException e) {
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                }
            }
        }
        return null;
    }

生成证书

  • maven 依赖
		<!-- PDF 签名 -->
		<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
		<dependency>
			<groupId>com.itextpdf</groupId>
			<artifactId>itextpdf</artifactId>
			<version>5.5.13</version>
		</dependency>
		<!-- 加密相关的-->
		<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-ext-jdk15on -->
		<dependency>
			<groupId>org.bouncycastle</groupId>
			<artifactId>bcprov-ext-jdk15on</artifactId>
			<version>1.60</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
		<dependency>
			<groupId>org.bouncycastle</groupId>
			<artifactId>bcprov-jdk15on</artifactId>
			<version>1.60</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on -->
		<dependency>
			<groupId>org.bouncycastle</groupId>
			<artifactId>bcpkix-jdk15on</artifactId>
			<version>1.60</version>
		</dependency>
 

验证数字签名

TODO https://blog.csdn.net/haoxiaoyong1014/article/details/80871639