2012-11-03 24 views
5

Sono nuovo su iTextSharp (e StackOverFlow). Sto cercando di firmare un PDF in C# usando un token USB esterno. Provo ad usare il codice che segue ho scavato da internet.Firma PDF con iTextSharp 5.3.3 e token 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); 

Il problema è che ricevo un'eccezione:

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

Quindi, per ora tornerò a iTextSharp 5.2.1 e utilizzare gli esempi da http://itextpdf.sourceforge.net/howtosign.html#signextdic. Loro fanno il lavoro per me. Se qualcuno trova la soluzione per iTextSHarp 5.3.3 sarò felice di vederlo. –

risposta

7

Questo approccio funziona bene per noi (iTextSharp 5.3.3). Usiamo smart-card e 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

C'è qualche caso che i certificati da token USB plug-in non siano elencati quando si utilizza in questo modo? Perché il certificato del mio token non è elencato usando questo codice mentre Acrobat * lo * elenca. Sebbene Acrobat restituisca un "Il keyset non è definito". errore quando si tenta di firmare con esso ... – user2173353

+0

Non importa. Sembra che Acrobat avesse importato i certificati nel mio negozio locale ad un certo punto e li stava visualizzando da lì. Non è possibile accedere al token USB ora. Sth sbagliato con il mio middleware/driver ... Come fanno queste aziende a vendere quelle cose? Ho passato giorni a cercare le versioni corrette del driver ... :( – user2173353

+0

@ user2173353 nel nostro caso non abbiamo avuto alcun problema) esempi, driver, supporto) grazie alla produzione – Sasha

3

Lo stesso codice come sopra, ma usa un file di certificato invece di negozio per firmare un documento PDF nell'ultima pagina.

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

Copia, incolla, importa le librerie necessarie e vai a lavorare su qualcos'altro.

5

ho fatto progetto aC# che può firmare un PDF da Windows Store, SmartCard o un file/P12 Pfx Può essere che può essere utile a quattro si

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

Grazie jean-luc. Ho finito con il mio progetto ma avrò in mente il tuo codice nello sviluppo futuro. –

+0

Metodi molto ben scritti e risposta. –

Problemi correlati