CryptoPro

Sign PDF using .NET and iText

Apr 20th, 2012
851
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.47 KB | None | 0 0
  1. using System;
  2. using System.Security.Cryptography.X509Certificates;
  3. using System.Collections.Generic;
  4. using System.Security.Cryptography;
  5. using System.Security;
  6.  
  7. #if PDF_SIGNATURE_ENABLED
  8. namespace Simple35.Pdf
  9. {
  10.     using iTextSharp.text.pdf;
  11.     using System.IO;
  12.     using Org.BouncyCastle.X509;
  13.     using System.Security.Cryptography.Pkcs;
  14.     using CryptoPro.Sharpei;
  15.     /// <summary>
  16.     /// Для сборки примера необходимо установить последнюю версию iTextSharp и определить переменную PDF_SIGNATURE_ENABLED
  17.     /// </summary>
  18.     public class Sign
  19.     {        
  20.         [STAThread]
  21.         public static int Main(string[] args)
  22.         {
  23.             // Разбираем аргументы
  24.             if (args.Length < 2)
  25.             {
  26.                 Console.WriteLine("Pdf.Sign <document> <certificate-dn> [<key-container-password>]");
  27.                 return 1;
  28.             }
  29.             string document = args[0];
  30.             string certificate_dn = args[1];
  31.  
  32.  
  33.             // Находим секретный ключ по сертификату в хранилище MY
  34.             X509Store store = new X509Store("My", StoreLocation.CurrentUser);
  35.             store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
  36.             X509Certificate2Collection found = store.Certificates.Find(
  37.                 X509FindType.FindBySubjectName, certificate_dn, true);
  38.             if (found.Count == 0)
  39.             {
  40.                 Console.WriteLine("Секретный ключ не найден.");
  41.                 return 1;
  42.             }
  43.             if (found.Count > 1)
  44.             {
  45.                 Console.WriteLine("Найдено более одного секретного ключа.");
  46.                 return 1;
  47.             }
  48.             X509Certificate2 certificate = found[0];
  49.  
  50.             if (args.Length > 2)
  51.             {
  52.                 //set password.
  53.                 Gost3410CryptoServiceProvider cert_key = certificate.PrivateKey as Gost3410CryptoServiceProvider;
  54.                 if (null != cert_key)
  55.                 {
  56.                     var cspParameters = new CspParameters();
  57.                     //копируем параметры csp из исходного контекста сертификата
  58.                     cspParameters.KeyContainerName = cert_key.CspKeyContainerInfo.KeyContainerName;
  59.                     cspParameters.ProviderType = cert_key.CspKeyContainerInfo.ProviderType;
  60.                     cspParameters.ProviderName = cert_key.CspKeyContainerInfo.ProviderName;
  61.                     cspParameters.Flags = cert_key.CspKeyContainerInfo.MachineKeyStore
  62.                                       ? (CspProviderFlags.UseExistingKey|CspProviderFlags.UseMachineKeyStore)
  63.                                       : (CspProviderFlags.UseExistingKey);
  64.                     cspParameters.KeyPassword = new SecureString();
  65.                     foreach (var c in args[2])
  66.                     {
  67.                         cspParameters.KeyPassword.AppendChar(c);
  68.                     }
  69.                     //создаем новый контекст сертификат, поскольку исходный открыт readonly
  70.                     certificate = new X509Certificate2(certificate.RawData);
  71.                     //задаем криптопровайдер с установленным паролем
  72.                     certificate.PrivateKey = new Gost3410CryptoServiceProvider(cspParameters);
  73.                 }
  74.             }
  75.  
  76.             PdfReader reader = new PdfReader(document);
  77.             PdfStamper st = PdfStamper.CreateSignature(reader, new FileStream(document + "_signed.pdf", FileMode.Create, FileAccess.Write), '\0');                        
  78.             PdfSignatureAppearance sap = st.SignatureAppearance;
  79.  
  80.             // Загружаем сертификат в объект iTextSharp
  81.             X509CertificateParser parser = new X509CertificateParser();
  82.             Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[] {
  83.                 parser.ReadCertificate(certificate.RawData)
  84.             };
  85.  
  86.             sap.SetCrypto(null, chain, null, null);
  87.             sap.Reason = "I like to sign";
  88.             sap.Location = "Universe";
  89.             sap.Acro6Layers = true;
  90.             sap.Render = PdfSignatureAppearance.SignatureRender.NameAndDescription;
  91.             sap.SignDate = DateTime.Now;
  92.  
  93.             // Выбираем подходящий тип фильтра
  94.             PdfName filterName = new PdfName("CryptoPro PDF");
  95.  
  96.             // Создаем подпись
  97.             PdfSignature dic = new PdfSignature(filterName, PdfName.ADBE_PKCS7_DETACHED);
  98.             dic.Date = new PdfDate(sap.SignDate);
  99.             dic.Name = PdfPKCS7.GetSubjectFields(chain[0]).GetField("CN");
  100.             if (sap.Reason != null)
  101.                 dic.Reason = sap.Reason;
  102.             if (sap.Location != null)
  103.                 dic.Location = sap.Location;
  104.             sap.CryptoDictionary = dic;
  105.  
  106.             int intCSize = 4000;
  107.             Dictionary<PdfName, int> hashtable = new Dictionary<PdfName, int>();
  108.             hashtable[PdfName.CONTENTS] = intCSize * 2 + 2;
  109.             sap.PreClose(hashtable);
  110.             Stream s = sap.RangeStream;
  111.             MemoryStream ss = new MemoryStream();
  112.             int read = 0;
  113.             byte[] buff = new byte[8192];
  114.             while ((read = s.Read(buff, 0, 8192)) > 0)
  115.             {
  116.                 ss.Write(buff, 0, read);
  117.             }
  118.  
  119.             // Вычисляем подпись
  120.             ContentInfo contentInfo = new ContentInfo(ss.ToArray());
  121.             SignedCms signedCms = new SignedCms(contentInfo, true);
  122.             CmsSigner cmsSigner = new CmsSigner(certificate);
  123.             signedCms.ComputeSignature(cmsSigner, false);
  124.             byte[] pk = signedCms.Encode();
  125.  
  126.             // Помещаем подпись в документ
  127.             byte[] outc = new byte[intCSize];
  128.             PdfDictionary dic2 = new PdfDictionary();
  129.             Array.Copy(pk, 0, outc, 0, pk.Length);
  130.             dic2.Put(PdfName.CONTENTS, new PdfString(outc).SetHexWriting(true));
  131.             sap.Close(dic2);
  132.  
  133.             Console.WriteLine("Документ {0} успешно подписан на ключе {1} => {2}.",
  134.                 document, certificate.Subject, document + "_signed.pdf");
  135.             return 0;
  136.         }
  137.     }
  138. }
  139. #endif
Advertisement
Add Comment
Please, Sign In to add comment