You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iText PDF 7签名后Adobe提示文档被篡改问题求助

iText PDF 7 签名后Adobe提示“文档已被篡改”的排查与解决

核心排查方向

1. 签名后文档是否被二次修改

  • 签名流程结束后,禁止对输出PDF做任何额外操作(如添加水印、修改元数据、调整页面结构),确保签名后的文件直接输出,无二次编辑。
  • 检查代码中PdfDocument、PdfSigner及输出流的关闭逻辑,确保所有流已正确刷新、关闭,避免文件写入不完整导致的损坏。

2. 签名模式与范围配置错误

  • 确认PdfSigner初始化参数的正确性:第三个布尔参数设为false(禁止签名后修改文档),单签名场景下不要设为true(允许附加签名后修改):
    PdfSigner signer = new PdfSigner(reader, os, false);
    
  • 检查签名认证级别设置,若设置为CERTIFIED_NO_CHANGES_ALLOWED,需确保签名后无任何隐式修改;普通签名场景建议使用NOT_CERTIFIED:
    signer.setCertificationLevel(PdfSigner.NOT_CERTIFIED);
    
  • 验证哈希计算范围,确保signDetached方法正确覆盖整个文档内容,未遗漏关键数据块。

3. 证书链与签名算法兼容性

  • 确保使用的证书包含完整链(从用户端证书到根CA),Adobe需要完整链才能验证签名合法性,链不完整会导致误判。
  • 使用Adobe兼容的签名算法,优先选择SHA-256及以上的哈希算法,避免过时的SHA-1:
    signer.setDigestAlgorithm(DigestAlgorithms.SHA256);
    signer.setSignatureAlgorithm(PdfSigner.CMS_SHA256_RSA);
    

4. 时间戳服务配置问题(若使用)

  • 检查时间戳服务的URL、请求参数是否正确,确保返回的时间戳令牌完整嵌入签名中,无篡改或截断。
  • 验证时间戳客户端配置,确保使用匹配的哈希算法:
    signer.setTimestampClient(new TSAClientBouncyCastle(tsaUrl, null, null, 4096, "SHA-256"));
    

5. 多版代码迭代差异对比

重点对比各版本代码的以下变更点:

  • PdfSigner初始化参数的变化
  • 签名算法、摘要算法的调整
  • 证书加载逻辑(是否从正确密钥库加载、是否包含完整链)
  • 输出流的处理方式
  • 签名后是否新增了文档操作逻辑

标准基础签名代码示例

try (PdfReader reader = new PdfReader("input.pdf");
     FileOutputStream os = new FileOutputStream("signed_output.pdf")) {
    // 初始化签名器,禁止签名后修改
    PdfSigner signer = new PdfSigner(reader, os, false);
    
    // 配置签名外观
    SignatureAppearance appearance = signer.getSignatureAppearance();
    appearance.setReason("Official document signature")
              .setLocation("HQ")
              .setContactInfo("support@example.com");
    
    // 加载PKCS12密钥库与证书链
    KeyStore ks = KeyStore.getInstance("PKCS12");
    ks.load(new FileInputStream("keystore.p12"), "password".toCharArray());
    String alias = ks.aliases().nextElement();
    PrivateKey privateKey = (PrivateKey) ks.getKey(alias, "password".toCharArray());
    Certificate[] certChain = ks.getCertificateChain(alias);
    
    // 设置签名算法
    signer.setDigestAlgorithm(DigestAlgorithms.SHA256);
    signer.setSignatureAlgorithm(PdfSigner.CMS_SHA256_RSA);
    signer.setCertificationLevel(PdfSigner.NOT_CERTIFIED);
    
    // 执行分离式签名
    signer.signDetached(new BouncyCastleDigest(), certChain, null, null, null, 0, PdfSigner.CryptoStandard.CMS);
} catch (Exception e) {
    e.printStackTrace();
}

内容的提问来源于stack exchange,提问作者Abhinav Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 15:23:08