iTextSharp не отображает цифровую подпись

Я прочитал электронный текст цифровой подписи I-TEXT, а также предыдущие сообщения, на которые ответил MKL (который, похоже, является авторитетом в этой теме вместе с Бруно).

по сути, у меня есть служба приложений Azure, которая получает цифровую подпись (base 64) и цепочку сертификатов из API подписи компании. API подписи компании возвращает подпись в Base64 вместе с цепочкой сертификатов.

Я просто хочу вставить объект / контейнер подписи в PDF-файл, чтобы он отображался на панели подписи, когда конечный пользователь открывает PDF-файл. Я предпочитаю использовать отложенное подписание.

Я перешел от примера клиентской переподписи в главе 4 к «Отложенной подписи» в MKL «Как создать подпись PDF без предварительного знания подписывающего сертификата».

API компании возвращает обычную подпись, в чем я почти уверен, а также возвращает цепочку из трех строковых сертификатов.

Я должен отметить, что у меня есть корневой и вспомогательный сертификаты заранее (2 файла .cer), но я не использую их при подготовке pdf для хеширования прямо сейчас, поскольку в примере с отложенной подписью они явно не используются. Для кода построения контейнера (после получения ответа от API компании) я использую цепочку из 3 сертификатов, возвращенную из API компании, но я также пробовал ее с двумя файлами .cer, но безрезультатно.

Единственная разница между моим кодом и кодом в примере - это вместо byte [] certificateBytes = THE_RETRIEVED_CERTIFICATE_BYTES; X509Certificate x509Certificate = новый X509CertificateParser (). ReadCertificate (certificateBytes); Я создаю 3 сертификата x509Certificates (по одному на каждую строку в цепочке, возвращаемую API компании.

К сожалению, что-то не работает, я получаю эти ошибки в Acrobat: подпись недействительна, есть ошибки в форматировании или информации, содержащейся в этой подписи, личность подписи еще не проверена, время подписи определяется часами на компьютере подписавшего ... также, если я нажму «Сведения о сертификате» чуть ниже этой ошибки в Acrobat, это будет пусто. Это были в значительной степени ошибки, которые я получал при попытке примера clientserversigning

Я очень стараюсь и задаюсь вопросом, что это может быть ... стоит ли мне попробовать изменить расчетный размер с 12000 и увеличить его? или ошибки, которые я получаю в Acrobat, возможно, они намекают, что цепочка сертификатов из API компании не улавливается кодом построения отложенного контейнера для подписи ... Я борюсь, но любые советы были бы очень признательны

Эван


Чтобы уточнить, я следую примеру clientserversigning из главы 4, но после воссоздания моего PDF-файла с подписью из API компании я получаю следующее.

полученный PDF-файл неправильно подписан

В нем говорится: 1) есть ошибки в форматировании информации 2) личность подписывающего лица не проверена 3) время подписи определяется по часам на компьютере подписавшего.

Теперь что касается подготовки pdf-файла перед его хешированием для отправки на подпись ... Я не вижу ничего в примере ClientSigning, который специально его подготавливает, могу ли я предположить, что библиотека IText подготавливает его под капотом?


