Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline kassfb  
#1 Оставлено : 8 августа 2022 г. 13:59:04(UTC)
kassfb

Статус: Участник

Группы: Участники
Зарегистрирован: 12.07.2022(UTC)
Сообщений: 13
Российская Федерация

Сказал(а) «Спасибо»: 2 раз
Прошу помощи! Полученная подпись не действительна (ошибка значения хеша). Пытаюсь реализовать встроенную подпись в PDF. На сервере с помощью iTextSharp создаю тестовый pdf, добавляю в него пустой контейнер для подписи, сохраняю этот pdf как массив байт (pdfWithBlankSignatureContainer), а на клиент отправляю поток, который содержит последовательность, которую хочу подписывать в base64 (bytesToSign).

Код:

        public static byte[] CreatePdf()
        {
            using (MemoryStream ms = new MemoryStream())
            {
                Document document = new Document(PageSize.A4, 25, 25, 30, 30);
                PdfWriter writer = PdfWriter.GetInstance(document, ms);
                document.Open();
                document.Add(new Paragraph("Hello World!"));
                document.Close();
                writer.Close();
                return ms.ToArray();
            }
        }


        public static byte[] GetPdfAndBytesToSign(byte[] unsignedPdf, string signatureFieldName, out byte[] pdfWithBlankSignatureContainer)
        {
            //unsignedPdf - массив байт исходного PDF файла
            using (PdfReader reader = new PdfReader(unsignedPdf))
            {
                using (MemoryStream tempPdf = new MemoryStream())
                {
                    //добавляем пустой контейнер для новой подписи
                    using (PdfStamper st = PdfStamper.CreateSignature(reader, tempPdf, '\0', null, true))
                    {
                        PdfSignatureAppearance appearance = st.SignatureAppearance;
                        appearance.SetVisibleSignature(new Rectangle(205, 700, 390, 800), reader.NumberOfPages, SignatureFieldName);
                        ExternalBlankSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
                        MakeSignature.SignExternalContainer(appearance, external, BufferSize);
                        pdfWithBlankSignatureContainer = tempPdf.ToArray();

                        //получаем поток, который содержит последовательность, которую мы хотим подписывать
                        using (Stream contentStream = appearance.GetRangeStream())
                        {
                            MemoryStream memoryStream = new MemoryStream();
                            contentStream.CopyTo(memoryStream);
                            byte[] bytesToSign = memoryStream.ToArray();
                            return bytesToSign;
                        }
                    }
                }
            }
        }

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

public SignHashAsync(dataToSign, thumbprint) {
    return new Promise<string>(function(resolve, reject) {
      cadesplugin.async_spawn(function*(arg) {
        var oStore;
        try {
          oStore = yield cadesplugin.CreateObjectAsync("CAdESCOM.Store");

          yield oStore.Open(cadesplugin.CAPICOM_CURRENT_USER_STORE, cadesplugin.CAPICOM_MY_STORE, cadesplugin.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);

          var allCertificates = yield oStore.Certificates;

          var oCertificates = yield allCertificates.Find(cadesplugin.CAPICOM_CERTIFICATE_FIND_SHA1_HASH, thumbprint);

          var certificatesCount = yield oCertificates.Count;
          if (certificatesCount === 0) {
            return reject("Сертификат не найден в хранилище.");
          }
          var oCertificate = yield oCertificates.Item(1);

          var oHashedData = yield cadesplugin.CreateObjectAsync("CAdESCOM.HashedData");
          yield oHashedData.propset_Algorithm(cadesplugin.CADESCOM_HASH_ALGORITHM_CP_GOST_3411_2012_256);

          yield oHashedData.propset_DataEncoding = cadesplugin.CADESCOM_BASE64_TO_BINARY;


          yield oHashedData.Hash(dataToSign);

          var oSigner = yield cadesplugin.CreateObjectAsync("CAdESCOM.CPSigner");
          oSigner.propset_Certificate(oCertificate);

          var oCadesSignedData = yield cadesplugin.CreateObjectAsync("CAdESCOM.CadesSignedData");
          oCadesSignedData.propset_ContentEncoding(cadesplugin.CADESCOM_BASE64_TO_BINARY);
          var signatureHex: string = yield oCadesSignedData.SignHash(oHashedData, oSigner, cadesplugin.CADESCOM_CADES_BES);
          debugger;
          return resolve(signatureHex);
        } catch (err) {
          return reject("Не удалось создать подпись. " + (err));
        } finally {
          if (oStore) {
            yield oStore.Close();
          }
        }
      });
    });
  }

