我正在尝试使用Itext 5.4和BouncyCastle 1.49验证PDF签名(通过Adobe Reader X使用我的数字证书手动签名)。
但验证结果总是出乎意料,这是我的Java代码:
**Security.addProvider(new BouncyCastleProvider());
PdfReader reader = new PdfReader("E:/signTest.pdf");
AcroFields acro = reader.getAcroFields();
PdfPKCS7 pkcs7 = acro.verifySignature("signatureField");
System.out.println("Integrity check OK? " + pkcs7.verify());**
控制台显示:完整性检查确定?真
但请记住,我已修改了“signTest.pdf”文档。预期结果应为:完整性检查确定?假
有没有人必须解决这个问题?
我将不胜感激。
答案 0 :(得分:2)
“完整性检查确定”(作为pkcs7.verify()
的结果)仅告诉您最初签名的修订版本,PDF的原始签名字节范围尚未更改。如果您在追加模式中应用了更改,即使用增量更新,则不会触及最初签名的字节范围。
如果您想检查是否已将更改作为增量更新,请同时检查acro.signatureCoversWholeDocument("signatureField")
:
/**
* Checks is the signature covers the entire document or just part of it.
*
* @param name the signature field name
* @return <CODE>true</CODE> if the signature covers the entire document,
* <CODE>false</CODE> otherwise
*/
public boolean signatureCoversWholeDocument(String name)
如果您确实更改了原始签名的字节范围,请在修改之前和之后提供PDF。
关于您的意见......
我按照你的建议在检查acro.signatureCoversWholeDocument(“signatureField”)时得到“false”返回。那么它是否意味着“未触及最初签名的字节范围”?
您必须考虑这些结果值的组合:
pkcs7.verify()
表示指示的签名本身是否正常,并正确签署相关签名词典中指示的字节范围。
acro.signatureCoversWholeDocument("signatureField")
表示由指示签名签名的字节范围是否覆盖整个文档(显然签名本身除外)。
仅当两个结果均为true
时,才会对签名进行肯定验证,以便在当前状态下对文档进行签名。
如果前一个是true
而后一个是false
,则会对签名进行肯定验证以签署文档的前一个状态,该状态可以使用acro.extractRevision("signatureField")
从文档中提取
与例如Adobe Reader,iText还不能检查内容的变化类型。因此,它无法告诉您更改是允许还是不允许。
如果前一个是假的,那么签名最初确实签名的状态(如果有这样的状态)就不能被提取了。
然后我如何应用签名来覆盖整个文档?
签署PDF时,签名涵盖整个文档。例如。示例文件signTest_after.pdf
中的签名确实涵盖了整个文件。之后填写字段会在您的示例文件signTest_modified.pdf
中添加一个新的修订版本,但您的签名不在其中。
对于某些背景,您可能需要阅读this answer以了解PDF签名的工作原理,this answer了解PDF中的多个修订信息,以及{em>上的this answer允许和禁止更改签名文档。
一般情况下,对于使用iText和集成PDF签名,您可能需要学习Digital Signatures for PDF documents,Bruno Lowagie(iText软件)的白皮书,尤其是第5章签署文档的验证。