我正在尝试学习使用Apache的pdfBox处理经过数字签名的文档。在测试期间,我创建了一个完全空白的pdf文档。
然后,我使用带有证书的签名功能通过Adobe Reader对该文档进行了签名。
我尝试使用pdfBox打开,保存和关闭签名文件,没有进行任何修改。但是,一旦我在Adobe中打开文件,这些文件将不再有效。
Adobe告诉我:“此签名中包含的格式或信息有错误(支持信息:SigDict / Contents非法数据)”
由于我尚未修改文件的内容,因此从直观上讲应该没有任何问题,并且签名应该仍然有效,但是事实并非如此,我也不知道解决方案是什么(谷歌搜索没有结果)。
我如何创建文档:
@Test
public void createEmptyPDF() throws IOException {
String path = "path to file";
PDDocument document = new PDDocument();
PDPage page = new PDPage();
document.addPage(page);
document.save(path);
document.close();
}
然后,我用Adobe对其进行签名,并通过它进行传递:
@Test
public void copySignedDocument() throws IOException {
String path = "path to file";
File file = new File(path);
PDDocument document = PDDocument.load(file);
document.save(file);
document.close();
//just opening and saving the file invalidates the signatures
}
我真不知道为什么这行不通。任何帮助将是巨大的!
编辑:
因此,我进行了一些深入研究,看来更新现有签名文档(添加注释或填写表格)尚未在PDFBox
2.0.1中实现,并且计划在2.1版中进行(但未指定发布日期)。这里和这里有更多信息。
但是,似乎可以使用IText在签名的文档上添加批注,而不会使用PDFStamper使签名无效,从这个问题开始
编辑2:代码以将图章添加到文档中并增量保存:
@Test
public void stampSignedDocument() throws IOException {
File file = new File("path to file");
PDDocument document = PDDocument.load(file);
File image = new File("path to image to be added to annotation");
PDPage page = document.getPage(0);
List<PDAnnotation> annotations = page.getAnnotations();
PDImageXObject ximage = PDImageXObject.createFromFileByContent(image, document);
//stamp
PDAnnotationRubberStamp stamp = new PDAnnotationRubberStamp();
stamp.setName("testing rubber stamp");
stamp.setContents("this is a test");
stamp.setLocked(true);
stamp.setReadOnly(true);
stamp.setPrinted(true);
PDRectangle rectangle = createRectangle(100, 100, 100, 100, 100, 100);
PDFormXObject form = new PDFormXObject(document);
form.setResources(new PDResources());
form.setBBox(rectangle);
form.setFormType(1);
form.getResources().add(ximage);
PDAppearanceStream appearanceStream = new PDAppearanceStream(form.getCOSObject());
PDAppearanceDictionary appearance = new PDAppearanceDictionary(new COSDictionary());
appearance.setNormalAppearance(appearanceStream);
stamp.setAppearance(appearance);
stamp.setRectangle(rectangle);
PDPageContentStream stream = new PDPageContentStream(document, appearanceStream);
Matrix matrix = new Matrix(100, 0, 0, 100, 100, 100);
stream.drawImage(ximage, matrix);
stream.close();
//close and save
annotations.add(stamp);
page.getCOSObject().setNeedToBeUpdated(true);
OutputStream os = new FileOutputStream(file);
document.saveIncremental(os);
document.close();
os.close();
}
上面的代码不会使我的签名无效,但不会保存我添加的注释。
如建议的那样,我为添加的注释,页面和注释列表将NeedToBeUpdated标志设置为true(我希望我正确地完成了最后一个):
stamp.getCOSObject().setNeedToBeUpdated(true);
COSArrayList<PDAnnotation> list = (COSArrayList<PDAnnotation>) annotations;
COSArrayList.converterToCOSArray(list).setNeedToBeUpdated(true);
page.getCOSObject().setNeedToBeUpdated(true);
document.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);
注释仍未保存,因此我显然缺少了一些内容。
编辑3:
这是我当前添加注释的方法:
@Test
public void stampSignedDocument() throws IOException {
File file = new File(
"E:/projects/eSign/g2digitalsignature/G2DigitalSignatureParent/G2DigitalSignatureTest/src/test/resources/pdfBoxTest/empty.pdf");
PDDocument document = PDDocument.load(file);
File image = new File(
"E:/projects/eSign/g2digitalsignature/G2DigitalSignatureParent/G2DigitalSignatureTest/src/test/resources/pdfBoxTest/digitalSign.png");
PDPage page = document.getPage(0);
List<PDAnnotation> annotations = page.getAnnotations();
PDImageXObject ximage = PDImageXObject.createFromFileByContent(image, document);
//stamp
PDAnnotationRubberStamp stamp = new PDAnnotationRubberStamp();
stamp.setName("testing rubber stamp");
stamp.setContents("this is a test");
stamp.setLocked(true);
stamp.setReadOnly(true);
stamp.setPrinted(true);
PDRectangle rectangle = createRectangle(100, 100, 100, 100, 100, 100);
PDFormXObject form = new PDFormXObject(document);
form.setResources(new PDResources());
form.setBBox(rectangle);
form.setFormType(1);
form.getResources().getCOSObject().setNeedToBeUpdated(true);
form.getResources().add(ximage);
PDAppearanceStream appearanceStream = new PDAppearanceStream(form.getCOSObject());
PDAppearanceDictionary appearance = new PDAppearanceDictionary(new COSDictionary());
appearance.setNormalAppearance(appearanceStream);
stamp.setAppearance(appearance);
stamp.setRectangle(rectangle);
PDPageContentStream stream = new PDPageContentStream(document, appearanceStream);
Matrix matrix = new Matrix(100, 0, 0, 100, 100, 100);
stream.drawImage(ximage, matrix);
stream.close();
//close and save
annotations.add(stamp);
appearanceStream.getCOSObject().setNeedToBeUpdated(true);
appearance.getCOSObject().setNeedToBeUpdated(true);
rectangle.getCOSArray().setNeedToBeUpdated(true);
stamp.getCOSObject().setNeedToBeUpdated(true);
form.getCOSObject().setNeedToBeUpdated(true);
COSArrayList<PDAnnotation> list = (COSArrayList<PDAnnotation>) annotations;
COSArrayList.converterToCOSArray(list).setNeedToBeUpdated(true);
document.getPages().getCOSObject().setNeedToBeUpdated(true);
page.getCOSObject().setNeedToBeUpdated(true);
document.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);
OutputStream os = new FileOutputStream(file);
document.saveIncremental(os);
document.close();
os.close();
}
当我在未签名的文档上使用注释添加注释时,注释将被添加并且可见。但是,在已签名的文档上使用它时,不会出现注释。
我在notepad ++中打开了pdf文件,发现自从我发现该注释以及与该注释有关的其余代码以来,似乎已经添加了注释:
<<
/Type /Annot
/Subtype /Stamp
/Name /testing#20rubber#20stamp
/Contents (this is a test)
/F 196
/AP 29 0 R
/Rect [100.0 100.0 200.0 200.0]
>>
但是,当我在Adobe Reader中打开文档时,它不会出现。也许这与外观流更多地关系于注解本身?
问题是使用PDDocument.save()会创建一个新文档,从而使签名无效。
使用PDDocument.saveIncremental(…)不会使签名无效,但是不会更新文档的任何更改(例如注释或表单填充),仅用于保存签名。
PDFBox 2.0尚无法使用注释或表单填充来更新签名的PDF文档,但是一旦PDFBox 2.1推出,就应该可以进行更新。
有关此问题的信息:此处和此处
然而使用的iText的PDFStamper解决加上注解签署的文件,而不作为回答的签名无效的问题在这里。
然后我用adobe签名并通过以下方式传递: 我真的不明白为什么这不起作用。任何帮助都会很好! 编辑: 按照建议,我已经将添加的注释、页面和注释列表的NeedToBeUpdated标志设置为true(希望最后一个操作正确): 注释仍然没有保存,所以我显然遗漏了一些东西。 编辑3: 但是,当我在adobe Reader中打开文档时,它不会出现。也许这与外观流的关系更大,而不是注释本身?
问题内容: 我在PDF文档中(以编程方式)填写了表格(AcroPdf),然后在文档上签名。我从doc.pdf开始,使用PDFBox的setFields.java示例创建doc_filled.pdf。然后,我根据签名示例使用一些代码对doc_filled.pdf进行签名,以创建doc?filled_signed.pdf,然后在Acrobat Reader中打开pdf。输入的字段数据可见,签名面板告诉
我在PDF文档中(以编程方式)填写一个表单(AcroPdf),然后在文档上签名。我从doc.pdf开始,使用pdfbox的setfields.java示例创建doc_filler.pdf。然后我对doc_fill.pdf进行签名,创建doc?filled_signer.pdf,使用一些代码,基于签名示例并在Acrobat Reader中打开pdf。输入的字段数据是可见的,并且签名面板告诉我 “此签
我在这里读到了关于saveIncremental是如何工作的,我的最终结果需要类似于这里,我已经成功地基于签名字段本身创建了具有多重可视化的可见签名(与响应中的情况不同,但响应对我帮助很大)。为了详细说明标题,我目前的基本任务是在已经签名的文档上创建一个空签名字段,而不中断现有签名。但是,这里的示例不适用于saveIncremental。我在主函数的末尾添加了以下片段(改编),但没有结果: 生成的
我对iTextSharp有意见。我有一个带有表单字段的文档,并且我已经为签名生成了字段。当第一个人在文件上签字时,它就会正常工作。Adobe Reader显示有效签名。当我让第二个人在文档上签名时,Adobe Reader显示签名1现在是“未知签名”,签名无效。Adobe reader显示: 此签名中包含的格式或信息有错误(支持信息:SigDict/Contents非法数据)
PDF创建步骤: 通过添加空签名字段名称创建pdf:suhasb@gmail.com和nikhil.courser@gmail.com,使用原始的hello.pdf输出文件名hello_tag.pdf运行程序>tagpdfsignaturefields.java 从hello_tag.pdf文件中提取签名字段suhasb@gmail.com进行首次签名,输出文件名为hello_signd.pdf