Добавление цифровой подписи в PDF с видимой меткой времени и полем Reason с помощью ESIG/DSS
Я пытаюсь понять и реализовать решение на основе проекта Службы цифровой подписи, спонсируемого Европейской комиссией. В настоящее время я преуспел в использовании абстракции, предоставленной приложением DSS-DEMO, упомянутой в вышеупомянутой ссылке на github, с помощью клиентского программного обеспечения Nowina NexU. Я хочу подписать цифровой документ PDF со следующей конфигурацией:
- нет контейнера
- PAdES подпись
- окутанный
- PAdES_BASELINE_LT уровень подписи
- Алгоритм дайджеста SHA256
Я хочу, чтобы подпись имела видимую часть, то есть была бы видна на первой странице документа. Это несколько продемонстрировано здесь. Лично мне нужна фактическая отметка времени подписи и имя подписавшего из ее сертификата. В приведенной выше демонстрации это делается путем предоставления "параметров" функции подписи.
Я также хочу заполнить поле "Причина" подписи - оно впоследствии отображается при просмотре свойств подписи с помощью программы, подобной Adobe Acrobat Reader.
Мои проблемы до сих пор следующие, и я не могу найти ни примеров, ни другой информации о них.
- Если я хочу отобразить метку времени подписи, которую я получу от службы Authority Timestamp, как я получу ее, поскольку связь с сервером меток времени осуществляется во время процесса подписания, то есть после указания параметров, как я упоминал выше. Я думаю, мне нужно копаться в коде DSS и делать все шаги, сделанные там для меня лично.
- В настоящее время происходит странная вещь. Похоже, что подписи считаются действительными или, по крайней мере, НЕИЗВЕСТНЫМИ, когда я указываю жестко запрограммированную причину (например, "тест-тест") или вообще не вижу причину. Когда я заполняю его из результатов чего-то другого, подпись недействительна. Поскольку подобные вещи обычно не происходят по волшебству, я, должно быть, делаю что-то ужасно неправильно.
Код организован примерно так: существует REST-связь между двумя компьютерами - сервером и клиентом с установленным NexU. NexU осуществляет всю связь со смарт-картой или любым другим хранилищем сертификатов на клиентском компьютере - он обменивается значением дайджеста и подписанным значением дайджеста с сервером. Есть, среди прочего, две специфические фазы в коде сервера:
- getDataToSign - здесь дайджест рассчитывается по содержанию PDF
- signDocument - здесь происходит фактическое подписание - (вложение подписи в документ, я полагаю?).
Я даю обеим фазам множество параметров, которые, помимо прочего, указывают метку времени подписания, причину и визуальные параметры текста, который я хочу отобразить на первой странице. Я делаю это с одинаковыми параметрами для обеих фаз (потому что я не уверен, на какой фазе я должен дать какую)
Моя дата подписания - не логично ли, чтобы она была настолько близка к отметке времени сервера авторизации, насколько это возможно? Хорошо, я устанавливаю текущую метку времени моего собственного сервера в момент начала процесса подписания.
Я устанавливаю Reason, используя PAdESSignatureParameters.setReason. Любое полезное понимание приветствуется - спасибо.
1 ответ
- Я решил странную проблему с полем Reason в Signature.
- Похоже, я не вижу, чтобы дата подписания отличалась от метки времени, предоставленной властями.
Объяснение следует.
Что касается первого случая, это была моя вина. Для уточнения, насколько я понимаю, параметры подписи предоставляются методам DSS два раза с использованием метода SigningService.fillParameters().
- в SigningService.getDataToSign(...), а затем
- в SigningService.signDocument(...)
Это важно сделать в обоих методах, потому что в первый раз вычисляется хэш / дайджест документа, подлежащего подписанию. Поскольку я выбрал подпись, которая должна быть заключена в оболочку, то есть должна содержаться в документе, который будет подписан, нам нужно сначала применить подпись, а затем вычислить дайджест на основе этого "окончательного" документа.
Насколько я видел в коде DSS (приблизительно), представление загруженного PDF в памяти подписывается, и его дайджест вычисляется во время getDataToSign - но результат отбрасывается.
Во время самого метода signDocument (между тем дайджест отправляется обратно на клиент с установленным NexU и возвращается обратно на сервер с подписью), загруженный PDF снова подписывается, его дайджест вычисляется снова, но на этот раз фактический подписанный дайджест (мы получили от клиента) также применяется к документу - и результат этой операции в памяти отправляется обратно клиенту в виде подписанного документа PDF.
Что я делал неправильно, так это то, что в первый раз я терял переменную, которую собирался добавить в качестве причины (она была потеряна где-то в атрибутах модели - я не передавал ее где-то между запросами), в результате чего моей первой карты параметров, переданной в getDataToSign, отличной от второй карты параметров - поэтому вполне логично, что фактический хэш / дайджест документа отличался от дайджеста в сохраненной подписи (потому что в то время -подписан был подсчитан, я не передавал причину). Вот почему, когда я передавал жестко закодированное значение, поскольку оно было жестко закодировано, оно присутствовало во время обоих вызовов fillParameters. Это была такая глупая ошибка, я знаю. Я должен был знать это, потому что не было абсолютно ничего о каких-либо трудностях с передачей Reason (или других полей, таких как Location) в Подпись.
Кстати, подпись выполняется с использованием Apache PDFBox, и это делается постепенно.
Что касается второго, мы решили оставить все как есть, хотя между отметкой времени подписания и отметкой времени отметки имеется сравнительно впечатляющий разрыв. Я действительно не знаю, какими должны быть допустимые пробелы в подобных случаях. Я думаю, что это происходит потому, что
- Мой сервер может иметь немного необычное местное время
- Поскольку весь процесс подписания происходит между двумя компьютерами (сервером и клиентом с установленным NexU, а также со смарт-картой), а также потому, что появляются разные диалоговые окна с запросом пароля и т. Д., - все это откладывает фактическое подписание и обращение к метке времени делается во время самого последнего шага. Конечно, я не уверен, что это проблема, так как теоретически авторитетные метки времени не знают о фактическом изменении содержимого - в этом случае была бы вызвана предыдущая ошибка...
Это больше похоже на это - конечно, я открыт для других комментариев и ответов. Спасибо!