2015-08-31 51 views
0

我閱讀Bruno Lowagie的白皮書:PDF文檔的數字簽名。iTextSharp 5.5.6:使用SwissSign USB令牌簽名無效

我遵循這些例子,我可以用我的SwissSign USB令牌使用MSCAPI簽署PDF。這行代碼有訣竅:

MakeSignature.SignDetached(appearance,pks,chain,crlList,ocspClient,tsaClient,estimatedSize,subfilter);

我也是經過TSA客戶端與SwissSign TSA網址:TSA(點)swisssign(點)淨

當我打開Acrobat Reader軟件DC 2015年簽署的PDF,我得到的錯誤:

簽名無效。

有包含在此簽名的格式或信息錯誤

簽名者的身份尚未得到驗證

簽約時間是簽名者計算機上的時鐘。

使用SwissSign工具簽署PDF時,一切看起來都很好:簽名是有效的。

我已經把PDF是在這裏:

invalid PDF - signed with iTextSharp 5.5.6

valid PDF - signed with SwissSign tool

我已經試過哈希算法不同的組合,但沒有成功。我錯過了什麼?

任何幫助表示讚賞。

最好的問候,

菲爾

下面是完整的代碼:

private void _sign_Click(object sender, RoutedEventArgs e) 
    { 
     X509Store x509Store = new X509Store(StoreName.My, StoreLocation.CurrentUser); 
     x509Store.Open(OpenFlags.ReadOnly); 
     X509Certificate2Collection certificates = x509Store.Certificates; 
     IList<Org.BouncyCastle.X509.X509Certificate> chain = new List<Org.BouncyCastle.X509.X509Certificate>(); 
     X509Certificate2 pk = null; 
     if (certificates.Count > 0) 
     { 
      for (int i = 0; i < certificates.Count; i++) 
      { 
       if (certificates[i].FriendlyName == "Philipp Egger (Qualified Signature) .....")  // Phil Egger Signature Certificate 
       { 
        pk = certificates[i]; 
        break; 
       } 
      } 

      X509Chain x509chain = new X509Chain(); 
      x509chain.Build(pk); 

      foreach (X509ChainElement x509ChainElement in x509chain.ChainElements) 
      { 
       chain.Add(Org.BouncyCastle.Security.DotNetUtilities.FromX509Certificate(x509ChainElement.Certificate)); 
      } 
     } 
     x509Store.Close(); 

     if (pk != null) 
     { 
      #region connect usb token 
      /////////////////// 
      RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)pk.PrivateKey; 

      CspParameters cspp = new CspParameters(); 
      cspp.KeyContainerName = rsa.CspKeyContainerInfo.KeyContainerName; 
      cspp.ProviderName = rsa.CspKeyContainerInfo.ProviderName; 
      cspp.ProviderType = rsa.CspKeyContainerInfo.ProviderType; 

      cspp.Flags = CspProviderFlags.NoPrompt; 
      System.Security.SecureString pwstr = new System.Security.SecureString(); 
      pwstr.AppendChar('x'); 
      pwstr.AppendChar('x'); 
      pwstr.AppendChar('x'); 
      cspp.KeyPassword = pwstr; 

      RSACryptoServiceProvider rsa2 = new RSACryptoServiceProvider(cspp); 
      rsa2.PersistKeyInCsp = true; 
      // PIN is cached from now on and popup won't appear 
      /////////////////////// 
      #endregion 

      IOcspClient ocspClient = new OcspClientBouncyCastle(); 
      ITSAClient tsaClient = null; 
      for (int i = 0; i < chain.Count; i++) 
      { 
       Org.BouncyCastle.X509.X509Certificate cert = chain[i]; 
       String tsaUrl = CertificateUtil.GetTSAURL(cert); 
       if (tsaUrl != null) 
       { 
        tsaClient = new TSAClientBouncyCastle(tsaUrl); 
        break; 
       } 
      } 

      if (tsaClient == null) 
      { 
       tsaClient = new TSAClientBouncyCastle("http://tsa.swisssign.net"); 
       //tsaClient = new MyTSAClientBouncyCastle("http://tsa.swisssign.net");  // set user-agent 
      } 

      IList<ICrlClient> crlList = new List<ICrlClient>(); 
      crlList.Add(new CrlClientOnline(chain)); 

      string pathSource = @"C:\Temp\test_to_sign.pdf"; 
      string pathTarget3 = @"C:\Temp\test_to_sign-signed3.pdf"; 

      // this.SignNew(pathSource, pathTarget1, chain, pk, DigestAlgorithms.SHA1, CryptoStandard.CMS, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0); 
      // this.SignNew(pathSource, pathTarget2, chain, pk, DigestAlgorithms.SHA1, CryptoStandard.CADES, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0); 
      this.SignNew(pathSource, pathTarget3, chain, pk, DigestAlgorithms.SHA256, CryptoStandard.CMS, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0); 
      // this.SignNew(pathSource, pathTarget4, chain, pk, DigestAlgorithms.SHA256, CryptoStandard.CADES, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0); 
      // this.SignNew(pathSource, pathTarget5, chain, pk, DigestAlgorithms.SHA384, CryptoStandard.CMS, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0); 
      // this.SignNew(pathSource, pathTarget6, chain, pk, DigestAlgorithms.SHA384, CryptoStandard.CADES, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0); 
      // this.SignNew(pathSource, pathTarget7, chain, pk, DigestAlgorithms.SHA512, CryptoStandard.CMS, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0); 
      // this.SignNew(pathSource, pathTarget8, chain, pk, DigestAlgorithms.SHA512, CryptoStandard.CADES, "Test", "Rheinau", crlList, ocspClient, tsaClient, 0); 

      this._txt.Text = "Signed successfully."; 
     } 
     else 
     { 
      this._txt.Text = "Certificate not found."; 
     } 
    } 

    public void SignNew(String src, String dest, 
      ICollection<Org.BouncyCastle.X509.X509Certificate> chain, X509Certificate2 pk, 
      String digestAlgorithm, CryptoStandard subfilter, 
      String reason, String location, 
      ICollection<ICrlClient> crlList, 
      IOcspClient ocspClient, 
      ITSAClient tsaClient, 
      int estimatedSize) 
    { 
     // Creating the reader and the stamper 
     PdfReader reader = null; 
     PdfStamper stamper = null; 
     FileStream os = null; 
     try 
     { 
      reader = new PdfReader(src); 
      os = new FileStream(dest, FileMode.Create); 
      stamper = PdfStamper.CreateSignature(reader, os, '\0'); 
      // Creating the appearance 
      PdfSignatureAppearance appearance = stamper.SignatureAppearance; 
      appearance.Reason = reason; 
      appearance.Location = location; 
      appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(36, 748, 144, 780), 1, "Signature1"); 
      // Creating the signature 
      IExternalSignature pks = new X509Certificate2Signature(pk, digestAlgorithm); 
      MakeSignature.SignDetached(appearance, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter); 
     } 
     catch (Exception e) 
     { 
      this._txt.Text = e.Message; 
     } 
     finally 
     { 
      if (reader != null) 
       reader.Close(); 
      if (stamper != null) 
       stamper.Close(); 
      if (os != null) 
       os.Close(); 
     } 
    } 
