使用iTextSharp 5.3.3和USB令牌签署PDF

我是iTextSharp(和StackOverFlow)的新手。 我正在尝试使用外部USB令牌在C#中签名PDF。 我尝试使用我从互联网上挖掘的以下代码。

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 certificate:", "", 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); 

问题是我收到一个例外:

 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 certificate, String hashAlgorithm) at WindowsFormsApplication1.PDFSignerHelper.signPdfFile(String sourceDocument, String resultDocument, X509Certificate2 certClient, String reason, String location) InnerException: 

这种方法对我们来说很好(iTextSharp 5.3.3)。 我们使用智能卡和USB令牌(供应商 – 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); 

我已经制作了可以从Windows商店,智能卡或Pfx / P12文件中签署PDF的ac#项目可能是有用的四个你

 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 SecureString GetSecurePin(string PinCode) { SecureString pwd = new SecureString(); 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 string ProviderName = textBox2.Text; string KeyContainerName = textBox3.Text; string PinCode = textBox4.Text; if (PinCode != "") { //if pin code is set then no windows form will popup to ask it SecureString 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 certificate selection in the windows certificate store X509Store store = new X509Store(StoreLocation.CurrentUser); store.Open(OpenFlags.ReadOnly); X509Certificate2 cert = null; //manually chose the certificate 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 certificate in a pfx or a p12 file string PfxFileName = textBox5.Text; string PfxPassword = textBox6.Text; X509Certificate2 cert = new X509Certificate2(PfxFileName, PfxPassword); SignWithThisCert(cert); } private void SignWithThisCert(X509Certificate2 cert) { string SourcePdfFileName = textBox1.Text; string 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"); } } } 

与上面相同的代码但使用证书文件而不是存储来在最后一页上签署PDF文档。

  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); 

复制,粘贴,导入所需的库并继续处理其他内容。