我有一个pdf,我正在使用itext 5.4.4处理它(我已经尝试使用相同的5.5.5并且我得到了相同的错误),在处理文件时我尝试验证所有签名是否覆盖了全部记录并使用以下代码进行验证:
boolean resp = false;
InputStream inputStream = null;
PdfReaderversionReader = null;
PdfReader originalReader = null;
String signatureName = "Signature1";
... loading orginal pdf and signature names ...
try {
inputStream = reader.getAcroFields().extractRevision(signatureName);
versionReader = new PdfReader(inputStream);
} catch (IOException e) {
log.warn("unable to get revision for signature FIELD ", e);
}
//After that i have tried to use the actual one, but it still fails...
if (versionReader == null) {
versionReader = originalReader;
}
resp = versionReader.getAcroFields().signatureCoversWholeDocument(signatureName);
我的第一个麻烦发生在创建versionReader时解析字节失败。
使用rups打开pdf lokks就像有两个带有相同字段名称的签名字段标签。
- 第一个包含字节范围/ ByteRange:[0,160,9634,121571]
- 和第二个/ ByteRange:[0,131726,1131728,3904]
iText只是恢复了第一个,然后失败了。
当我调试代码时,我发现方法
com.itextpdf.text.pdf.AcroFields.fill()
in com.itextpdf.text.pdf.AcroFields line 241 this code
if (fields.containsKey(name))
continue;
所以它显然丢弃了这些信息,我不知道但iText有可能有错误吗?或者我在阅读pdf文件时做错了什么? 重点是Adobe Acrobat阅读器验证所有签名没有问题...
这是问题所在的PDF。
所有帮助都很受欢迎,谢谢你。
答案 0 :(得分:2)
由于OP已经发现自己,他的PDF包含两个具有相同名称的签名表单字段:
这两个字段都有部分名称Signature1
且没有父级,因此这也是两个字段的完全限定名称。
ISO规范ISO 32000-1在以下字段中说明:
特别是,具有相同完全限定字段名称的字段词典应具有相同的字段类型( FT ),值( V )和默认值( DV 强>)。
(第12.7.3.2节字段名称)
对于OP的PDF,这些字段的相应值明显不同。因此,PDF表单字段结构无效。
虽然在这种情况下显然PDF库可能会忽略任何已经找到字段名称的额外字段,但iText的搜索顺序是不幸的:
没有父母的PDF表单字段应该从PDF的 AcroForm 字典字段数组中引用。旧PDF表单通常只有页面 Annots 数组引用的表单字段,而不是 AcroForm / Fields 。为了支持这样的形式,iText(就像Adobe Reader一样)也考虑这些领域。
如果手头有PDF, AcroForm 字典字段数组中只有一个字段:
此处引用的签名字段是iText忽略的字段。反之亦然,iText应该优先选择 AcroForm 字典字段数组引用的字段,而不是仅从页面 Annots 数组中引用的字段。< / p>
评论中的OP说
如果我通过调试强制获取第二个字段,问题是摘要不正确,
当Adobe Reader验证其他签名(至少它没有抱怨其哈希值,仅仅是缺少对其签名者的信任)时,这意味着iText或Adobe Reader在哈希验证中存在错误。因此,我编写了一个小测试,直接或间接地从 AcroForm 字典 Fields 数组中引用签名。您可以找到来源here。您文件的结果:
* A named entry: Signature1
FQP: Signature1
Type: /Sig
Value: present
Signed range: 0 131726 1131728 3904 (covers whole file)
Validity: true
因此,较新的签名(唯一一个在 AcroForm / Fields 中,被iText AcroFields
忽略)覆盖整个文件并验证确定。所以你的摘要不匹配似乎是一个调试工件。
答案 1 :(得分:0)
正如Micheal所说,如果您在第268行更改AcroFields以发表评论
// if (this.fields.containsKey(name)) {
// continue;
// }
然后,PDF完全验证,因为Adobe Acrobat Reader说,不好的一点是你必须覆盖
com.itextpdf.text.pdf.AcroFields
或者通过低级别的iText代码。