使用CERTIFIED_NO_CHANGES_ALLOWED认证PDF时提示文档篡改签名无效
问题根因
你的代码存在两个核心错误,直接导致最高级认证签名被判定为篡改:
- 操作顺序错误:
flattenFields()表单扁平化操作放在了设置认证级别之后,iText 计算认证签名摘要时,无法正确纳入扁平化操作带来的文档结构变更,导致最终文档和签名基准摘要不匹配。 - 全量表单扁平化错误:直接调用无参
flattenFields()会把你预留的signature签名字段也一同扁平化移除,后续签名操作实际上是在缺失目标字段的结构上执行的,普通未认证签名校验逻辑宽松不会报错,但最高级认证签名的强校验会直接判定为篡改。
修复方案
调整操作顺序,先执行除签名字段外的其他表单域扁平化,再配置签名参数执行认证签名,参考代码如下:
PdfReader reader = new PdfReader(SRC); reader.setUnethicalReading(true); PdfSigner pdfSigner = new PdfSigner(reader, new FileOutputStream(DEST), new StampingProperties()); // 第一步:先处理表单扁平化,排除要用于签名的signature字段 PdfAcroForm form = PdfAcroForm.getAcroForm(pdfSigner.getDocument(), false); List<String> fieldToFlatten = new ArrayList<>(form.getFormFields().keySet()); fieldToFlatten.remove("signature"); // 保留签名字段,其他字段全部扁平化 form.flattenFields(fieldToFlatten); // 第二步:再配置签名认证参数 pdfSigner.setFieldName("signature"); pdfSigner.setCertificationLevel(PdfSigner.CERTIFIED_NO_CHANGES_ALLOWED); // 第三步:执行签名 IExternalSignature pks = new PrivateKeySignature(pk, DigestAlgorithms.SHA256, provider.getName()); IExternalDigest digest = new BouncyCastleDigest(); pdfSigner.signDetached(digest, pks, chain, null, null, null, 0, CryptoStandard.CMS);
补充说明
CERTIFIED_NO_CHANGES_ALLOWED 属于最高级别的PDF认证签名,签名完成后不允许对文档做任何修改,包括新增普通签名、修改注释等操作,任何后续变更都会触发签名篡改提示。
内容的提问来源于stack exchange,提问作者user15228699
相关产品推荐
相关产品推荐