+0

SwissSign工具內部也使用iText(夏普)。因此,您如何使用iTextSharp簽名API有些問題。從您提供的單一代碼行中無法推斷出任何東西。因此,請提供更多代碼。此外,你已經簽署了包括一個巨大的CRL和一個時間戳。爲什麼不從簡單開始,首先創建一個沒有這些添加的簽名,並在基本工作後儘快添加它們? – mkl

+0

@mkl:謝謝你的回覆。是的,關於CRL - >我在重構iTextSharp中的同一個列表時與使用SwissSign工具簽名時一樣。 – Fitsch

+0

好的,但你有沒有嘗試過一次沒有名單?如果你這樣做,是否成功併產生Adobe Reader接受的簽名? – mkl

回答

0

的問題是,它顯然SwissSign CSP(加密服務提供商;提供之間的橋樑層Windows系統存儲和硬件設備)在使用MSCAPI時挑選錯誤的私鑰。

似乎沒有解決方法可以在MSCAPI中選擇正確的私鑰。

因此,我決定使用PKCS11和NCryptroki庫。這裏的代碼:

using Cryptware.NCryptoki; 
using iTextSharp.text; 
using iTextSharp.text.log; 
using iTextSharp.text.pdf; 
using iTextSharp.text.pdf.security; 
using Org.BouncyCastle.Security; 
using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Security.Cryptography.X509Certificates; 
using System.Text; 
using System.Threading.Tasks; 

