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

iText 8.0.3初始签名失效求助:添加/升级PAdES签名时签名无效

解决iText 8.0.3追加模式下破坏PAdES B-T签名的问题

问题场景

使用iText 8.0.3将PAdES B-T签名升级为B-LT,或执行添加新签名操作时,初始签名会触发“签名应用后文档已被更改或损坏”的无效提示。甚至仅用如下简单的追加模式读写代码,也会导致该问题(仅特定PDF文件出现,其他PDF正常):

String srcFileName = "./BT.pdf";
String outFileName = "./B-LT01.pdf";
PdfDocument document = new PdfDocument(new PdfReader(srcFileName), new PdfWriter(outFileName), new StampingProperties().useAppendMode());
document.close();

升级签名的完整业务代码如下:

byte[] addLTV(byte[] in)
            throws IOException, GeneralSecurityException, java.io.IOException {
        IOcspClient ocsp = new OcspClientBouncyCastle(new com.itextpdf.signatures.OCSPVerifier(null, null));
        ICrlClient crl = new CrlClientOnline();
        PdfReader reader = new PdfReader(new ByteArrayInputStream(in));
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        PdfWriter writer = new PdfWriter(out);
        PdfDocument pdfDoc = new PdfDocument(reader, writer, new StampingProperties().useAppendMode());
        LtvVerification v = new LtvVerification(pdfDoc);
        SignatureUtil signatureUtil = new SignatureUtil(pdfDoc);
        List<String> names   = signatureUtil.getSignatureNames();
        String sigName = names.get(names.size() - 1);
        PdfPKCS7 pkcs7 = signatureUtil.readSignatureData(sigName);
        if (pkcs7.isTsp()) {
            v.addVerification(sigName, ocsp, crl, LtvVerification.CertificateOption.WHOLE_CHAIN,
                              LtvVerification.Level.OCSP_CRL, LtvVerification.CertificateInclusion.NO);
        } else {
            for (String name : names) {
                v.addVerification(name, ocsp, crl, LtvVerification.CertificateOption.WHOLE_CHAIN,
                                  LtvVerification.Level.OCSP_CRL, LtvVerification.CertificateInclusion.YES);
            }
        }
        v.merge();
        pdfDoc.close();
        return out.toByteArray();
    }

问题原因

该问题源于目标PDF存在非标准结构(如异常的交叉引用表、对象流或自定义字典字段),iText默认的宽松解析模式会自动修复这些结构,导致原签名覆盖的字节内容发生变更,触发签名哈希验证失败。

解决方法

通过配置PdfReader启用严格解析模式,强制iText保留原文档的原始结构,仅在增量更新中添加新内容,避免修改原签名覆盖的字节:

1. 修改简单测试代码

String srcFileName = "./BT.pdf";
String outFileName = "./B-LT01.pdf";
// 配置Reader严格解析,禁用自动修复
PdfReaderProperties readerProps = new PdfReaderProperties().setStrictParsing(true);
PdfReader reader = new PdfReader(srcFileName, readerProps);
// 保持追加模式
StampingProperties stampProps = new StampingProperties().useAppendMode();
PdfDocument document = new PdfDocument(reader, new PdfWriter(outFileName), stampProps);
document.close();

2. 修改添加LTV的完整代码

byte[] addLTV(byte[] in) throws IOException, GeneralSecurityException {
    IOcspClient ocsp = new OcspClientBouncyCastle(new com.itextpdf.signatures.OCSPVerifier(null, null));
    ICrlClient crl = new CrlClientOnline();
    // 启用严格解析模式,避免iText自动修改原文档结构
    PdfReaderProperties readerProps = new PdfReaderProperties().setStrictParsing(true);
    PdfReader reader = new PdfReader(new ByteArrayInputStream(in), readerProps);
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    PdfWriter writer = new PdfWriter(out);
    // 使用追加模式,仅添加增量内容
    StampingProperties stampProps = new StampingProperties().useAppendMode();
    PdfDocument pdfDoc = new PdfDocument(reader, writer, stampProps);
    LtvVerification v = new LtvVerification(pdfDoc);
    SignatureUtil signatureUtil = new SignatureUtil(pdfDoc);
    List<String> names = signatureUtil.getSignatureNames();
    String sigName = names.get(names.size() - 1);
    PdfPKCS7 pkcs7 = signatureUtil.readSignatureData(sigName);
    if (pkcs7.isTsp()) {
        v.addVerification(sigName, ocsp, crl, LtvVerification.CertificateOption.WHOLE_CHAIN,
                          LtvVerification.Level.OCSP_CRL, LtvVerification.CertificateInclusion.NO);
    } else {
        for (String name : names) {
            v.addVerification(name, ocsp, crl, LtvVerification.CertificateOption.WHOLE_CHAIN,
                              LtvVerification.Level.OCSP_CRL, LtvVerification.CertificateInclusion.YES);
        }
    }
    v.merge();
    pdfDoc.close();
    return out.toByteArray();
}

额外排查建议

如果严格解析模式仍未解决问题,可以尝试:

  • 使用PDF结构检查工具(如Adobe Preflight)确认目标PDF是否存在交叉引用、对象流等结构异常。
  • 检查原签名字典是否包含自定义扩展字段,必要时通过PdfDictionary手动保留这些字段,避免iText误修改。

内容的提问来源于stack exchange,提问作者Vinh Dương

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 11:50:13