保护 PDF 文件和 PDFBox 中的 "saveIncremental"

Protect PDF file and "saveIncremental" in PDFBox

我正在尝试使用权限和密码保护 PDF 文件,然后使用 "saveIncremental" 方法保存它(因为如果签名在 PDF 文件中,我希望它即使在保护后仍然有效)。

这是代码片段:

StandardProtectionPolicy standardProtectionPolicy = new StandardProtectionPolicy(ownerPassword, userPassword, accessPermission);

File protectedFile = new File(pdfFile.getParent(), substring + "_protected.pdf");

try (PDDocument document = PDDocument.load(pdfFile)) {

     document.protect(standardProtectionPolicy);

     SecurityHandler securityHandler = document.getEncryption().getSecurityHandler();
     if (!securityHandler.hasProtectionPolicy()) {
                throw new IllegalStateException("PDF contains an encryption dictionary, please remove it with "
                        + "setAllSecurityToBeRemoved() or set a protection policy with protect()");
     }
     securityHandler.prepareDocumentForEncryption(document);

     // update and save
     document.getDocument().getEncryptionDictionary().setNeedToBeUpdated(true);
     document.getEncryption().getCOSDictionary().setNeedToBeUpdated(true);

     COSDictionary encrypt = (COSDictionary) document.getDocumentCatalog().getCOSObject().getDictionaryObject(COSName.ENCRYPT);
     if (encrypt != null) encrypt.setNeedToBeUpdated(true);
     document.getDocumentCatalog().getPages().getCOSObject().setNeedToBeUpdated(true);
     document.getDocumentCatalog().getCOSObject().setNeedToBeUpdated(true);

     document.saveIncremental(new FileOutputStream(protectedFile));
}

我用了this file.

Here 是结果 - 受保护的 PDF 文件和 "allSecurityToBeRemoved".

之后的同一文件

用户密码为 "user",所有者密码为 "owner"。

问题出在受保护的文件上。看不到内容,签名无效,所有签名信息都以不可读的字符显示...

对于 "save" 它有效,但对于 "saveIncremental" 无效。是否可以让它与 "saveIncremental" 一起使用,这样签名仍然有效?如果是,如何?

我正在使用 PDFBox 2.0.7 和 Adob​​e Acrobat Reader DC。

感谢大家的帮助!

@Tilman 已经在评论中展示了多头和空头

so in PDFBox there is no way how to encrypt file with signatures so the signatures will remain valid?

不是递增的。不适用于 PDFBox,也不适用于其他软件。您必须在开始时加密,即在创建 PDF 时。 (或者你正常加密保存,然后重新载入增量签名保存。

这里对背景做一些解释:

当您签署 PDF 时,您通常首先通过在字段值中添加一个带有占位符的签名表单字段来准备它,然后您对这个准备好的 PDF 减去占位符进行加密签名并将生成的签名注入该占位符。 (更详细here。)结果:

因此,带符号的字节是序列化 PDF 文件中的实际字节,而不是某些(可能与加密无关)in-memory 表示。所以这些字节的每次更改都会破坏签名

另一方面,

PDF 加密 必须相同地应用于所有文档修订:给定 PDF 的所有修订都被加密(使用相同的密码或证书数据)或 none 是,这意味着每个修订 .[=14= 的预告片中至少有 一个 Encrypt 条目]

因此,如果您加密签名的 PDF,您会自动更改签名字节的某些部分,至少是尾部,所以 您破坏了签名.

不过,您可以做的是同时加密和签名,或者先创建一个加密的 PDF,然后在增量更新中对其签名。

(注意,虽然 ISO 32000-1 在这方面有点草率,没有提到注入的签名字节不能自己加密。ISO 32000-2 已经澄清了这一点,但现在有一些假设签名字节被加密的 PDF 验证器,有些则没有。更详细的 。因此,加密和签名可能不值得麻烦...)