Java PDFBox 1.8.10:填充并签名PDF生成无效签名
我(按程序)在PDF文档中填写表格(AcroPdf),然后在文档上签名。我从doc.pdf开始,使用PDFBox的setFields.java示例创建doc_filled.pdf。然后我签署doc_filled.pdf,创建doc?filled_signed.pdf,使用一些代码,基于签名示例,并在Acrobat Reader中打开pdf。输入的字段数据可见,签名面板告诉我 “此签名中包含的格式或信息有错误(签名字节数组无效)” 到目前为止,我知道:Java PDFBox 1.8.10:填充并签名PDF生成无效签名,java,pdf,pdfbox,sign,pdf-form,Java,Pdf,Pdfbox,Sign,Pdf Form,我(按程序)在PDF文档中填写表格(AcroPdf),然后在文档上签名。我从doc.pdf开始,使用PDFBox的setFields.java示例创建doc_filled.pdf。然后我签署doc_filled.pdf,创建doc?filled_signed.pdf,使用一些代码,基于签名示例,并在Acrobat Reader中打开pdf。输入的字段数据可见,签名面板告诉我 “此签名中包含的格式或信息有错误(签名字节数组无效)” 到目前为止,我知道: 单独应用的签名代码(即直接创建一些doc_
- 单独应用的签名代码(即直接创建一些doc_signed.pdf)会创建有效的签名
- 将“不可见签名”、可见签名和可见签名添加到现有签名字段时存在问题
- 如果我不填写表单,而只打开并保存表单,甚至会出现问题,即:
PDDocument doc = PDDocument.load(new File("doc.pdf")); doc.save(new File("doc_filled.pdf")); doc.close();
- odc.pdf:
- doc_filled.pdf:
- 已填写的文件已签名.pdf:
- 已填写的文件和已签名的文件.pdf:
doc.saveIncremental();
正如我在评论中所写的,一些
setNeedToBeUpdate(true);
但似乎不见了。
关于@mkl的第二条评论,我发现
所以问题:,也包括一些输入的文本没有显示。我第一次试了一下,申请了
setBoolean(COSName.getPDFName("NeedAppearances"), true);
添加到字段和表单的字典,该字典随后显示字段上下文,但签名不会添加到最后。不过,我还需要进一步研究
更新:
故事在这里继续:OP最初问题的原因,即在用PDFBox加载其PDF(用于填写表单)并保存后,无法使用PDFBox签名代码成功签名此新PDF,简言之,已详细解释如下:
- 定期保存文档时,PDFBox使用交叉引用表进行保存
- 如果要定期保存的文档是从带有交叉引用流的PDF加载的,则交叉引用流字典的所有条目都保存在拖车字典中
- 在应用签名的过程中保存文档时,PDFBox创建增量更新;由于此类增量更新要求更新使用与原始版本相同的交叉引用,因此PDFBox在本例中尝试使用相同的技术
- 为了识别最初使用的技术,PDFBox在其文档表示中查看已加载拖车或交叉引用流字典的字典的类型条目:如果有类型条目的值为XRef(这是为交叉引用流指定的),假定为流,否则为表
doc.PDF
具有交叉引用流的情况下:
- 加载并填写表单后,文档会定期保存,即使用交叉引用表,但所有以前的交叉引用流条目(其中包括类型)都会复制到尾部。(
)doc\u filled.pdf
- 加载此保存的PDF以及用于签名的交叉引用表后,将使用增量更新再次保存此PDF。PDFBox假定(由于类型尾部条目),现有文件具有交叉引用流,因此在增量更新结束时也使用交叉引用流。(
)doc\u filled\u signed.pdf
- 因此,最终,填写后签名的PDF有两个版本,内部版本有一个交叉引用表,外部版本有一个交叉引用流
- 由于这是无效的,Adobe Reader在加载PDF时会在其内部文档表示中修复此问题。修复会更改文档字节。因此,Adobe Reader眼中的签名被打破了
- 大多数其他签名验证器不会尝试这样的修复,而是按原样检查文档的签名。他们成功地验证了签名
- 答:在加载用于填写表单的PDF后,在定期保存之前,从尾部删除Type条目。如果对该文件应用签名,PDFBox将采用交叉引用表(因为不存在误导性的类型条目)。因此,签名增量更新将有效
- B:在单独运行或与签名相同的运行中,也可以使用增量更新保存表单填写更改。这也会导致有效的增量更新
在手头的案例中,OP尝试了后一种选择(
doc\u filled\u and\u signed.pdf
):
目前,文本框的内容仅在选中文本框时可见(使用Acrobat reader和Preview的行为相同)。我标记PDField、其所有父项、AcroForm、目录以及其中的页面