2012-11-03 1 views
5

Ich bin neu bei iTextSharp (und StackOverFlow). Ich versuche, ein PDF in C# mit einem externen USB-Token zu signieren. Ich versuche, den folgenden Code zu verwenden, den ich aus dem Internet gegraben habe.Signiere PDF mit iTextSharp 5.3.3 und USB Token

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<Org.BouncyCastle.X509.X509Certificate> chain = new List<Org.BouncyCastle.X509.X509Certificate>(); 
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); 

Das Problem ist, dass ich eine Ausnahme an:

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: 
+0

So, jetzt ich iTextSharp zurück 5.2.1 und verwenden Sie die Beispiele von http://itextpdf.sourceforge.net/howtosign.html#signextdic. Sie machen die Arbeit für mich. Wenn jemand eine Lösung für iTextSHarp 5.3.3 findet, werde ich mich freuen, sie zu sehen. –

Antwort

7

Dieser Ansatz funktioniert gut für uns (iTextSharp 5.3.3). Wir verwenden Smart-Card und USB-Token (Vendor - 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); 
+0

Gibt es Fälle, in denen Zertifikate von eingesteckten USB-Tokens auf diese Weise nicht aufgeführt sind? Weil das Zertifikat meines Tokens mit diesem Code nicht aufgelistet ist, während Acrobat * es auflistet. Obwohl Acrobat ein "Das Schlüsselset ist nicht definiert" meldet. Fehler beim Versuch, damit zu unterschreiben ... – user2173353

+0

Macht nichts. Es scheint, dass Acrobat die Zertifikate irgendwann in meinen lokalen Laden importiert hat und sie von dort aus angesehen hat. Das USB-Token kann nun nicht mehr zugegriffen werden. Mit meiner Middleware/meinem Treiber ist das nicht in Ordnung ... Wie verkaufen diese Firmen diese Dinge? Ich habe Tage damit verbracht, nach den richtigen Treiberversionen zu suchen ... :( – user2173353

+0

@ user2173353 in unserem Fall hatten wir kein Problem) Beispiele, Treiber, Support) Dank der Herstellung – Sasha

3

Der gleiche Code wie oben, jedoch verwendet eine Zertifikatsdatei statt Speicher ein PDF-Dokument auf der letzten Seite zu unterzeichnen.

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

Kopieren, einfügen, importieren Sie benötigte Bibliotheken und arbeiten an etwas anderem.

5

Ich habe eine C# Projekt gemacht, das eine PDF aus den Fenstern zu speichern, Smartcard oder einer Pfx/P12-Datei signieren kann Vielleicht ist es nützlich vier sein können Sie

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

    } 


} 
+0

Danke Jean-Luc. Ich bin mit meinem Projekt fertig, aber ich werde Ihren Code in der zukünftigen Entwicklung berücksichtigen. –

+0

Sehr gut geschriebene Methoden und Antwort. –

Verwandte Themen