PDFBox зашифрован/заблокирован PDF по-прежнему изменяется Adobe Reader во время «сохранить как»

Я работаю над реализацией, в которой наша система создает файл 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

Изменить (решение):==========

Как предложил @mkl (все кредиты этому человеку), мы смогли решить проблему с использованием флага appendOnly, который является частью функциональности AcroForm. Оказалось, что для решения нашей проблемы не требовался флаг signalExists. (и после прочтения спецификаций не применимо)

Ниже приведено решение, которое мы реализовали:

    /*
     *  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);

    }

person JPas    schedule 24.10.2019    source источник
comment
Вы можете попробовать установить флаги AcroForm, которые утверждают, что подпись существует. Это должно по крайней мере привести к тому, что любое изменение будет применено как добавочное обновление, которое можно будет отменить, обрезав файл до исходного размера.   -  person mkl    schedule 26.10.2019
comment
И всегда обновляйтесь до последней версии, на данный момент 2.0.17. (Не поможет и с этой проблемой, но исправит ошибки, в том числе проблемы с безопасностью)   -  person Tilman Hausherr    schedule 27.10.2019
comment
Спасибо за вклад @mkl и Tilman-Hausherr! Я обновился до 2.0.17 (действительно, проблема не решена, но все равно хорошо) и просмотрел флаги AcroForm. Я новичок в разработке PDF, поэтому мне пришлось искать AcroForms и некоторый код, чтобы это сделать. Я добавлю код в свой пост, который я пробовал, но, к сожалению, это не помешало Adobe Reader изменить полученный PDF-файл во время действия «сохранить как»... Если я неправильно истолковал или пропустил что-либо по этому вопросу, чем любая помощь приветствуется!   -  person JPas    schedule 30.10.2019
comment
Пожалуйста, поделитесь примером PDF до и после манипуляций с этой установкой Adobe Reader.   -  person mkl    schedule 30.10.2019
comment
@mkl Придержи коней! После еще одного теста (хотел провести двойную проверку с пользователем, который смог изменить pdf на своей рабочей станции), похоже, что это акроформа и 2 флага signaturesExist и appendOnly< /b> имеют эффект! В настоящее время я делаю еще несколько тестов. Держать вас в курсе...   -  person JPas    schedule 30.10.2019
comment
@mkl Отличные новости: оказывается, вы указывали в правильном направлении. Использование флага appendOnly было именно тем, что нам было нужно. Читая спецификацию PDF, кажется, что это то, что мы искали, и оно хорошо справляется со своей задачей. Мы, вероятно, объединим его с существующими разрешениями + шифрованием пароля (код в моем исходном сообщении), чтобы предотвратить добавление нового контента. Я добавлю полученный код где-нибудь здесь. Спасибо большое за вашу помощь!! Я здесь новенький, так что скажите: вы напишете ответ на мой запрос, который я отмечу как ответ, или мне сделать это?   -  person JPas    schedule 31.10.2019
comment
Замечательно! (Однако мне было бы действительно интересно, как эти конкретные установки Adobe были изменены, чтобы изменить PDF-файлы в первую очередь ...) Я напишу ответ.   -  person mkl    schedule 31.10.2019


Ответы (1)


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

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

Рассматриваемая запись flags — это запись SigFlags в словаре AcroForm.

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

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

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

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

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

person mkl    schedule 31.10.2019