Signer un PDF avec iTextSharp 5.3.3 et un token USB

Je suis nouveau sur iTextSharp (et StackOverFlow). J’essaie de signer un fichier PDF en C # à l’aide d’un jeton USB externe. J’essaie d’utiliser le code de suivi que j’ai trouvé sur Internet.

Org.BouncyCastle.X509.X509CertificateParser cp = new Org.BouncyCastle.X509.X509CertificateParser(); //Get Sertifiacte X509Certificate2 certClient = null; X509Store st = new X509Store(StoreName.My, StoreLocation.CurrentUser); st.Open(OpenFlags.MaxAllowed); X509Certificate2Collection collection = X509Certificate2UI.SelectFromCollection(st.Certificates, "Please choose certificatee:", "", X509SelectionFlag.SingleSelection); if (collection.Count > 0){ certClient = collection[0]; } st.Close(); //Get Cert Chain IList chain = new List(); X509Chain x509chain = new X509Chain(); x509chain.Build(certClient ); foreach (X509ChainElement x509ChainElement in x509chain.ChainElements){ chain.Add(DotNetUtilities.FromX509Certificate(x509ChainElement.Certificate)); } PdfReader reader = new PdfReader(sourceDocument); FileStream resStream = new FileStream(resultDocument, FileMode.Create, FileAccess.ReadWrite); PdfStamper stamper = PdfStamper.CreateSignature(reader, resStream , '\0', null, true); PdfSignatureAppearance appearance = stamper.SignatureAppearance; appearance.Reason = reason; appearance.Location = location; appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(20, 10, 170, 60), 1, "Signed"); X509Certificate2Signature es = new X509Certificate2Signature(certClient, "SHA-1"); MakeSignature.SignDetached(appearance, es, chain, null, null, null, 0, CryptoStandard.CMS); 

Le problème est que je reçois une exception:

 System.Security.Cryptography.CryptographicException was unhandled Message=Invalid type specified. Source=mscorlib StackTrace: at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr) at System.Security.Cryptography.Utils._GetKeyParameter(SafeKeyHandle hKey, UInt32 paramID) at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle) at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair() at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize) at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey() at iTextSharp.text.pdf.security.X509Certificate2Signature..ctor(X509Certificate2 certificatee, Ssortingng hashAlgorithm) at WindowsFormsApplication1.PDFSignerHelper.signPdfFile(Ssortingng sourceDocument, Ssortingng resultDocument, X509Certificate2 certClient, Ssortingng reason, Ssortingng location) InnerException: 

