2012-11-03 12 views
5

Jestem nowy w iTextSharp (i StackOverFlow). Próbuję podpisać plik PDF w języku C# za pomocą zewnętrznego tokena USB. Próbuję użyć następującego kodu, który wykopałem z internetu.Zarejestruj PDF z iTextSharp 5.3.3 i tokenem USB

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

Problemem jest to, że otrzymuję wyjątek:

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

Więc teraz wrócę do iTextSharp 5.2.1 i użyj przykładów z http://itextpdf.sourceforge.net/howtosign.html#signextdic. Wykonują za mnie to zadanie. Jeśli ktoś znajdzie rozwiązanie dla iTextSHarp 5.3.3, z przyjemnością go zobaczę. –

Odpowiedz

7

Podejście to działa dobrze dla nas (iTextSharp 5.3.3). Używamy smart-karty i USB token (sprzedawca - 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

Czy są jakieś certyfikaty przypadków z podłączonych tokenów USB nie są wymienione podczas korzystania z tej metody? Ponieważ certyfikat mojego tokena nie znajduje się na liście przy użyciu tego kodu, a program Acrobat * go * wymienia. Chociaż program Acrobat zgłasza "Zestaw kluczy nie został zdefiniowany." błąd podczas próby podpisania z nim ... – user2173353

+0

Nieważne. Wygląda na to, że w pewnym momencie program Acrobat zaimportował certyfikaty do mojego lokalnego sklepu i przeglądał je. Nie można teraz uzyskać dostępu do tokena USB. Coś nie tak z moim oprogramowaniem pośredniczącym/sterownikiem ... Jak te firmy sprzedają te rzeczy? Spędziłem kilka dni szukając prawidłowych wersji sterowników ... :( – user2173353

+0

@ user2173353 w naszym przypadku nie mieliśmy żadnego problemu) przykłady, sterowniki, wsparcie) dzięki produkcji – Sasha

3

Ten sam kod jak wyżej, ale używa pliku certyfikatu zamiast sklepu do podpisania dokumentu PDF na ostatniej stronie.

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

Skopiuj, wklej, zaimportuj potrzebne biblioteki i rozpocznij pracę nad czymś innym.

5

Zrobiłem aC# projekt, który może podpisać PDF z okien sklepu, SmartCard lub pliku/P12 Pfx Może być to może być przydatne cztery ty

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

Dzięki jean-luc. Skończyłem z moim projektem, ale będę miał na uwadze twój kod w przyszłym rozwoju. –

+0

Bardzo dobrze napisane metody i odpowiedź. –

Powiązane problemy