namespace _07SignWithPKCS11DLL 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      LoggerFactory.GetInstance().SetLogger(new SysoLogger()); 

      // Creates a Cryptoki object related to the specific PKCS#11 native library 
      Cryptoki cryptoki = new Cryptoki("cvP11.dll"); 
      cryptoki.Initialize(); 

      // Reads the set of slots containing a token 
      SlotList slots = cryptoki.Slots; 
      if (slots.Count == 0) 
      { 
       Console.WriteLine("No slot available"); 
       Console.ReadLine(); 
       return; 
      } 
      // Gets the first slot available 
      Slot slot = slots[0]; 
      if (!slot.IsTokenPresent) 
      { 
       Console.WriteLine("No token inserted in the slot: " + slots[0].Info.Description); 
       Console.ReadLine(); 
       return; 
      } 

      // Gets the first token available 
      Token token = slot.Token; 

      // Opens a read serial session 
      Session session = token.OpenSession(Session.CKF_SERIAL_SESSION, null, null); 

      // Executes the login passing the user PIN 
      int nRes = session.Login(Session.CKU_USER, "secret"); 
      if (nRes != 0) 
      { 
       Console.WriteLine("Wrong PIN"); 
       return; 
      } 

      CSignWithPKCS11SC.Smartcardsign(session, "PhilippEggerQualifiedSignature", "SwissSign_nonRep    "); 

      /* 
      CryptokiCollection template = new CryptokiCollection(); 
      template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_CERTIFICATE)); 
      template.Add(new ObjectAttribute(ObjectAttribute.CKA_CERTIFICATE_TYPE, Certificate.CKC_X_509)); 

      CryptokiCollection objects = session.Objects.Find(template, 10); 

      // If the private keys is found continue 
      if (objects.Count > 0) 
      { 
       foreach (Object obj in objects) 
       { 
        Cryptware.NCryptoki.X509Certificate cert = (Cryptware.NCryptoki.X509Certificate)obj; 
        Console.WriteLine(cert.Label + " - " + cert.ID); 
       } 
      } 
      */ 

      // Logouts and closes the session 
      session.Logout(); 
      session.Close(); 
      cryptoki.Finalize(IntPtr.Zero); 

      Console.ReadLine(); 
     } 
    } 

    class CryptokiPrivateKeySignature : IExternalSignature 
    { 
     private readonly Cryptware.NCryptoki.Session session; 
     RSAPrivateKey privateKey; 

     public CryptokiPrivateKeySignature(Session session, String alias) 
     { 
      this.session = session; 
      CryptokiCollection template = new CryptokiCollection(); 
      template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_PRIVATE_KEY)); 
      template.Add(new ObjectAttribute(ObjectAttribute.CKA_KEY_TYPE, Key.CKK_RSA)); 
      // "SwissSign_nonRep    " 
      // "SwissSign_digSig    " 
      template.Add(new ObjectAttribute(ObjectAttribute.CKA_LABEL, alias)); 

      /* 
      CryptokiCollection objects = session.Objects.Find(template, 10); 
      if (objects.Count > 0) 
      { 
       foreach (Object obj in objects) 
       { 
        RSAPrivateKey cert = (RSAPrivateKey)obj; 
        Console.WriteLine(cert.Label); 
       } 
      } 
      */ 

      privateKey = (RSAPrivateKey)session.Objects.Find(template); 
     } 

     public String GetHashAlgorithm() 
     { 
      return "SHA1"; 
     } 

     public String GetEncryptionAlgorithm() 
     { 
      return "RSA"; 
     } 

     public byte[] Sign(byte[] message) 
     { 
      session.SignInit(Mechanism.SHA1_RSA_PKCS, privateKey); 
      return session.Sign(message); 
     } 
    } 

    class CSignWithPKCS11SC 
    { 
     public const String SRC = @"C:\Temp\test_to_sign.pdf"; 
     public const String DEST = @"C:\Temp\test_to_sign-pkcs11.pdf"; 
     //public const String DLL = "c:/windows/system32/beidpkcs11.dll"; 
     public const String DLL = "c:/windows/system32/cvP11.dll"; 

     public void Sign(String src, String dest, ICollection<Org.BouncyCastle.X509.X509Certificate> chain, Session session, String alias, 
         String digestAlgorithm, CryptoStandard subfilter, String reason, String location, 
         ICollection<ICrlClient> crlList, IOcspClient ocspClient, ITSAClient tsaClient, int estimatedSize) 
     { 
      // Creating the reader and the stamper 
      PdfReader reader = null; 
      PdfStamper stamper = null; 
      FileStream os = null; 
      try 
      { 
       reader = new PdfReader(src); 
       os = new FileStream(dest, FileMode.Create); 
       stamper = PdfStamper.CreateSignature(reader, os, '\0'); 
       // Creating the appearance 
       PdfSignatureAppearance appearance = stamper.SignatureAppearance; 
       appearance.Reason = reason; 
       appearance.Location = location; 
       appearance.SetVisibleSignature(new Rectangle(36, 748, 144, 780), 1, "sig"); 
       // Creating the signature 
       IExternalSignature pks = new CryptokiPrivateKeySignature(session, alias); 
       MakeSignature.SignDetached(appearance, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter); 
      } 
      finally 
      { 
       if (reader != null) 
        reader.Close(); 
       if (stamper != null) 
        stamper.Close(); 
       if (os != null) 
        os.Close(); 
      } 
     } 


     public static void Smartcardsign(Session session, String alias, String aliasPrivateKey) 
     { 
      // Searchs for an RSA certificate object 
      // Sets the template with its attributes 
      CryptokiCollection template = new CryptokiCollection(); 
      template.Add(new ObjectAttribute(ObjectAttribute.CKA_CLASS, CryptokiObject.CKO_CERTIFICATE)); 
      template.Add(new ObjectAttribute(ObjectAttribute.CKA_CERTIFICATE_TYPE, Certificate.CKC_X_509)); 
      template.Add(new ObjectAttribute(ObjectAttribute.CKA_LABEL, alias)); 

      Cryptware.NCryptoki.X509Certificate nCert = (Cryptware.NCryptoki.X509Certificate)session.Objects.Find(template); 

      if (nCert != null) 
      { 

       X509Certificate2 cert = Utils.ConvertCertificate(nCert); 
       ICollection<Org.BouncyCastle.X509.X509Certificate> chain = new List<Org.BouncyCastle.X509.X509Certificate>(); 
       X509Chain x509chain = new X509Chain(); 
       x509chain.Build(cert); 

       foreach (X509ChainElement x509ChainElement in x509chain.ChainElements) 
       { 
        chain.Add(DotNetUtilities.FromX509Certificate(x509ChainElement.Certificate)); 
       } 

       IOcspClient ocspClient = new OcspClientBouncyCastle(); 
       List<ICrlClient> crlList = new List<ICrlClient>(); 
       crlList.Add(new CrlClientOnline(chain)); 
       TSAClientBouncyCastle tsaClient = new TSAClientBouncyCastle("http://tsa.swisssign.net"); 

       CSignWithPKCS11SC app = new CSignWithPKCS11SC(); 

       Console.WriteLine("Logged in? " + session.IsLoggedIn); 

       app.Sign(SRC, DEST, chain, session, aliasPrivateKey, DigestAlgorithms.SHA256, CryptoStandard.CMS, 
         "Test", "Rheinau", crlList, ocspClient, tsaClient, 0); 
      } 
      else 
      { 
       Console.WriteLine("Certificate not found: " + alias); 
      } 
     } 
    } 
} 
相關問題