Apache PDFBox外部签名异常:签名后PDF提示已篡改求助
PDF签名后提示篡改的排查方案
哈希值大小验证
你提供的哈希值LXl/LHCaxrf7lYlN8d8m7gDNp9DRqY+azvxCS/mB3uY=是Base64编码格式,解码后为32字节(256位),这是SHA-256哈希算法的标准输出长度,大小完全正常,哈希本身的尺寸不是问题所在。
关键缺失步骤排查
结合Apache PDFBox 3.0.0的签名流程,重点检查以下环节:
1. 待哈希内容范围是否正确
PDF签名的核心是对签名占位符插入后的待签文档字节流计算哈希,而非原始PDF文件。需确认代码中是否通过ExternalSigningSupport.getContent()获取正确的数据流:
- 错误做法:直接读取原始PDF文件的字节数组计算哈希
- 正确做法:调用
ExternalSigningSupport.getContent()获取PDFBox准备好的待签流,读取该流计算哈希
2. 签名算法与签名字典配置匹配
确保外部签名算法与PDF签名字典的参数完全一致:
- 若使用SHA256withRSA签名,需设置:
- 签名字典
/Filter为/Adobe.PPKLite /SubFilter为/adbe.pkcs7.detached(分离式签名)/DigestAlgorithm为/SHA256
- 签名字典
- 检查
CreateSignature中配置签名字典的代码,是否遗漏或错误设置了上述参数
3. 签名值的编码与写入逻辑
外部服务返回的签名通常是DER编码的二进制数据,需确保传递给PDFBox的是原始二进制签名:
- 避免将Base64编码的签名直接写入PDF,需先解码为字节数组
- 检查
ExternalSignature实现,是否正确将外部服务返回的签名转换为字节数组后传递
4. 文档增量更新是否正确
PDF签名必须通过增量更新保存,不能覆盖原始文档:
- 确认代码中使用
saveIncremental()方法保存签名后的文档,而非普通的save()方法 - 增量更新会保留原始文档内容,仅追加签名数据,这是保证签名有效性的关键
5. 外部签名流程的正确性
模拟外部签名时,需严格遵循“哈希→签名”的流程:
- 先对待签字节流计算哈希,再用私钥对哈希值进行签名
- 错误示例:直接对待签字节流签名(而非哈希)
- 正确实现参考:
@Override public byte[] sign(byte[] content) throws IOException { try { MessageDigest digest = MessageDigest.getInstance(getHashAlgorithm()); byte[] hash = digest.digest(content); Signature signature = Signature.getInstance(getSignatureAlgorithm()); signature.initSign(privateKey); signature.update(hash); return signature.sign(); } catch (Exception e) { throw new IOException(e); } }
内容的提问来源于stack exchange,提问作者jan_s
相关产品推荐
相关产品推荐

