【问题标题】:PDFBox encrypted / locked PDF is still modified by Adobe Reader during 'save as'在“另存为”期间,Adobe Reader 仍会修改 PDFBox 加密/锁定的 PDF
【发布时间】:2020-02-20 12:42:32
【问题描述】:

我正在执行一个实现,我们的系统会生成一个 PDF 文件供用户下载。 我们的流程和系统的关键是该 PDF 文件不应由用户或用户计算机上的程序修改(至少,并非没有恶意),因为该文件可以稍后上传到我们需要制作的系统通过比较文件的哈希值确保文件处于原始状态。

我们认为我们首先禁用所有权限(CanModify、CanAssembleDocument 等)然后使用所有者的密码加密文档来实现此目的。这阻止了我们有权访问的所有读者修改文件。现在事实证明,我们的一位用户在 Acrobat Reader 中打开文件并将文档“另存为”到新的 pdf 文件后立即修改了 PDF。我们无法使用相同的阅读器版本 (2015.006.30497) 重现此内容,但他每次都可以。

签署 PDF 文档的替代方案对我们来说不是一个选项,至少不能使用 PKI 或用户可以在其阅读器中看到的任何可见签名。如果有某种不可见的签名选项,那就太好了,但我不知道怎么做。

在我们用来锁定 PDF 的代码下方。出于测试目的,我们禁用了所有权限,但无济于事。我们使用的是 PDFBox 2.0.11。

任何建议有哪些选项可以更好地锁定文件以进行修改?

    public static byte[] SealFile(byte[] pdfFile, String password) throws IOException
    {   PDDocument doc =PDDocument.load(pdfFile);
        ByteArrayOutputStream bos= new ByteArrayOutputStream();
        byte[] returnvalue =null;
        int keyLength = 256;

        AccessPermission ap = new AccessPermission();

        //Disable all
        ap.setCanModifyAnnotations(false);
        ap.setCanAssembleDocument(false); .
        ap.setCanFillInForm(false);
        ap.setCanModify(false);
        ap.setCanExtractContent(false);
        ap.setCanExtractForAccessibility(false);
        ap.setCanPrint(false);

        //The user password is empty ("") so user can read without password. The admin password is
        // set to lock/encrypt the document.
        StandardProtectionPolicy spp = new StandardProtectionPolicy(password, "", ap);
        spp.setEncryptionKeyLength(keyLength);
        spp.setPermissions(ap);
        doc.protect(spp);
        doc.save(bos);
        doc.close();
        bos.flush();
        return bos.toByteArray();
    }

这会产生 Adob​​e 属性:

编辑(解决方案):==========

正如@mkl 所建议的,(此人的所有功劳)我们能够通过使用 appendOnly 标志来解决问题,该标志是 AcroForm 功能的一部分。事实证明,解决我们的问题不需要 signatureExists 标志。 (阅读规格后,不适用)

以下是我们实施的解决方案:

    /*
     *  This method is used to add the 'appendOnly flag' to the PDF document. This flag is part of
     *  the AcroForm functionality that instructs a PDF reader that the file is signed and should not be
     *  modified during the 'saved as' function. For full description see PDF specification PDF 32000-1:2008
     *  (https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf)
     *  paragraph 12.7.2 Interactive Form Dictionary
     */
    public static void addAcroFormSigFlags(PDDocument pdfDoc) {
        PDDocumentCatalog catalog = pdfDoc.getDocumentCatalog();
        PDAcroForm acroForm = catalog.getAcroForm();
        if (acroForm == null) {
            acroForm = new PDAcroForm(pdfDoc);
            catalog.setAcroForm(acroForm);

        }
        // AppendOnly:
        // If set, the document contains signatures that may be invalidated if the
        // file is saved (wirtten) in a way that alters its previous contents, as
        // opposed to an incremental update. Merely updating the file by appending
        // new information to the end of the previous version is safe (see h.7,
        // "Updating Example"). Conforming readers may use this flag to inform a
        // user requesting a full save that signatures will be invalidated and
        // require explicit confirmation before continuing with the operation
        acroForm.setAppendOnly(true);

        // SignatureExists: (Currently not used by us)
        // If set, the document contains at least one signature field. This flag
        // allows a conforming reader to enable user interface items (such as menu
        // items or pushbuttons) related to signature processing without having to
        // scan the entire document for the presence of signature fields.
//        acroForm.setSignaturesExist(true);

        // flag objects that changed (in case a 'saveIncremental' is done hereafter)
        catalog.getCOSObject().setNeedToBeUpdated(true);
        acroForm.getCOSObject().setNeedToBeUpdated(true);

    }

【问题讨论】:

  • 您可以尝试设置声称存在签名的 AcroForm 标志。这应该至少导致任何更改被应用为增量更新,可以通过将文件截断为其原始大小来撤消。
  • 并且始终更新到最新版本,目前是 2.0.17。 (也无助于解决这个问题,但它修复了包括安全问题在内的错误)
  • 感谢@mkl 和 Tilman-Hausherr 的输入!我已经升级到 2.0.17(确实没有解决问题,但无论如何都很好)并查看了 AcroForm 标志。我对 PDF 开发相当陌生,所以必须查找 AcroForms 和一些代码才能完成这项工作。我会将代码添加到我尝试过的帖子中,但不幸的是,它并没有阻止 Adob​​e Reader 在另存为操作期间修改生成的 PDF……如果我误解或遗漏了关于这个主题的任何内容欢迎任何帮助!
  • 请在安装 Adob​​e Reader 之前和之后分享一个示例 PDF。
  • @mkl 抓住你的马!在做了更多测试之后(想要对能够在他的工作站上修改 pdf 的用户进行一些双重检查),它看起来确实像这个 acroform 和 2 个标志 signaturesExistappendOnly 有效果!我目前正在做更多的测试。随时通知您...

标签: pdf encryption adobe pdfbox reader


【解决方案1】:

即使您无法真正签署 PDF 文档,您也可以尝试设置 声称存在签名的 AcroForm 标志

这应该防止对这些标志敏感的程序(如 Adob​​e Reader)将更改应用到 PDF,或者至少它们应该将更改应用为增量更新,可以通过将文件截断为其原始大小来撤消。

有问题的标志条目是 AcroForm 字典中的 SigFlags 条目。

位位置姓名 — 意义

1SignaturesExist — 如果设置,则文档包含至少一个签名字段。此标志允许交互式 PDF 处理器启用与签名处理相关的用户界面项(例如菜单项或按钮),而无需扫描整个文档以查找签名字段的存在。

2仅追加 — 如果设置,则文档包含签名,如果文件以更改其先前内容的方式保存(写入)而不是增量更新,则该签名可能会失效。仅通过将新信息附加到先前版本的末尾来更新文件是安全的(参见 H.7,“更新示例”)。交互式 PDF 处理器可以使用此标志来通知请求完全保存的用户签名将无效,并且需要在继续操作之前明确确认。

(ISO 32000-2,表 225 - 签名标志)

因此,您应该将目录AcroForm字典中的SigFlags条目设置为3。如果您的 PDF 还没有表单定义,您可能必须先创建 AcroForm 字典

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-23
    • 1970-01-01
    • 2022-01-24
    • 2012-09-24
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    • 1970-01-01
    相关资源
    最近更新 更多