Статус: Активный участник
Группы: Участники
Зарегистрирован: 13.04.2012(UTC) Сообщений: 109
|
Добрый день! Задача по прежнему не решена. Используются следующие версии ПО: Windows 7 Professional 32-bit Visual Studio 2010 .NET Framework 4.0 КриптоПро CSP 3.6 R2 (3.6.6497) КриптоПро .NET 1.0.4583.3 CADESCOM из КриптоПро ЭЦП SDK 1.05.0970 (интеропы взяты отсюда) iTextSharp 5.2.1 пропатченный для КриптоПро Вот код, который я выполняю. Код:
// Подписываем PDF документ
public byte[] SignPdf(byte[] sourcePdf, X509Certificate2 certificate)
{
MemoryStream signedPdfStream = new MemoryStream();
PdfReader reader = new PdfReader(sourcePdf);
PdfStamper stamper = PdfStamper.CreateSignature(reader, signedPdfStream, '\0');
// загружаем сертификат в объект iTextSharp
X509CertificateParser parser = new X509CertificateParser();
Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[] {
parser.ReadCertificate(certificate.RawData)
};
// задаем параметры подписи
PdfName filterName = new PdfName("CryptoPro PDF");
PdfSignatureAppearance sap = stamper.SignatureAppearance;
sap.SetCrypto(null, chain, null, filterName);
sap.SignDate = DateTime.Now;
sap.Reason = "I like to sign";
sap.Location = PdfPKCS7.GetSubjectFields(chain[0]).GetField("L") + ", " + PdfPKCS7.GetSubjectFields(chain[0]).GetField("C");
sap.Contact = PdfPKCS7.GetSubjectFields(chain[0]).GetField("CN") + " <" + PdfPKCS7.GetSubjectFields(chain[0]).GetField("E") + ">";
sap.Acro6Layers = true;
sap.Render = PdfSignatureAppearance.SignatureRender.NameAndDescription;
// создаем подпись
PdfSignature pdfSignature = new PdfSignature(filterName, PdfName.ADBE_PKCS7_DETACHED);
pdfSignature.Date = new PdfDate(sap.SignDate);
pdfSignature.Name = PdfPKCS7.GetSubjectFields(chain[0]).GetField("CN");
pdfSignature.Reason = sap.Reason;
pdfSignature.Location = sap.Location;
pdfSignature.Contact = sap.Contact;
sap.CryptoDictionary = pdfSignature;
// задаем размер буфера подписи
int intCSize = 40000;
Dictionary<PdfName, int> hashtable = new Dictionary<PdfName, int>();
hashtable[PdfName.CONTENTS] = intCSize * 2 + 2;
sap.PreClose(hashtable);
// получаем и копируем контент
Stream rangeStream = sap.GetRangeStream();
MemoryStream contentStream = new MemoryStream();
rangeStream.CopyTo(contentStream);
byte[] content = contentStream.ToArray();
// вычисляем подпись
//byte[] signature = SignWithSimpleEDS(content, certificate); // - вызывается создание обычной подпись
byte[] signature = SignWithAdvancedEDS(content, certificate); // - вызывается создание УЭЦП
// помещаем подпись в документ
byte[] signBuff = new byte[intCSize];
Array.Copy(signature, 0, signBuff, 0, signature.Length);
PdfDictionary dictionary = new PdfDictionary();
dictionary.Put(PdfName.CONTENTS, new PdfString(signBuff).SetHexWriting(true));
sap.Close(dictionary);
byte[] signedPdf = signedPdfStream.ToArray();
return signedPdf;
}
// Вычисляем обычную ЭЦП
public static byte[] SignWithSimpleEDS(byte[] content, X509Certificate2 certificate)
{
byte[] signature = null;
try
{
ContentInfo contentInfo = new ContentInfo(content);
SignedCms signedCms = new SignedCms(contentInfo, true);
CmsSigner cmsSigner = new CmsSigner(certificate);
cmsSigner.IncludeOption = X509IncludeOption.WholeChain;
signedCms.ComputeSignature(cmsSigner, true);
signature = signedCms.Encode();
}
catch (Exception ex)
{
throw ex;
}
return signature;
}
// Вычисляем УЭЦП
public static byte[] SignWithAdvancedEDS(byte[] content, X509Certificate2 certificate)
{
byte[] signature = null;
try
{
string tspServerAddress = @"http://www.cryptopro.ru/tsp/tsp.srf";
CPSigner cps = new CPSigner();
cps.Options = CAPICOM_CERTIFICATE_INCLUDE_OPTION.CAPICOM_CERTIFICATE_INCLUDE_WHOLE_CHAIN;
cps.Certificate = GetCAPICOMCertificate(certificate.Thumbprint);
cps.TSAAddress = tspServerAddress;
CadesSignedData csd = new CadesSignedData();
csd.Content = content;
signature = csd.Sign(cps, true);
// тестовая проверка подписи
CadesSignedData csd2 = new CadesSignedData();
csd2.Content = content;
csd2.Verify(signature, true);
}
catch (Exception ex)
{
throw ex;
}
return signature;
}
// Ищем сертификат
public static ICertificate GetCAPICOMCertificate(string certificateThumbprint)
{
ICertificate cert = null;
certificateThumbprint = certificateThumbprint.Replace(" ", "").ToUpper();
string storeName = "My";
CAPICOM_STORE_LOCATION storeLocation = CAPICOM_STORE_LOCATION.CAPICOM_CURRENT_USER_STORE;
try
{
Store sto = new Store();
sto.Open(storeLocation, storeName, CAPICOM_STORE_OPEN_MODE.CAPICOM_STORE_OPEN_READ_ONLY);
foreach (ICertificate c in sto.Certificates)
{
if ((c.Thumbprint == certificateThumbprint) && (c.HasPrivateKey()) && (c.IsValid().Result))
{
cert = c;
break;
}
}
sto.Close();
}
catch (Exception ex)
{
throw ex;
}
return cert;
}
Если я использую метод SignWithSimpleEDS(), то есть подписываю PDF обычной подписью, то все в порядке. Но если я использую метод SignWithAdvancedEDS(), то есть подписываю PDF с помощтю УЭЦП, то подпись не распознается. Adobe Reader пишет об ошибке подписи (см. скриншот). Если в Adobe Reader принудительно нажать "Validate Signature", то получаю следующий лог валидации: Цитата: Error during signature verification. ASN.1 parsing error: Error encountered while BER decoding:
С помощью dbgView лог также собрать не удалось. Если подпись обычная или если подписывается УЭЦП вручную с помощью КриптоПро PDF в Adobe Reader, то лог пишется. Если подписывать PDF с УЭЦП программно приведенным выше кодом, то нет. Могу предположить, что сама подпись вычисляется нормально (так как в коде есть ее валидация), но вот в PDF вставляется как-то странно. Поэтому Adobe Reader ее не распознает и не хочет или не может провалидировать. То есть, до вызова библиотек КриптоПро дело даже не доходит. Настоятельно прошу помощи в решении данной задачи. Она для нас очень важна и приоритетна. Все лицензии у нас есть, в том числе годовая техническая поддержка.Отредактировано пользователем 30 июля 2012 г. 23:12:06(UTC)
| Причина: Не указана Пользователь avorobev прикрепил следующие файлы:  cadescom2.png (18kb) загружен 269 раз(а).У Вас нет прав для просмотра или загрузки вложений. Попробуйте зарегистрироваться.
|