person Evan Econo    schedule 11.07.2020    source источник
comment
a) PDF-файл должен быть подготовлен перед хешированием диапазонов байтов, которые будут подписаны (что не весь подготовленный PDF-файл!); b) достаточно ли получить сертификат только вместе с подписью, зависит от формата, в котором возвращается подпись. Если API компании возвращает контейнер подписи CMS, вам не нужен сертификат раньше ; если это обычная подпись, обычно сертификат требуется заранее.   -  person mkl    schedule 11.07.2020
comment
следует ли мне смотреть на PDFBox вместо Itext - вы не указали никаких особых требований для своей подписи (например, вы не упомянули специальный профиль для создания, такой как PAdES-LTA), поэтому подойдет любая библиотека.   -  person mkl    schedule 11.07.2020
comment
github не работает, но у этой женщины есть решения для нескольких библиотек pdf: github.com/crs2195   -  person Tilman Hausherr    schedule 13.07.2020
comment
спасибо mkl, достаточно сказать, что вы являетесь авторитетом в этом деле; Я думаю, что это обычная подпись, которую возвращает API компании ... Я читаю все тексты ... можно ли предположить, что если у меня нет доступа к сертификатам заранее, я бы использовал пример отложенного пения, и если У меня были сертификаты заранее, я бы использовал clientserversigningexample? Другими словами, мне трудно различать эти два ... но я предполагаю, что если API компании возвращает только обычную подпись (с цепочкой сертификатов, заметьте), он заставляет мою руку, и я должен использовать clientseversigningexample?   -  person Evan Econo    schedule 13.07.2020
comment
просто дополнение, у меня есть два сертификата от API компании, root и sub, оба являются файлами .cer. Можно ли предположить, что я могу создать цепочку, используя эти два сертификата, при создании вызова API компании с использованием clientserversigningexample? Как вы думаете, значение цепочки возврата, которое возвращает API компании, отличается?   -  person Evan Econo    schedule 13.07.2020
comment
это только я или в IText7 вы не можете создать экземпляр PDFReader из byteArray, как вы могли бы в ITextSharp .... думаю, они не делают их такими, как раньше ... какое-либо обходное решение?   -  person Evan Econo    schedule 14.07.2020
comment
не может создать экземпляр PDFReader из byteArray - не напрямую. Но вы можете сделать new PdfReader(new RandomAccessSourceFactory().CreateSource(YOUR_BYTE_ARRAY), new ReaderProperties()).   -  person mkl    schedule 14.07.2020
comment
спасибо, чувак, это помогает больше, чем ты думаешь, я думаю, мне нужно знать, следует ли использовать пример clientserversigning, или я должен сделать пример отложенного подписания   -  person Evan Econo    schedule 14.07.2020
comment
какой из них больше подходит?   -  person Evan Econo    schedule 14.07.2020
comment
ну, похоже, я ответил на свой вопрос, возможно ... глядя на примеры c # IText, в примере с отложенной подписью требуется закрытый ключ ICipherParameters pk = pk12.GetKey (alias) .Key; и я знаю, что у меня нет доступа к закрытому ключу, поэтому я буду придерживаться примера подписи клиент-сервер   -  person Evan Econo    schedule 14.07.2020
comment
безопасно ли предположить, что если у меня нет доступа к сертификатам заранее, чем я бы использовал пример отложенного пения, и если бы у меня были сертификаты заранее, я бы использовал clientserversigningexample - Нет. Строго говоря, если только в одном варианте использования не удастся обойтись очень примитивными подписями, сертификат потребуется перед выполнением фактического вызова подписи. Использовать ли отложенное подписание или нет - это другой вопрос. Напишу ответ по этому поводу.   -  person mkl    schedule 14.07.2020
comment
спасибо, парень, я просматриваю ваши обмены с Always Developer в stackoverflow. com / questions / 58486468 / - ›Я заметил в вашем примере, который вы предоставили, он пытается это сделать без сертификата заранее ... Я думаю попробовать это, но с PKCS7, а не с PKCS1 Если нужно, у меня есть предварительно получить доступ к корневым и дополнительным файлам .cer - ›так ли это проще? как ни странно, API компании возвращает 3 сертификата, поэтому я не уверен, в чем заключается несоответствие.   -  person Evan Econo    schedule 14.07.2020
comment
Найдите время, чтобы прочитать Как задать вопрос. Вопросы должны содержать один полный, автономный вопрос, который содержит всю информацию, необходимую для того, чтобы кто-то дал ответ не только вам, но и будущим посетителям сайта, у которых может быть такая же проблема. Любая дополнительная информация, которую вы думаете, должна быть добавлена ​​к вопросу с помощью кнопки редактирования, но она должна относиться к единственный вопрос. Если вы решите это и перейдете к другому вопросу, вам следует поднять его как отдельный вопрос и подумать о том, чтобы принять ответ, который помог вам лучше всего в этом вопросе.   -  person David Buck    schedule 15.07.2020
comment
Не проблема, я редактировал вопрос;   -  person Evan Econo    schedule 15.07.2020


