Подписание в формате Pdfbox — сохранение в режиме реального времени против сохранения в режиме реального времени

#java #pdfbox #digital-signature

#java #pdfbox #цифровая подпись

Вопрос:

Я работаю над подписанием PDF-файла, и у меня возникают некоторые проблемы. В примере с pdfbox я вижу 2 способа подписать pdf. Первый:

 document.saveIncremental(output);
 

И второй способ:

 ExternalSigningSupport externalSigning = doc.saveIncrementalForExternalSigning(fos);
// invoke external signature service
byte[] cmsSignature = sign(externalSigning.getContent());

if (isLateExternalSigning()) {
    // this saves the file with a 0 signature
    externalSigning.setSignature(new byte[0]);
    // remember the offset (add 1 because of "<")
    int offset = signature.getByteRange()[1]   1;
    // now write the signature at the correct offset without any PDFBox methods
    RandomAccessFile raf = new RandomAccessFile(signedFile, "rw");
    raf.seek(offset);
    raf.write(Hex.getBytes(cmsSignature));
    raf.close();
} else {
    // set signature bytes received from the service and save the file
    externalSigning.setSignature(cmsSignature);
}
 

В чем разница между saveIncremental и saveIncrementalForExternalSigning ? Я имею в виду варианты использования этих методов.

Каковы цели каждого метода?

Что такое «инкрементный»?

Что такое «внешняя подпись»? Это третья сторона, например, правительство?

Ответ №1:

Что такое «инкрементный»?

При сохранении изменений в pdf у вас есть два варианта: можно сохранить совершенно новый файл pdf или добавить изменения в (копию) исходного файла. Последний метод называется инкрементным обновлением.

При повторном подписании уже подписанного PDF-файла дополнения для этой новой подписи должны применяться как инкрементное обновление, чтобы предотвратить аннулирование уже существующих подписей:

эскиз pdf с несколькими подписями

(Смотрите Этот ответ для фона и ссылок.)

Таким образом, библиотеки pdf должны поддерживать подписание PDF-файлов также при инкрементных обновлениях.

PDFBox, для простоты, поддерживает подписание PDF-файлов только при инкрементных обновлениях, поэтому таким образом уже добавляется первая подпись.

В чем разница между saveIncremental и saveIncrementalForExternalSigning ?

saveIncremental

Создание подписанного pdf-файла с saveIncremental использованием обратного вызова для создания контейнера подписи: метод sign SignatureInterface реализации, который вы выбрали в своем PDDocument.addSignature вызове, используется saveIncremental для извлечения контейнера подписи для байтов документа для подписи.

В примерах подписи pdfbox sign метод реализован CreateSignatureBase и задан как интерфейс подписи signPDF .

saveIncrementalForExternalSigning

Создание подписанного PDF-файла с использованием saveIncrementalForExternalSigning не требует SignatureInterface реализации. Вместо этого он возвращает ExternalSigningSupport объект, из которого вы можете извлечь данные для sign ( getContent ), для которого, в свою очередь, вы можете затем создать контейнер подписи, который вы в конечном итоге можете ввести в pdf с помощью другого ExternalSigningSupport метода ( setSignature ) .

Пока это звучит только как вариант поддержки различных настроек шаблонов программирования, обратного вызова или без обратного вызова, последовательного.

Однако здесь есть дополнительная опция, также известная как отложенная подпись: вместо введения фактического контейнера подписи вы можете ввести фиктивный:

 externalSigning.setSignature(new byte[0]);
 

и извлеките позицию, в которой находится заполнитель для контейнера подписи (в шестнадцатеричной кодировке):

 int offset = signature.getByteRange()[1]   1;
 

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

В конечном итоге вы можете внедрить контейнер подписи, как в примере кода:

 RandomAccessFile raf = new RandomAccessFile(signedFile, "rw");
raf.seek(offset);
raf.write(Hex.getBytes(cmsSignature));
raf.close();
 

примеры использования этих методов

Как было сказано выше, на первый взгляд, эти два метода просто поддерживают разные шаблоны программирования, обратный вызов и последовательный.

Дополнительная опция, тем не менее, действительно позволяет поддерживать дополнительные варианты использования, она особенно удобна в некоторых ситуациях:

  • если служба подписи работает медленно, например, из-за того, что запросы собираются и обрабатываются пакетами или ожидается подтверждение второго фактора.
  • если извлечение и внедрение контейнера подписи должны выполняться в другой программе, возможно, даже на другом компьютере, чем подготовка pdf.

Что такое «внешняя подпись»? Это третья сторона, например, правительство?

«Внешний» здесь относится к выполнению программы. В то время как обратный вызов кажется очень внутренним, разделение вызовов в последовательном порядке ощущается меньше, и отложенная подпись может рассматриваться как действительно внешняя.

Сторонние службы подписи (будь то государственные или нет) могут быть интегрированы в любую архитектуру. В зависимости от их производительности, отложенный подход может быть предпочтительнее.

Комментарии:

1. Привет @mkl, как вы сказали, даже я использую первый метод или второй, ethod, мне все равно нужно реализовать свой собственный метод «sign». Разница здесь в том, что первый метод автоматически вызовет метод «sign» (из обратного вызова), в то время как второй метод, мне нужно вызвать метод «sign» вручную. Это правильно?

2. По сути, да. В первом случае вы обязаны реализовать этот код подписи в методе в соответствии с упомянутым интерфейсом, но затем это делается. Во втором случае вы не связаны интерфейсом, но вам дополнительно необходимо явно вызвать код. Скорее вопрос предпочтений программирования, чем что-либо еще.