尝试使用 java 签署 pdf 文档。为啥 PDF 文件中的签名无效?
Posted
技术标签:
【中文标题】尝试使用 java 签署 pdf 文档。为啥 PDF 文件中的签名无效?【英文标题】:Trying to sign a pdf document with java. Why is the signature invalid in the PDF files?尝试使用 java 签署 pdf 文档。为什么 PDF 文件中的签名无效? 【发布时间】:2018-10-29 13:39:03 【问题描述】:我目前正在一个 Java 应用程序上处理 PDF,该应用程序对 PDF 文档进行了一些修改。
目前,这些 PDF 的签名工作正常,因为我正在使用 FileInputStream 和 FileOutputStream 等类。基本上,我从源文件夹中复制原始文档,然后将它们放在输出文件夹中。我正在使用带有 pdfbox 1.8.9 的 PDDocument 类
但是,我想使用相同的文件,这意味着我不再假装复制 PDF。我想获取文件,签名,然后覆盖原始文件。
因为我了解到让 FileInputStream 和 FileOutputStream 指向同一个文件不是一个好主意,所以我只是尝试使用 File 类。
我尝试了以下方法:
File file = new File(locOriginal);
PDDocument doc = PDDocument.load(file);
PDSignature signature = new PDSignature();
Overlay overlay = new Overlay();
//The signature itself. It has not been modified
signature.setFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED); // default filter
signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
if (msg.getAreaNegocio().startsWith("A"))
signature.setName(this.campoCertificadoAcquiring);
signature.setLocation(this.localCertificadoAcquiring);
signature.setReason(this.razaoCertificadoAcquiring);
else
signature.setName(this.campoCertificadoIssuing);
signature.setLocation(this.localCertificadoIssuing);
signature.setReason(this.razaoCertificadoIssuing);
// register signature dictionary and sign interface
doc.addSignature(signature,this);
doc.saveIncremental(file.getAbsolutePath());
doc.close();
我的 PDF 文件确实按预期被覆盖,但是当我打开文件时签名不再有效。我读了这些问题......它与这些问题中的任何一个有关吗?我能做些什么来解决这个问题?
PDFBox 1.8.10: Fill and Sign PDF produces invalid signatures
PDFBox - opening and saving a signed pdf invalidates my signature
感谢您的帮助!
【问题讨论】:
顺便说一句:signature.setFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED)
- 将过滤器设置为子过滤器名称没有意义。现在过滤器名称已经不再重要了,所以这可能不会导致失败,但设置它仍然是无稽之谈。
我没有开发代码。此代码是很久以前制作的,但感谢您启发我! :)
【参考方案1】:
在 PDFBox 1.8.16 之前,1.8.* saveIncremental(filename)
是错误的。这在PDFBOX-4312 中有所描述,但令人困惑,因为用户删除了他自己的大部分消息并遇到了多个其他问题。如果您坚持使用过时的版本(存在安全问题),请尝试使用此代码而不是调用saveIncremental(filename)
:
//BEWARE: do not "optimize" this method by using buffered streams,
// because COSStandardOutputStream only allows seeking
// if a FileOutputStream is passed, see PDFBOX-4312.
FileInputStream fis = new FileInputStream(fileName);
byte[] ba = IOUtils.toByteArray(fis);
fis.close();
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(ba);
fis = new FileInputStream(fileName);
saveIncremental(fis, fos);
不,我认为您链接的问题与您的问题无关。
顺便说一句,我不认为覆盖原始文件是个好主意。如果出现错误或断电,您将面临丢失文件的风险。
另见 mkl 的评论:setFilter()
通常用参数PDSignature.FILTER_ADOBE_PPKLITE
调用。
【讨论】:
“我不认为覆盖原始文件是个好主意” - +10! 我的想法完全正确,但我的客户要求这样做,因为要生成 10k 个文档,实际上我们会生成 50k 个文档,因为每次我们在文档中添加一些东西,比如背景图像、签名、复制,我们复制它们。我仍在探索覆盖同一个文件的可能性和影响,但他们希望这样。 如果无法使用,请分享原始文件和签名文件。以上是关于尝试使用 java 签署 pdf 文档。为啥 PDF 文件中的签名无效?的主要内容,如果未能解决你的问题,请参考以下文章
JAVA 代码 使用PD4ML进行 html转换 PDF文档时,如果文档中存在 “~” 字符,则该字符转换的结果 不一致