На сервере получаю Эту подпись в base64, декодирую в массив байт и iTextSharp'ом встраиваю в PDF с пустым контейнером для подписи, созданный на сервере на первом этапе.
Код:

public static byte[] GetSignedPdf(byte[] unsignedPdfWithContainer, byte[] signature)
        {
            using var pdfReader = new PdfReader(unsignedPdfWithContainer);

            using var output = new MemoryStream();

            var external = new MyExternalSignatureContainer(signature);
            MakeSignature.SignDeferred(pdfReader, SignatureFieldName, output, external);
            return output.ToArray();
        }
        private class MyExternalSignatureContainer : IExternalSignatureContainer
        {
            private readonly byte[] _signedBytes;

            public MyExternalSignatureContainer(byte[] signedBytes)
            {
                this._signedBytes = signedBytes;
            }

            public byte[] Sign(Stream data)
            {
                return this._signedBytes;
            }

            public void ModifySigningDictionary(PdfDictionary signDic)
            {
                throw new NotImplementedException();
            }
        }


Полученный PDF с встроенной подписью передаю на клиента в виде массива байт закодированный в base64, на клиенте сохраняю эту строку, конвертируя base64 в PDF.
Когда проверяю подпись в PDF она не действительная! CryptExpert пишет что ошибка - неправильное значение хеша.
Как надо подписывать хеш на клиенте и нужно ли считать хеш для встроенной подписи в PDF? Может надо подписывать сразу переданные данные без хеша? Что я делаю не так, подскажите, пожалуйстаPray
Offline TolikTipaTut1  
#2 Оставлено : 8 августа 2022 г. 20:57:41(UTC)
TolikTipaTut1

Статус: Активный участник

Группы: Участники
Зарегистрирован: 05.07.2018(UTC)
Сообщений: 467

Сказал(а) «Спасибо»: 43 раз
Поблагодарили: 69 раз в 61 постах
Добрый вечер.

https://github.com/anato...0using%20BouncyCastle.cs

Посмотрите примеры Sample_15_CreatePAdES_usingTables и Sample_15_CreatePAdES
Offline kassfb  
#3 Оставлено : 8 августа 2022 г. 20:58:57(UTC)
kassfb

Статус: Участник

Группы: Участники
Зарегистрирован: 12.07.2022(UTC)
Сообщений: 13
Российская Федерация

Сказал(а) «Спасибо»: 2 раз
Удалось получить валидную подпись. Для этого я дропнул строки с вычислением Хеша и подписывал методом SignCades сразу данные с сервера
Код:

public SignHashAsync(dataToSign, thumbprint) {
    return new Promise<string>(function(resolve, reject) {
      cadesplugin.async_spawn(function*(arg) {
        var oStore;
        try {
          oStore = yield cadesplugin.CreateObjectAsync("CAdESCOM.Store");

          yield oStore.Open(cadesplugin.CAPICOM_CURRENT_USER_STORE, cadesplugin.CAPICOM_MY_STORE, cadesplugin.CAPICOM_STORE_OPEN_MAXIMUM_ALLOWED);

          var allCertificates = yield oStore.Certificates;

          var oCertificates = yield allCertificates.Find(cadesplugin.CAPICOM_CERTIFICATE_FIND_SHA1_HASH, thumbprint);

          var certificatesCount = yield oCertificates.Count;
          if (certificatesCount === 0) {
            return reject("Сертификат не найден в хранилище.");
          }
          var oCertificate = yield oCertificates.Item(1);

          try {
            var oSigner = yield cadesplugin.CreateObjectAsync("CAdESCOM.CPSigner");
            oSigner.propset_Certificate(oCertificate);
          } catch (err) {
            return reject("Не удалось создать Подписчика. " + (err));
          }
          // Подписываю данные base64 с сервера
          var oSignedData = yield cadesplugin.CreateObjectAsync("CAdESCOM.CadesSignedData");
          if (dataToSign) {
              try {
                yield oSignedData.propset_ContentEncoding(cadesplugin.CADESCOM_BASE64_TO_BINARY);
                yield oSignedData.propset_Content(dataToSign);
                var Signature = yield oSignedData.SignCades(oSigner, cadesplugin.CADESCOM_CADES_BES, true);
              } catch (err) {
                return reject("Не удалось создать подпись по данным " + (err));
              }
          }
          return resolve(Signature);
        } catch (err) {
          return reject("Не удалось создать подпись. " + (err));
        } finally {
          if (oStore) {
            yield oStore.Close();
          }
        }
      });
    });
  }

valid signature.jpg (278kb) загружен 7 раз(а).
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.