Я использую шестнадцатеричное кодирование байтовых массивов здесь.Ваш хэш в кодировке base64
klh6CGp7DUzayt62Eusiqjr1BFCcTZT4XdgnMBq7QeY=
в шестнадцатеричной кодировке равен
92587A086A7B0D4CDACADEB612EB22AA3AF504509C4D94F85DD827301ABB41E6
Короче
Ваш код хеширует подписанныйАтрибуты дважды.Просто не хэшируйте байты, возвращаемые signatureContainer.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CMS)
в GetHashOfPdf
, а вместо этого используйте сами байты атрибута в качестве возвращаемого значения.
Подробно
Анализ подписи в вашем примере PDF этополучается, что
действительно хэш подписанных атрибутов равен
92587A086A7B0D4CDACADEB612EB22AA3AF504509C4D94F85DD827301ABB41E6
, но хеш в зашифрованном RSA DigestInfo
объектеподпись
1DC7CAA50D88243327A9D928D5FB4F1A61CBEFF9E947D393DDA705BD61B67F25
, которая оказывается хэшем вышеупомянутого хэша подписанных атрибутов.
Таким образом, ваш
var signature = signer.sign(toBeSignedHash);
вызов, кажется, снова хэширует значение toBeSignedHash
.
Самое простое решение - заменить
byte[] signatureHash = signatureContainer.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CMS);
result = DigestAlgorithms.Digest(new MemoryStream(signatureHash), "SHA256");
на
result = signatureContainer.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CMS);
в GetHashOfPdf
только для хеширования signer.sign
.
Анализ таких проблем
В комментарии вы спросили
как вы это выясниливсе это:)?
Ну, это не первый вопрос с настраиваемым процессом подписывания iText, приводящим к ошибкам илипо крайней мере нежелательные профили.
В ходе анализа этих вопросов первым шагом обычно является извлечение встроенного контейнера подписи и проверка его в средстве просмотра ASN.1.
В случаеВаш PDF, основной результат этой проверки состоял в том, что подпись как таковая выглядела нормально, и что ваши подписанные атрибуты не содержат никаких переменных данных.
Если были некоторые переменные данные (например,атрибут времени подписи), кандидатом для причины проблемы было бы то, что вы создали дважды подписанные атрибуты, один раз явно в GetHashOfPdf
, один раз неявно в EmbedSignature
, с различными значениями для переменных данных.Но, как упоминалось выше, это был не тот случай.
Следующим шагом здесь была проверка задействованных хэшей.Проверка хеша документа проста: вычисляется хэш диапазона байтов со знаком и сравнивается со значением атрибута со знаком MessageDigest
, ср. ExtractHash test testSotnSignedpdf
(на Java).
Результат для вашего PDF оказался нормальным.
Следующим шагом была более тщательная проверка контейнера подписи.В этом контексте я однажды начал писать некоторые проверки, но не очень далеко, ср. SignatureAnalyzer класс.Я немного расширил его для проверки хэша подписанных атрибутов, используя алгоритм подписи, который вы использовали, старый RSASSA-PKCS1-v1_5 : в отличие от многих других алгоритмов подписи, этот позволяеттривиально извлечь подписанный хеш.
Здесь результат для вашего PDF оказался не в порядке, хэш подписанных атрибутов отличался от подписанного хеша.
Здесь есть две часто встречающиеся причины несоответствия:
либо подписанные атрибуты подписаны с неправильной кодировкой (это должна быть обычная кодировка DER, а не какая-то произвольная)Кодировка BER и, в частности, не кодировка с неявным тегом, который имеет значение, хранящееся в сигнатуре - даже крупные игроки иногда делают это неправильно, например, Docusign, ср. DSS-1343 )
или хэш каким-то образом трансформировался во время подписи (например, хэш был закодирован или снова хеширован в base64).
Как оказалось,последний случай был здесь, хеш был снова хеширован.