使用外部摘要签名PDF时出现BER编码及文档篡改提示问题求助
解决PDF智能卡签名后的BER编码与文档篡改提示问题
看起来你遇到的是典型的跨PDF阅读器签名验证不一致问题——Adobe揪出BER编码错误,PDF Studio能识别证书但认为文档被改。结合你的代码片段和症状,我整理了几个核心排查点和修复方案:
1. 先搞定BER编码问题(Adobe报错的核心)
Adobe提示的"BER编码问题"几乎100%指向签名值的格式错误:
- 智能卡返回的签名值必须是完整的PKCS#7/CMS格式BER编码字节流,不能是裸签名(比如单纯的RSA签名字节)。很多智能卡API会返回CMS容器,如果你手动提取了裸签名,就会触发这个错误。
- 绝对不要对智能卡返回的签名字节做额外转码操作(比如转成UTF-8字符串再转回字节),这会破坏BER编码的结构。直接用原始字节数组插入PDF:
// 假设signatureBytes是智能卡返回的BER编码CMS签名 ExternalSignatureContainer sigContainer = new ExternalSignatureContainer() { @Override public byte[] sign(InputStream is) throws GeneralSecurityException { // 这里直接返回智能卡签好的CMS字节,不要重新计算 return signatureBytes; } @Override public void modifySigningDictionary(PdfDictionary signDic) { signDic.put(PdfName.FILTER, PdfName.ADOBE_PPKLITE); signDic.put(PdfName.SUBFILTER, PdfName.ADBE_PKCS7_DETACHED); } }; // 绑定到签名外观 PdfSignatureAppearance appearance = stamper.getSignatureAppearance(); stamper.signExternalContainer(appearance, sigContainer, 8192);
2. 强制启用PDF追加模式(解决"文档已被修改")
你设置了pdfReader.setAppendable(true);,但这还不够,必须确保PdfStamper以追加模式创建——否则签名时会覆盖原始文档内容,触发阅读器的篡改检测:
// 最后一个参数true是关键:启用追加模式,只在文档末尾添加签名层 PdfStamper stamper = PdfStamper.createSignature( pdfReader, new FileOutputStream("signed_output.pdf"), '\0', null, true );
追加模式下,原始PDF内容完全不变,签名作为新的增量层添加,阅读器就不会认为文档被修改了。
3. 检查签名摘要的计算范围
PDF Studio能显示证书但提示篡改,大概率是签名摘要和实际PDF的ByteRange不匹配:
- 不要自己计算整个PDF的哈希,必须用iText提供的
ExternalSignatureContainer的sign(InputStream is)方法中传入的流来计算摘要——这个流对应的是PDF签名域指定的ByteRange范围,是符合PDF规范的待签内容。 - 智能卡签名时,一定要传入这个ByteRange对应的哈希值,而不是整个文档的哈希。如果传错了,签名容器的摘要和实际文档内容对不上,就会触发篡改提示。
4. 签名后绝对不要修改文档
如果你在调用stamper.close()之后,又对输出的PDF做了任何修改(比如添加注释、调整页面),哪怕是微小的变更,都会导致阅读器检测到内容变化,提示"文档已被修改"。确保签名是最后一步操作。
内容的提问来源于stack exchange,提问作者Drifter
相关产品推荐
相关产品推荐

