#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-файлов также при инкрементных обновлениях.
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. По сути, да. В первом случае вы обязаны реализовать этот код подписи в методе в соответствии с упомянутым интерфейсом, но затем это делается. Во втором случае вы не связаны интерфейсом, но вам дополнительно необходимо явно вызвать код. Скорее вопрос предпочтений программирования, чем что-либо еще.