Сравнение подписанного PDF файла с неподписанным PDF файлом с использованием хеша документа

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

Это принципиально то, что я считаю, что я должен быть в состоянии сделать в принципе, и я надеюсь, что iTextSharp позволит мне:

Я пишу на С# и .NET и используя iTextSharp для анализа файлов PDF. У меня есть файл unsigned PDF, а также подписанная версия того же файла.

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

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

В настоящее время я не знаю, как это сделать! то есть:.

  • Как извлечь данные PDF из подписанного PDF, исключая подпись?
  • Альтернативно, как мне создать хэш из неподписанного PDF?
  • Наряду с 2. как извлечь дешифрованный хэш из подписи PDF?

Надеюсь, это ясно, и я никуда не упустил!

Ответ 1

Об этом:

"Это потому, что я не только хочу проверить, что подписанный PDF файл аутентичным, но также и тем, что он имеет тот же неподписанный PDF, что у меня есть запись"

Предполагая, что вы просто хотите знать, что документ, который вы получаете на своем сервере, является подлинным:

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

Стоит отметить, что существуют два типа подписей PDF, подписей о подписке и подписей на сертификацию. Из документа Цифровые подписи в PDF из Adobe:

Подписи подписи

(...), где кто-то подписывает документ для показа согласия, одобрения или принятия. Сертифицированный документ - это документ, подпись сертификата, поданная инициатором, когда документ готова к использованию. Создатель указывает, какие изменения разрешены; выбирая один из трех разрешенных модификаций:

  • без изменений
  • только заполнение формы
  • заполнение формы и комментирование

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

Для идентификации документа я бы посоветовал разобраться с ним отдельно. Как только документ можно открыть, может быть создан хеш (например, md5) из конкатенации распакованного содержимого всех его страниц, а затем сравнить его с другим похожим хешем из исходного документа (который может быть сгенерирован один раз и сохранен в базе данных).

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

Если вы используете iText, вы можете получить массив байтов содержимого страницы, используя метод PdfReader.getPageContent и использовать результат для вычисления хеша MD5.

Код в Java может выглядеть следующим образом:

PdfReader reader = new PdfReader("myfile.pdf");
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
int pageCount = reader.getNumberOfPages(); 
for(int i=1;i <= pageCount; i++)
{
     byte[] buf = reader.getPageContent(i);
     messageDigest.update(buf, 0, buf.length);
}
byte[] hash = messageDigest.digest();

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

Из спецификации PDF (выделенные жирным шрифтом в моей учетной записи):

Подписи создаются путем вычисления дайджеста данных (или части данные) в документе и сохранение дайджеста в документе. (...) Существует два определенных метода вычисления воспроизводимого дайджеста содержимое всего или части файла PDF:

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

-Объектный дайджест (PDF 1.5) вычисляется с помощью выборочно, ходя по поддереву объектов в памяти, начиная с ссылочного объекта, который обычно является корневым объектом. Полученный в результате дайджест вместе с информация о том, как она была вычислена, помещена в подпись справочный словарь (...).

Ответ 2

Стратегия проверки целостности подписанного PDF:

  • Не отправляйте неподписанный PDF файл в первую очередь. Используя iText (версия Java для приложений, совместимых с Linux), подпишите certify документ с помощью CERTIFIED_FORM_FILLING.

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

  • Проверяйте как сигнатуры, так и документацию.

Вы должны иметь возможность выяснить, как это сделать в документации iText: http://itextpdf.sourceforge.net/howtosign.html

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

Чтобы получить название из pdf для сравнения с помощью iText, вы просто используете этот код:

PdfReader reader = new PdfReader("AsignedPDF.pdf");
string s = reader.Info["Title"];