Cette approche fonctionne bien pour nous (iTextSharp 5.3.3). Nous utilisons une carte à puce et un jeton USB (fournisseur – http://www.author.kiev.ua ):

  X509Store store = new X509Store(StoreLocation.CurrentUser); store.Open(OpenFlags.ReadOnly); X509Certificate2Collection sel = X509Certificate2UI.SelectFromCollection(store.Certificates, null, null, X509SelectionFlag.SingleSelection); X509Certificate2 cert = sel[0]; Org.BouncyCastle.X509.X509CertificateParser cp = new Org.BouncyCastle.X509.X509CertificateParser(); Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[] { cp.ReadCertificate(cert.RawData)}; IExternalSignature externalSignature = new X509Certificate2Signature(cert, "SHA-1"); PdfReader pdfReader = new PdfReader(pathToBasePdf); signedPdf = new FileStream(pathToBasePdf, FileMode.Create); pdfStamper = PdfStamper.CreateSignature(pdfReader, signedPdf, '\0'); PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance; signatureAppearance.SignatureGraphic = Image.GetInstance(pathToSignatureImage); signatureAppearance.SetVisibleSignature(new Rectangle(100, 100, 250, 150), pdfReader.NumberOfPages, "Signature"); signatureAppearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.GRAPHIC_AND_DESCRIPTION; MakeSignature.SignDetached(signatureAppearance, externalSignature, chain, null, null, null, 0, CryptoStandard.CMS); 

J’ai créé un projet qui permet de signer un fichier PDF depuis Windows Store, une carte SmartCard ou un fichier Pfx / P12. Peut-être peut-il vous être utile

 using System; using System.Windows.Forms; using System.IO; using System.Security; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using iTextSharp.text.pdf; using iTextSharp.text.pdf.security; namespace SignPdf { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private SecureSsortingng GetSecurePin(ssortingng PinCode) { SecureSsortingng pwd = new SecureSsortingng(); foreach (var c in PinCode.ToCharArray()) pwd.AppendChar(c); return pwd; } private void button1_Click(object sender, EventArgs e) { //Sign from SmartCard //note : ProviderName and KeyContainerName can be found with the dos command : CertUtil -ScInfo ssortingng ProviderName = textBox2.Text; ssortingng KeyContainerName = textBox3.Text; ssortingng PinCode = textBox4.Text; if (PinCode != "") { //if pin code is set then no windows form will popup to ask it SecureSsortingng pwd = GetSecurePin(PinCode); CspParameters csp = new CspParameters(1, ProviderName, KeyContainerName, new System.Security.AccessControl.CryptoKeySecurity(), pwd); try { RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider(csp); // the pin code will be cached for next access to the smart card } catch (Exception ex) { MessageBox.Show("Crypto error: " + ex.Message); return; } } X509Store store = new X509Store(StoreLocation.CurrentUser); store.Open(OpenFlags.ReadOnly); X509Certificate2 cert = null; if ((ProviderName == "") || (KeyContainerName == "")) { MessageBox.Show("You must set Provider Name and Key Container Name"); return; } foreach (X509Certificate2 cert2 in store.Certificates) { if (cert2.HasPrivateKey) { RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert2.PrivateKey; if (rsa == null) continue; // not smart card cert again if (rsa.CspKeyContainerInfo.HardwareDevice) // sure - smartcard { if ((rsa.CspKeyContainerInfo.KeyContainerName == KeyContainerName) && (rsa.CspKeyContainerInfo.ProviderName == ProviderName)) { //we find it cert = cert2; break; } } } } if (cert == null) { MessageBox.Show("Certificate not found"); return; } SignWithThisCert(cert); } private void button2_Click(object sender, EventArgs e) { //Sign with certificatee selection in the windows certificatee store X509Store store = new X509Store(StoreLocation.CurrentUser); store.Open(OpenFlags.ReadOnly); X509Certificate2 cert = null; //manually chose the certificatee in the store X509Certificate2Collection sel = X509Certificate2UI.SelectFromCollection(store.Certificates, null, null, X509SelectionFlag.SingleSelection); if (sel.Count > 0) cert = sel[0]; else { MessageBox.Show("Certificate not found"); return; } SignWithThisCert(cert); } private void button3_Click(object sender, EventArgs e) { //Sign from certificatee in a pfx or a p12 file ssortingng PfxFileName = textBox5.Text; ssortingng PfxPassword = textBox6.Text; X509Certificate2 cert = new X509Certificate2(PfxFileName, PfxPassword); SignWithThisCert(cert); } private void SignWithThisCert(X509Certificate2 cert) { ssortingng SourcePdfFileName = textBox1.Text; ssortingng DestPdfFileName = textBox1.Text + "-Signed.pdf"; Org.BouncyCastle.X509.X509CertificateParser cp = new Org.BouncyCastle.X509.X509CertificateParser(); Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[] { cp.ReadCertificate(cert.RawData) }; IExternalSignature externalSignature = new X509Certificate2Signature(cert, "SHA-1"); PdfReader pdfReader = new PdfReader(SourcePdfFileName); FileStream signedPdf = new FileStream(DestPdfFileName, FileMode.Create); //the output pdf file PdfStamper pdfStamper = PdfStamper.CreateSignature(pdfReader, signedPdf, '\0'); PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance; //here set signatureAppearance at your will signatureAppearance.Reason = "Because I can"; signatureAppearance.Location = "My location"; signatureAppearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.DESCRIPTION; MakeSignature.SignDetached(signatureAppearance, externalSignature, chain, null, null, null, 0, CryptoStandard.CMS); //MakeSignature.SignDetached(signatureAppearance, externalSignature, chain, null, null, null, 0, CryptoStandard.CADES); MessageBox.Show("Done"); } } } 

Le même code que ci-dessus mais utilise un fichier de certificate au lieu de magasin pour signer un document PDF sur la dernière page.

  X509Certificate2 cert = new X509Certificate2("C:\\mycert.p12"); Org.BouncyCastle.X509.X509CertificateParser cp = new Org.BouncyCastle.X509.X509CertificateParser(); Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[] { cp.ReadCertificate(cert.RawData)}; IExternalSignature externalSignature = new X509Certificate2Signature(cert, "SHA-1"); PdfReader pdfReader = new PdfReader("C:\\multi-page-pdf.pdf"); var signedPdf = new FileStream("C:\\multi-page-pdf-signed.pdf", FileMode.Create); var pdfStamper = PdfStamper.CreateSignature(pdfReader, signedPdf, '\0'); PdfSignatureAppearance signatureAppearance = pdfStamper.SignatureAppearance; signatureAppearance.SignatureGraphic = Image.GetInstance("C:\\logo.png"); signatureAppearance.Reason = "Because I can"; signatureAppearance.Location = "My location"; signatureAppearance.SetVisibleSignature(new Rectangle(100, 100, 250, 150), pdfReader.NumberOfPages, "Signature"); signatureAppearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.GRAPHIC_AND_DESCRIPTION; MakeSignature.SignDetached(signatureAppearance, externalSignature, chain, null, null, null, 0, CryptoStandard.CMS); 

Copiez, collez, importez les bibliothèques nécessaires et allez travailler sur autre chose.