using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using iTextSharp.text.pdf;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;

namespace PdfSignerTest
{
     class Program
     {
         static void Main(string[] args)
         {
             try
             {
                 Console.WriteLine("Start");

                 string inputFileName = @"..\..\..\Report.pdf";
                 string outputFileName = @"..\..\..\Signed.pdf";
                 string timeStampUrl = "http://www.xxxx.com/timestamp.cgi";;

                 using (FileStream inputPdfStream = new  
FileStream(inputFileName, FileMode.Open, FileAccess.Read))
                 {
                     using (FileStream outputPdfStream = new  
FileStream(outputFileName, FileMode.Create, FileAccess.Write))
                     {
                         X509Certificate2 card = SelectCertificate();

                         SignPdf(card, inputPdfStream,  
outputPdfStream, false, "Test Reason", "Test Location", "Test  
Contact", timeStampUrl, "teszt", "teszt");
                     }
                 }
             }
             catch (Exception ex)
             {
                 Console.WriteLine(ex.ToString());
             }
             finally
             {
                 Console.WriteLine("Done.");
                 Console.ReadLine();
             }
         }

         /// <summary>
         ///
         /// </summary>
         /// <param name="certificate">smart card certificate</param>
         /// <param name="inputPdfStream">input PDF</param>
         /// <param name="outputPdfStream">output PDF (signed)</param>
         /// <param name="append">append if <CODE>true</CODE> the  
signature and all the other content will be added as a new revision  
thus not invalidating existing signature</param>
         /// <param name="reason">Reason field of signature</param>
         /// <param name="location">Location field of signature</param>
         /// <param name="contact">Contact field of signature</param>
         /// <param name="tsaClientUrl">Timestamp server URL</param>
         /// <param name="tsaClientLogin">Login user for timestamp  
server (BASIC authentication)</param>
         /// <param name="tsaClientPwd">Login password for timestamp  
server</param>
         public static void SignPdf(X509Certificate2 certificate,  
Stream inputPdfStream, Stream outputPdfStream, bool append, string  
reason, string location, string contact, string tsaClientUrl, string  
tsaClientLogin, string tsaClientPwd)
         {
             // Building certificate chain for the OCSP verification
             X509Chain ch = new X509Chain();
             ch.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
             ch.Build(certificate);

             Org.BouncyCastle.X509.X509Certificate[] chain = new  
Org.BouncyCastle.X509.X509Certificate[ch.ChainElements.Count];
             Org.BouncyCastle.X509.X509CertificateParser cp = new  
Org.BouncyCastle.X509.X509CertificateParser();
             int i = 0;

             foreach (X509ChainElement element in ch.ChainElements)
             {
                 Org.BouncyCastle.X509.X509Certificate chainElement =  
cp.ReadCertificate(element.Certificate.RawData);
                 chain[i] = chainElement;
                 i++;
             }

             //Org.BouncyCastle.X509.X509CertificateParser cp = new  
Org.BouncyCastle.X509.X509CertificateParser();
             //Org.BouncyCastle.X509.X509Certificate[] chain = new  
Org.BouncyCastle.X509.X509Certificate[] {  
cp.ReadCertificate(certificate.RawData) };

             PdfReader reader = new PdfReader(inputPdfStream);
             PdfStamper st = PdfStamper.CreateSignature(reader,  
outputPdfStream, '\0', null, append);
             PdfSignatureAppearance sap = st.SignatureAppearance;

             sap.SetCrypto(null, chain, null,  
PdfSignatureAppearance.SELF_SIGNED);

             sap.Reason = reason;
             sap.Contact = contact;
             sap.Location = location;

             sap.SetVisibleSignature(new iTextSharp.text.Rectangle(50,  
50, 200, 100), 1, null);

             PdfSignature dic = new  
PdfSignature(PdfName.ADOBE_PPKLITE, new PdfName("adbe.pkcs7.detached"));
             dic.Reason = sap.Reason;
             dic.Location = sap.Location;
             dic.Contact = sap.Contact;
             dic.Date = new PdfDate(sap.SignDate);
             sap.CryptoDictionary = dic;

             int contentEstimated = 15000;

             Dictionary<PdfName, int> exc = new Dictionary<PdfName, int>();
             exc[PdfName.CONTENTS] = contentEstimated * 2 + 2;
             sap.PreClose(exc);

             PdfPKCS7 sgn = new PdfPKCS7(null, chain, null, "SHA1", false);
             IDigest messageDigest = DigestUtilities.GetDigest("SHA1");
             Stream data = sap.RangeStream;
             byte[] buf = new byte[8192];
             int n;
             while ((n = data.Read(buf, 0, buf.Length)) > 0)
             {
                 messageDigest.BlockUpdate(buf, 0, n);
             }
             byte[] hash = new byte[messageDigest.GetDigestSize()];
             messageDigest.DoFinal(hash, 0);
             DateTime cal = DateTime.Now;
             byte[] ocsp = null;
             if (chain.Length >= 2)
             {
                 String url = PdfPKCS7.GetOCSPURL(chain[0]);
                 if (url != null && url.Length > 0)
                     ocsp = new OcspClientBouncyCastle(chain[0],  
chain[1], url).GetEncoded();

                 //File.WriteAllBytes(@"..\..\..\ocsp.pdf", ocsp);
             }
             byte[] sh = sgn.GetAuthenticatedAttributeBytes(hash, cal, ocsp);

             // SHA1withRSA calculated by CAPI
             byte[] signedHashValue = SignSHA1withRSA(certificate, sh);
             sgn.SetExternalDigest(signedHashValue, hash, "RSA");

             byte[] paddedSig = new byte[contentEstimated];

             if (!string.IsNullOrEmpty(tsaClientUrl))
             {
                 TSAClientBouncyCastle tsc = new  
TSAClientBouncyCastle(tsaClientUrl, tsaClientLogin, tsaClientPwd);
                 byte[] encodedSigTsa = sgn.GetEncodedPKCS7(hash, cal,  
tsc, ocsp);
                 System.Array.Copy(encodedSigTsa, 0, paddedSig, 0,  
encodedSigTsa.Length);
                 if (contentEstimated + 2 < encodedSigTsa.Length)
                     throw new ApplicationException("Not enough space  
for signature");
             }
             else
             {
                 byte[] encodedSig = sgn.GetEncodedPKCS7(hash, cal,  
null, ocsp);
                 System.Array.Copy(encodedSig, 0, paddedSig, 0,  
encodedSig.Length);
                 if (contentEstimated + 2 < encodedSig.Length)
                     throw new ApplicationException("Not enough space  
for signature");
             }

             PdfDictionary dic2 = new PdfDictionary();
             dic2.Put(PdfName.CONTENTS, new  
PdfString(paddedSig).SetHexWriting(true));
             sap.Close(dic2);
         }

         public static byte[] SignSHA1withRSA(X509Certificate2  
certificate, byte[] input)
         {
             const Int32 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG = 0x00000002;
             const Int32 CRYPT_ACQUIRE_COMPARE_KEY_FLAG = 0x00000004;

             IntPtr privateKeyHandle = IntPtr.Zero;
             bool isCallerNeedFreeKeyHandle = false;
             IntPtr hashHandle = IntPtr.Zero;
             byte[] result = null;

             try
             {
                 IntPtr cardHandle = certificate.Handle;
                 Int32 pdwKeySpec = Crypto.AT_SIGNATURE;

                 if  
(!Crypto.CryptAcquireCertificatePrivateKey(cardHandle,  
CRYPT_ACQUIRE_USE_PROV_INFO_FLAG |
                                                       
CRYPT_ACQUIRE_COMPARE_KEY_FLAG, IntPtr.Zero, ref privateKeyHandle, ref  
pdwKeySpec, ref isCallerNeedFreeKeyHandle))
                 {
                     throw new  
CryptographicException(Marshal.GetLastWin32Error());
                 }

                 if (!Crypto.CryptCreateHash(privateKeyHandle,  
Crypto.CALG_SHA1, IntPtr.Zero, 0, ref hashHandle))
                 {
                     throw new  
CryptographicException(Marshal.GetLastWin32Error());
                 }

                 MemoryStream streamInput = new MemoryStream(input);
                 byte[] buffer = new byte[4096];

                 while (true)
                 {
                     int read = streamInput.Read(buffer, 0, buffer.Length);

                     if (read == 0)
                         break;

                     if (!Crypto.CryptHashData(hashHandle, buffer, read, 0))
                     {
                         throw new  
CryptographicException(Marshal.GetLastWin32Error());
                     }
                 }

                 int pwdSigLen = 0;
                 if (!Crypto.CryptSignHash(hashHandle, pdwKeySpec,  
null, 0, null, ref pwdSigLen))
                 {
                     throw new  
CryptographicException(Marshal.GetLastWin32Error());
                 }

                 result = new byte[pwdSigLen];

                 if (!Crypto.CryptSignHash(hashHandle, pdwKeySpec,  
null, 0, result, ref pwdSigLen))
                 {
                     throw new  
CryptographicException(Marshal.GetLastWin32Error());
                 }

                 // CAPI generated hash has a different indian order
                 Array.Reverse(result);
             }
             finally
             {

                 if (hashHandle != IntPtr.Zero)
                 {
                     if (!Crypto.CryptDestroyHash(hashHandle))
                     {
                         throw new  
CryptographicException(Marshal.GetLastWin32Error());
                     }
                 }

                 if (isCallerNeedFreeKeyHandle && privateKeyHandle !=  
IntPtr.Zero)
                 {
                     if (!Crypto.CryptReleaseContext(privateKeyHandle, 0))
                     {
                         throw new  
CryptographicException(Marshal.GetLastWin32Error());
                     }
                 }
             }

             return result;

         }

         public static X509Certificate2 SelectCertificate()
         {
             X509Store st = new X509Store(StoreName.My,  
StoreLocation.CurrentUser);
             st.Open(OpenFlags.ReadOnly);
             X509Certificate2Collection col =  
st.Certificates.Find(X509FindType.FindByKeyUsage,  
X509KeyUsageFlags.NonRepudiation, true);

             X509Certificate2 card = null;
             X509Certificate2Collection sel =  
X509Certificate2UI.SelectFromCollection(col, "Certificates", "Select  
one to sign", X509SelectionFlag.SingleSelection);
             if (sel.Count > 0)
             {
                 X509Certificate2Enumerator en = sel.GetEnumerator();
                 en.MoveNext();
                 card = en.Current;
             }
             st.Close();
             return card;
         }
     }
}


This is a working code, but unfortunatly copied from a Hungarian blog:
http://gubus2.wordpress.com/2010/09/01/elektronikus-alairas-keszitese-pdf-allomanyra-smart-card-tamogatassal-net-alatt/



------------------------------------------------------------------------------
Virtualization & Cloud Management Using Capacity Planning
Cloud computing makes use of virtualization - but cloud computing 
also focuses on allowing computing to be delivered as a service.
http://www.accelacomm.com/jaw/sfnl/114/51521223/
_______________________________________________
iText-questions mailing list
iText-questions@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/itext-questions

iText(R) is a registered trademark of 1T3XT BVBA.
Many questions posted to this list can (and will) be answered with a reference 
to the iText book: http://www.itextpdf.com/book/
Please check the keywords list before you ask for examples: 
http://itextpdf.com/themes/keywords.php

Reply via email to