Подписание PDF через iText sharp с использованием хэша и подписи из внешнего веб-сервиса
Я пытаюсь подписать PDF через внешний веб-сервис. Веб-служба получает хеш-код в формате SHA-256, а после подписания служба возвращает подпись с шестнадцатеричным дайджестом.
В данный момент я застрял, пытаясь использовать библиотеку iText 7 (C#), пытаясь подписать документ значениями подписи. Мне удалось подписать pdf-документ с помощью itext с использованием локального самоподписанного сертификата, но еще не с внешним контейнером. Adobe Acrobat всегда сообщает о проблемах с декодированием BER, что заставляет меня думать, что что-то идет не так с анализом моя сторона или значения подписи неверны.
Шаги подписи с образцами программного обеспечения следующие:
Сначала добавьте пустую подпись, подпишите этот документ, а затем сгенерируйте хеш (SHA-256).
public static void CalculateHash(Stream fileStream, out byte[] docBytesHash, out byte[] preSignedBytes) { PdfName filter = PdfName.Adobe_PPKLite; PdfName subFilter = PdfName.Adbe_pkcs7_detached; int estimatedSize = 8192; PdfReader reader = new PdfReader(fileStream); MemoryStream baos = new MemoryStream(); PdfSigner signer = new PdfSigner(reader, baos, new StampingProperties()); signer.SetCertificationLevel(PdfSigner.CERTIFIED_NO_CHANGES_ALLOWED); PdfSignatureAppearance appearance = signer.GetSignatureAppearance(); appearance.SetLayer2Text("Signature field which signing is deferred.").SetPageRect(new Rectangle(36, 600, 200, 100)).SetPageNumber(1); signer.SetFieldName("DeferredSignature1"); DigestCalcBlankSigner external = new DigestCalcBlankSigner(filter, subFilter); //IExternalSignatureContainer external = new ExternalBlankSignatureContainer(filter, subFilter); signer.SignExternalContainer(external, estimatedSize); docBytesHash = external.GetDocBytesHash(); preSignedBytes = baos.ToArray(); }
Хеш конвертируется в bytearray и отправляется на веб-сервис
public static string ByteArrayToString(byte[] array) { StringBuilder stringBuilder = new StringBuilder(); foreach (byte b in array) stringBuilder.AppendFormat("{0:x2}", b); return stringBuilder.ToString(); }
Веб-служба отвечает данными подписи на примере данных строки
"473e8e376ca067f3c806902f718be21bf8a788ddbd31786b14fc47678596d6993a4f1ecb80e091f93af4820a75d97aee4b1a15c4a7914b4f881ca86e5d06b429b176d5b663c986c9ce2824333c98e0b5def0af53178b9ce38aa4efaa0adce2eee409487fb7fecf58e4c5bfcc3a0d083e35a83f9c722c73b78784e9990b6f00b89ae4934714c92b34699ce00ad5a662d0058bd613021449e9d09ab2d25376230de75591ab6ce4b5c5d24216794e8c871a690b4e19011621d41c66f4b0048abc9f2d4449072ee9e70c30dcf9b8b5a1ea8ee3a285163c2c5b293a3798a4a13ca59e83c66d9148d519b55e13643a3a7e0794732b92f50c1424f7be5774f67e910076"
Затем строка преобразуется в bytearray с помощью следующей функции
public static byte[] StringToByteArray(String hex) { int NumberChars = hex.Length; byte[] bytes = new byte[NumberChars / 2]; for (int i = 0; i < NumberChars; i += 2) bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); return bytes; }
Контейнер подписи теперь создается с использованием подписи байтового массива, а документ подписывается с использованием контейнера и предварительно подписанных байтов документа.
using (System.IO.FileStream outStream = new System.IO.FileStream(System.IO.Path.GetTempPath() + "tempout.pdf", System.IO.FileMode.Create)) { PdfName filter = PdfName.Adobe_PPKLite; PdfName subFilter = PdfName.Adbe_pkcs7_detached; MemoryStream baos = new MemoryStream(); fileStream.CopyTo(baos); //temp byte[] preSignedBytes = baos.ToArray(); ReadySignatureSigner extSigContainer = new ReadySignatureSigner(StringHelper.StringToByteArray(signature.data.attributes.signature)); //now use external provider signature PdfDocument docToSign = new PdfDocument(new PdfReader(new MemoryStream(preSignedBytes))); PdfSigner.SignDeferred(docToSign, "DeferredSignature1", outStream, extSigContainer); docToSign.Close(); }
Я также добавил исходный PDF, неподписанный PDF и подписанный PDF для ссылки в ссылке ниже. Я надеюсь, что кто-то может взглянуть на содержимое и, возможно, сказать мне, что здесь происходит не так. Я уже много часов провожу в Интернете в поисках решений, но пока ничего не нашел.
С уважением, Йос Эйлерс