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

使用iText-2.1.7为PDF添加签名后提示文档被篡改的问题排查

错误含义解释

“Document has been altered or corrupted since it was signed” 意味着Adobe Acrobat在验证PDF签名时,发现当前文档的实际内容哈希值与签名嵌入的哈希值不匹配,判定文档签名后被篡改或签名过程本身存在错误导致验证失败。

问题定位与修复方案

你的代码核心问题在于PKCS7结构生成时传递了错误的哈希值,导致签名验证时哈希不匹配。以下是具体修复步骤:

1. 修正getEncodedPKCS7的参数传递

原代码中调用sgn.getEncodedPKCS7(signedHash, appearance.getSignDate())时,错误地将签名后的signedHash作为第一个参数传入,而该方法需要的是原始文档内容的哈希值(即appeareanceHash)。

将该行代码修改为:

val encodedPKCS7 = sgn.getEncodedPKCS7(appeareanceHash, appearance.getSignDate())

2. 验证其他潜在问题(可选)

  • 确认KalkanProvider正确注册且支持SHA256和SHA256withRSA算法,避免因算法支持问题导致签名生成错误。
  • 检查estimatedSize设置是否足够:8192字节对于大多数PKCS7签名已经足够,若签名过大可适当调整(如16384),确保填充后的签名长度不超过预留的空间。
  • 确认CryptUtils中的证书链、私钥、证书均有效且匹配,避免因密钥/证书问题导致签名无效。
修复后的完整代码
def postProcessPdf(pdf: Array[Byte], os: OutputStream): Unit = {
 val reader = new PdfReader(pdf)
 Security.addProvider(new KalkanProvider)
 val stamper = PdfStamper.createSignature(reader, os, '\u0000')
 val appearance = stamper.getSignatureAppearance
 val signDate = Calendar.getInstance
 val pdfSignature = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED)
 pdfSignature.setDate(new PdfDate(signDate))
 pdfSignature.setCert(CryptUtils.cert.getEncoded)
 appearance.setCryptoDictionary(pdfSignature)
 appearance.setCrypto(null, CryptUtils.chain, null, PdfSignatureAppearance.WINCER_SIGNED)
 appearance.setCertificationLevel(PdfSignatureAppearance.CERTIFIED_NO_CHANGES_ALLOWED)
 val estimatedSize = 8192
 val exc = new HashMap[PdfName, Int]()
 exc.put(PdfName.CONTENTS, estimatedSize * 2 + 2)
 appearance.preClose(exc)
 val data = appearance.getRangeStream()
 val sgn = new PdfPKCS7(null, CryptUtils.chain, null, "SHA256", null, false)
 val digest = MessageDigest.getInstance("SHA256","KALKAN")
 val dataBytes = IOUtils.toByteArray(data)
 digest.update(dataBytes)
 val appeareanceHash = digest.digest()
 val hashToSign = sgn.getAuthenticatedAttributeBytes(appeareanceHash, appearance.getSignDate(), null)
 val signature = Signature.getInstance("SHA256withRSA","KALKAN")
 signature.initSign(CryptUtils.privateKey)
 signature.update(hashToSign)
 val signedHash = signature.sign()
 sgn.setExternalDigest(signedHash,null,"RSA")
 // 修正此处的参数,传入文档哈希appeareanceHash而非签名后的signedHash
 val encodedPKCS7 = sgn.getEncodedPKCS7(appeareanceHash, appearance.getSignDate())
 val paddedSig = new Array[Byte](estimatedSize)
 System.arraycopy(encodedPKCS7, 0, paddedSig, 0, encodedPKCS7.length)
 val dic = new PdfDictionary()
 dic.put(PdfName.CONTENTS, new PdfString(paddedSig).setHexWriting(true))
 appearance.close(dic)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 09:59:54