基于iText7 Java的PDF云签名:如何启用LTV长期验证?
在iText7中为PDF数字签名启用LTV(长期验证)
要让PDF签名支持LTV,核心是把签名验证所需的长期有效性数据嵌入PDF的Document Security Store(DSS)中,这些数据包括OCSP响应、CRL证书吊销列表,以及证书链中必要的中间证书。以下是基于iText7的具体实现步骤:
1. 准备LTV所需的验证数据
首先要获取签名相关的所有验证数据:
- 从云签名服务或CA官方接口,获取签名证书的OCSP响应(优先选择,因为体积小、时效性强)
- 获取证书链中所有中间证书的OCSP响应或CRL
- 如果使用私有CA,还需要根证书的CRL(公信任锚的根证书可省略)
注意:确保这些数据的有效期覆盖签名时间,且获取时间尽可能接近签名时间,避免验证失效。
2. 为已签名PDF添加LTV数据
如果已经完成签名,可事后通过LtvVerification类嵌入LTV数据:
// 打开已签名的PDF文件 PdfReader reader = new PdfReader("signed.pdf"); PdfDocument pdfDoc = new PdfDocument(reader, new PdfWriter("signed_with_ltv.pdf")); // 初始化LTV处理器 LtvVerification ltv = new LtvVerification(pdfDoc); // 目标签名字段(替换为你的签名字段名) String signatureName = "MyDigitalSignature"; PdfSignatureField sigField = pdfDoc.getAcroForm().getSignatureField(signatureName); // 获取签名的PKCS7对象(用于关联证书链) PdfPKCS7 pkcs7 = sigField.getSignature().getPdfPKCS7(); // 假设已获取OCSP响应和CRL字节数组 byte[] ocspResp = ...; // 从云签/CA获取的OCSP响应 byte[] crlData = ...; // 从CA获取的CRL数据 // 添加OCSP响应到LTV(覆盖整个证书链) ltv.addVerification( signatureName, ocspResp, null, LtvVerification.CertificateOption.WHOLE_CHAIN, LtvVerification.Level.OCSP_CRL, LtvVerification.CertificateInclusion.NO ); // 可选:添加CRL作为补充验证数据 ltv.addVerification( signatureName, null, crlData, LtvVerification.CertificateOption.WHOLE_CHAIN, LtvVerification.Level.OCSP_CRL, LtvVerification.CertificateInclusion.NO ); // 将LTV数据写入PDF的DSS ltv.merge(); // 关闭资源 pdfDoc.close(); reader.close();
3. 签名时直接启用LTV
如果要在签名流程中直接添加LTV,可在PdfSigner配置阶段集成:
PdfReader reader = new PdfReader("original.pdf"); PdfSigner signer = new PdfSigner(reader, new FileOutputStream("signed_with_ltv.pdf"), new StampingProperties()); // 配置签名字段和基本参数 signer.setFieldName("MyDigitalSignature"); signer.setCertificationLevel(PdfSigner.CERTIFIED_NO_CHANGES_ALLOWED); // 初始化LTV处理器 LtvVerification ltv = new LtvVerification(signer.getDocument()); // 提前添加OCSP/CRL数据(同步骤2的配置) ltv.addVerification("MyDigitalSignature", ocspResp, null, ...); // 调用云签名服务完成签名(自定义IExternalSignature实现) IExternalSignature cloudSignature = new CloudSignServiceSignature(); // 你的云签实现 signer.signDetached( cloudSignature, pkcs7.getCertificates(), null, null, null, 0, PdfSigner.CryptoStandard.CMS ); // 合并LTV数据到PDF ltv.merge(); // 关闭资源 signer.close(); reader.close();
关键注意事项
- 数据有效性:OCSP/CRL必须在签名时间点处于有效状态,且有效期足够长
- 证书链覆盖:要确保所有非信任锚的证书(中间证书、签名证书)都有对应的验证数据
- 时间戳:如果签名包含可信时间戳,LTV验证会依赖时间戳的时间来检查证书状态,需确保时间戳服务可靠
- 云签对接:优先从云签名服务获取配套的OCSP/CRL数据,避免自己获取时出现时间或数据不匹配的问题
内容的提问来源于stack exchange,提问作者Wesley Alves
相关产品推荐
相关产品推荐

