PDFBox зашифрованный / заблокированный PDF все еще изменяется Adobe Reader во время «сохранить как» - PullRequest
2 голосов
/ 24 октября 2019

Я работаю над реализацией, в которой наша система генерирует файл PDF для загрузки пользователем. Ключом нашего процесса и системы является то, что этот PDF-файл не должен изменяться пользователем или программой на компьютере пользователя (по крайней мере, не без злого умысла), так как файл может быть загружен в систему позже, где нам нужно сделатьубедитесь, что файл находится в исходном состоянии, сравнивая его хеш-значение.

Мы думали, что достигли этого, сначала отключив все разрешения (CanModify, CanAssembleDocument и т. Д.), А затем зашифровав документ с помощью пароля владельца. Это предотвратило изменение файла всеми читателями, к которым у нас был доступ. Теперь выясняется, что один из наших пользователей изменяет PDF-файл, как только он открывает файл в Acrobat Reader и «сохраняет как» документ в новый 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();
    }

Это приводит к свойствам Adobe:

Adobe properties

Редактировать (решение): ==========

Как предлагается@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);

    }

1 Ответ

1 голос
/ 31 октября 2019

Даже если подпись документа PDF на самом деле не подходит для вас, вы можете попробовать установить AcroForm , чтобы утверждал, что подпись существует .

Это должно препятствовать тому, чтобы программы, чувствительные к этим флагам (например, Adobe Reader), применяли изменения к PDF, или, по крайней мере, они должны применять свои изменения как инкрементное обновление, которое можно отменить, обрезав файл до его исходного размера.

Указанная запись флагов - это запись SigFlags в словаре AcroForm .

Битовая позиция - Имя - Значение

1 - SignaturesExist - Если установлено, документ содержит хотя бы одно поле подписи. Этот флаг позволяет интерактивному процессору PDF включать элементы пользовательского интерфейса (например, пункты меню или кнопки), связанные с обработкой подписи, без необходимости сканировать весь документ на наличие полей подписи.

2 - AppendOnly - Если установлено, документ содержит подписи, которые могут быть признаны недействительными, если файл сохранен (записан) способом, который изменяет его предыдущее содержимое, в отличие от инкрементного обновления. Простое обновление файла путем добавления новой информации в конец предыдущей версии является безопасным (см. H.7, «Пример обновления»). Интерактивные обработчики PDF могут использовать этот флаг, чтобы сообщить пользователю, запрашивающему полное сохранение, о том, что подписи будут признаны недействительными и требуют явного подтверждения перед продолжением операции.

(ISO 32000-2, таблица 225)- Флаги подписи)

Таким образом, вы должны установить запись SigFlags в словаре AcroForm в каталоге на 3 . Для начала вам может потребоваться создать словарь AcroForm , если в вашем PDF еще нет определения формы

...