简介
我有一个问题,数字签署PDF文件,已被标记为PDF/A-3A兼容。使用PDFBox (最新版本,2.0.24),我最终得到了Acrobat中的无效签名,而使用iText7 (最新版本),我得到了一个有效的签名。目标是获得符合PAdES LTV的签名。
概述
我的流程如下(包括PDFBox和iText7):
对于PDFBox,用于签名的代码是这里,OCSP/CRL嵌入的代码是这里。对于iText7,用于签名和OCSP/CRL嵌入的代码是这里。
问题所在
现在,这可以用于大多数PDF文件,包括多签名文档。问题在于一个特殊的PDF格式,它是作为PDF/A遵从性创建的,级别3A。
使用PDFBox时,如果我只是在Acrobet中嵌入签名并打开文档,则签名是有效的。如果我还嵌入了OCSP/CRL内容,则签名不再有效。Adobe Acrobat抱怨:
签名无效:文档自签名以来已被更改或损坏。
我还注意到,仅仅通过这样做:
document.load(inputStream);
document.save(outputStream);我打破了签名。根据我的测试,实际的嵌入并不是问题的真正原因,而只是在嵌入签名并将其保存回磁盘后重新打开PDF的事实。
使用相同的进程(密钥、证书等)通过iText7,我最终在Acrobat中获得了一个有效的LTV签名。
样本PDFs
示例文档为这里。原件包含未签名的文档,然后有两个示例,一个用于PDFBox (在Acrobat中无效),另一个用于iText7 (在Acrobat中有效)。
到目前为止,我的研究表明,PDFBox在签名嵌入后加载PDF时,不知怎么地破坏了元素的顺序。它暗示本期需要加载和保存文档,不过对于所有其他PDF,我做的都是相同的过程,Acrobat不抱怨签名。
我还尝试使用PDFBox 2.1.0-快照和3.0.0-快照,希望这个问题与PDF中元素的排序有关,并且得到了修复。尽管如此,我还是得到了同样的结果。
稍后编辑1
请看后面的编辑2下面,这以后编辑1这里不是一个好主意!
根据下面@mkl所接受的答案,问题是原始PDF文件,其中包含交叉参考表分成几个子部分,而不是一个。这似乎是由生成PDF的服务使用的库(asosPDFfor.NET,Version21.3或更高版本)造成的。
似乎适用于我当前代码的一个解决方法是:
PDDocumentInformation info = pdDocument.getDocumentInformation();
if (info != null && StringUtils.containsIgnoreCase(info.getProducer(), "Aspose")) {
try {
pdDocument.save(inMemoryStream);
pdDocument.close();
pdDocument = PDDocument.load(inMemoryStream.toByteArray());
inMemoryStream.reset();
} catch (Exception e) {基本上,如果我检测到文档的生产者是Aspose,我会将文档保存在内存中(通过PDFBox‘pdDocument.save())并将其加载回去。这确保了交叉参考表在内存中的正确写入,并且从那里签名和OCSP+CRL嵌入按预期工作,在Acrobat中产生一个有效的签名。
稍后编辑2
谢谢你@mkl和TilmanHausherr,你说得对。假设使用某个库生成的所有文档都必须自动标准化,这不是一个好主意,因为现有签名将无效。最后,更好的想法是保持代码的原样,并期望得到一个正确构造的PDF。修复所创建的问题。
发布于 2021-08-16 16:46:32
这个问题是由原始PDF中的一个错误引起的。您的PDFBox代码以附加模式(即增量更新)进行签名,因此签名版本中也存在错误。您的iText代码不以附加模式登录,而是重写整个PDF;这样做不会产生与原始PDF生成程序相同的错误,因此错误不再出现在签名版本中。Acrobat在使用更新验证签名时对此类问题非常敏感。
误差
PDF初始修订本的交叉参考表不得分割为单独的分节,但如果您的原始PDF已被拆分:
0 75
0000000000 65535 f
0000000018 00000 n
...
0000313374 00000 n
0000313397 00000 n
76 20
0000313419 00000 n
0000313443 00000 n
...
0000846048 00000 n
0000846175 00000 n类似的情况已经在这个答案、这个答案、这个答案和其他地方讨论过;您还可以在这些答案中找到一些规范参考。
通常情况下,当遇到PDF中的小问题时,Acrobat通常是相当松懈的。
通常情况下,即除外,除了在经过签名的之后使用集成签名和增量更新对文档进行验证时,在这种情况下,Acrobat通常会认为此类问题可疑,并且无法验证签名,即使它在验证相同的PDF时没有在签名后进行增量更新时也不会抱怨。
在这种危急情况下,您的最后文档包含了经过签名的修订后的增量更新,这是一个包含验证相关信息的更新。
是谁造成了这个错误?
根据你原来的信息字典,它是由"Aspose.PDF for .NET 21.3.0“生成的。已知,早期版本的Aspose.PDF会创建这样错误的交叉引用表(请参阅上面提到的第一个答案的“损坏PDF处理器”一节)。显然,Aspose还没有解决这个问题。
https://stackoverflow.com/questions/68801701
复制相似问题