Ответы (1)


В вашем вопросе и в комментариях к нему вы, кажется, особенно заинтересованы в

  • можно ли использовать API подписи, который возвращает сертификаты только вместе с подписью, и
  • когда следует отложить подписание.

Можно ли использовать API подписи, предоставляющий сертификат пользователя только после подписи?

Чтобы ответить на этот вопрос, сначала необходимо уточнить, какие подписи создает рассматриваемый API подписи, простые значения подписи (например, подписи RSA PKCS # 1) или полноценные контейнеры подписи CMS.

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

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

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

Когда использовать отложенное подписание

Разница между отложенной подписью и другими вызовами подписи iText заключается в том, не то, что для отложенной подписи требуется меньше информации (по сравнению с подписью ExternalContainer).

В отличие от других методов подписи iText, signDeferred повторно использует самое внешнее существующее заполненное поле подписи PDF-файла для подписи и просто заменяет контейнер подписи в нем.

Название метода происходит от наиболее распространенного варианта его использования:

  • На первом этапе поле подписи (возможно, сначала создается, а затем) заполняется с использованием signExternalContainer с реализацией IExternalSignatureContainer, которая вычисляет хэш документа для подписи, но еще не возвращает окончательный контейнер CMS, а просто некоторый (обычно) пустой массив. Сгенерированный PDF-файл с заполненным полем подписи (хотя и без окончательного контейнера подписи) затем временно сохраняется (в файловой системе или базе данных).
  • На втором этапе контейнер подписи для определенного хэша документа запрашивается и (возможно, асинхронно) ожидается.
  • На последнем этапе signDeferred используется для вставки полученного контейнера подписи в PDF-файл, подготовленный на первом этапе.

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

person mkl    schedule 14.07.2020
comment
привет, mkl, я не могу вас отблагодарить ... есть ли способ отличить или узнать, является ли возвращенная подпись из API компании простой подписью или полноценным контейнером подписи CMS, проверив / просмотрев подпись base64string, которую он возвращает? могу я сделать обоснованное предположение? - person Evan Econo; 15.07.2020
comment
последовал этому примеру кода ответа ... Я все еще получаю сообщение, подписанное неизвестным / личность подписавшего еще не проверена, ошибка в панели подписи ... Мне интересно, связано ли это как-то с тем, о чем вы говорите: - person Evan Econo; 15.07.2020
comment
Контейнер подписи CMS может содержать структуру подписанных атрибутов. Если это так, один из этих атрибутов должен быть хешем подписанных байтов PDF (см. Выше, все, кроме значения Contents), и фактические байты подписи, заключенные в контейнер, подписывают эти подписанные атрибуты. Допускается ли вариант без подписанных атрибутов и какие атрибуты требуются дополнительно, зависит от точного типа подписи. - person Evan Econo; 15.07.2020
comment
могу я сделать обоснованное предположение? - ну размер уже подсказка. Менее 1 КБ - это, скорее всего, голая подпись. Более 2 КБ - это, скорее всего, большая структура, такая как контейнер подписи CMS. - person mkl; 15.07.2020
comment
ах, в этом случае это похоже на голую подпись ... Я скопировал / вставил полученную подпись, и файл блокнота пришел на 344 байта ... заметьте, это следует за вашим Как создать подпись PDF, не зная подписавшего сертификат рано. - person Evan Econo; 15.07.2020
comment
в вашем примере с AlwaysDeveloper, о котором вы упомянули. Теперь для хэша, рассчитанного выше в переменной Hash, вы можете запросить подпись PKCS # 1 и сертификат подписавшего. ... могу или должен вместо этого запросить PKCS7? Может быть, это натянуто, но я не понимаю, почему что-то не работает - person Evan Econo; 15.07.2020
comment
Если вы можете запросить pkcs7 ... pkcs7 по сути является контейнером подписи cms! - person mkl; 15.07.2020
comment
Я должен был уточнить, моя ошибка была поздней ночью, я почти уверен, что API-интерфейс компании возвращает простую подпись, потому что в его руководстве говорится, что я должен создать объект подписи самостоятельно, а также из-за небольшого размера (~ 350 байт) - возвращает цепочку сертификатов, которая, когда я пробовал, возвращала цепочку из 3 строк подписи, хотя компания заранее предоставила мне 2 файла cer (корень и под), поэтому я не знаю, почему было возвращено 3 - person Evan Econo; 15.07.2020
comment
p.s. Я борюсь ... стоит мне увеличить расчетный размер с 12000? ошибки, которые я получаю в Acrobat, возможно, они намекают, что цепочка сертификатов из API компании не улавливается кодом построения контейнера отсрочки подписи. в стороне, я предполагаю, что контейнер ExternalHashingSignature заботится о подготовке хэша / определяет правильный хэш диапазонов байтов. Я говорю "предположить", потому что не вижу явного вызова getAuthenticatedAttributeBytes? Я вижу возвращаемый новый байт [0] в ExternalHashingSignatureContainer, который по какой-то причине является фиктивным / пустым значением? - person Evan Econo; 15.07.2020
comment
Единственная разница между моим кодом и кодом в примере - это вместо byte [] certificateBytes = THE_RETRIEVED_CERTIFICATE_BYTES; X509Certificate x509Certificate = новый X509CertificateParser (). ReadCertificate (certificateBytes); Я создаю 3 сертификата x509Certificates (по одному на каждую строку в цепочке, возвращаемую API компании. - person Evan Econo; 15.07.2020
comment
похоже, что загадочный 3-й сертификат, который возвращает CompanyAPI, является сертификатом с закрытым ключом, используемым для генерации подписи ... так что у меня есть root, sub и этот третий. должен я или не должен использовать этот третий в коде построения контейнера cms из Как создать подпись PDF, не зная раннего примера сертификата подписавшего - person Evan Econo; 15.07.2020
comment
Скорее всего, третий сертификат является сертификатом подписавшего. В этом случае это сертификат, который вам, в конце концов, нужно заполнить некоторыми деталями. - person mkl; 15.07.2020
comment
ах, ладно, могу ли я использовать этот сертификат исключительно в байте [] certificateBytes = THE_RETRIEVED_CERTIFICATE_BYTES; часть раздела Как создать подпись PDF, не зная в начале примера сертификата подписавшего? Другими словами, я могу забыть о двух других сертификатах (корневом и дополнительном). - person Evan Econo; 15.07.2020
comment
Я бы так предположил. (Вы еще не предоставили никаких примеров данных, поэтому я должен многое догадываться ...) - person mkl; 15.07.2020
comment
:) небольшой проблеск надежды, теперь pdf, хотя все еще имеет ошибку недопустимой подписи, по крайней мере, подбирает правильное имя подписавшего, подписанное им. теперь ошибки следующие: 1) - документ был изменен или поврежден с момента его подписания 2) - личность подписавшего неизвестна, потому что он не был включен в ваш список доверенных сертификатов, и этот раздражающий 3) - время подписи отсчитывается по часам на компьютере подписавшего - person Evan Econo; 15.07.2020
comment
Я знаю, что я уже доверял корневому сертификату и сертификату в моем списке доверенных сертификатов, поэтому, может быть, мне не следует забывать о корневых и дополнительных сертификатах в моем коде, когда он подписывает pdf? - person Evan Econo; 15.07.2020
comment
корневые и вспомогательные сертификаты - поскольку они у вас есть, вы также должны добавить их в контейнер подписи. В коде указанного ответа есть Asn1EncodableVector certs, к которому добавлен сертификат подписывающей стороны x509Certificate (certs.Add(x509Certificate.CertificateStructure.ToAsn1Object())). Просто аналогичным образом добавьте к этому Asn1EncodableVector другие соответствующие сертификаты, которые у вас есть. - person mkl; 15.07.2020
comment
Еще раз хотел поблагодарить mkl, вы были правы, похоже, мне нужен был сертификат подписавшего, а не два других - person Evan Econo; 15.07.2020