2

I am currently working on a web application (1) that allows sending the hash of a pdf file to another application (2). Application (2) returns a signed hash. I have a timestamp token that is a return of another API, and I'm trying to add it in my signature method but I don't know-how

signature method

   public string GetHash(string AttachID, string InternalAttch_ID, string Certif, string AttachName, bool notPdfFile, bool hasPdf )
    {
      try
      {
         string fileName = ConfigurationManager.AppSettings["unsignedPdf"] + AttachID + ".pdf";
         string SignedFileName = ConfigurationManager.AppSettings["signedPdf"] + AttachID + "_Signed.pdf";
         string SignatureImg = ConfigurationManager.AppSettings["ImagePath"];
         Org.BouncyCastle.X509.X509Certificate[] chain = new Org.BouncyCastle.X509.X509Certificate[1];
         byte[] bytes = Convert.FromBase64String(Certif);
         var cert = new X509Certificate2(bytes);
         chain[0] = new Org.BouncyCastle.X509.X509CertificateParser().ReadCertificate(cert.GetRawCertData());       
         using (PdfReader reader = new PdfReader(fileName))
          {
            using (FileStream os = File.OpenWrite(SignedFileName))
             {
               PdfStamper stamper = PdfStamper.CreateSignature(reader, os, '\0', null, true);   
               PdfSignatureAppearance appearance = null;
               appearance = stamper.SignatureAppearance;
               appearance.Reason = "Reason";
               appearance.Location = "location";
               appearance.SignDate = DateTime.Now.Date;
               appearance.SetVisibleSignature(new iTextSharp.text.Rectangle(50, 100, 270, 270), 1, UserName); 
               appearance.IsInvisible();
               appearance.Acro6Layers = true;
               IExternalSignature signature = new RemoteSignature();
               MakeSignature.SignDetached(appearance, signature, chain, null, null, null, 0, CryptoStandard.CADES);
               stamper.Close();
               os.Close();
             }
          }
              return "GetHash successfully done";
      }
     catch (Exception e)
      {
         string err = e.Message;
         return null;
      }
    }
  internal class RemoteSignature : IExternalSignature
    {
      public virtual byte[] Sign(byte[] message)
       {
         IDigest messageDigest = DigestUtilities.GetDigest(GetHashAlgorithm());
         byte[] messageHash = DigestAlgorithms.Digest(messageDigest, message);      
         string urlEncoded = HttpUtility.UrlEncode(Convert.ToBase64String(messageHash));
         byte[] urlEncodedByte = Encoding.ASCII.GetBytes(urlEncoded);
         var i = 0;
         while (readySignHashFile != true)
          {
            i++;
          }
        return Convert.FromBase64String(signedHash);
       }
      public virtual String GetHashAlgorithm()
       {
         return "SHA-256";
       }

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

1 Answers1

3

You call

MakeSignature.SignDetached(appearance, signature, chain, null, null, null, 0, CryptoStandard.CADES);

One of the null parameters is a ITSAClient.

To have your signature time-stamped, supply a non-null ITSAClient, for example a TSAClientBouncyCastle instance.

mkl
  • 90,588
  • 15
  • 125
  • 265
  • the problem is that TSClientBouncyCastle only accepts URL in the parameter and in my case I should set the token result of my post API in the parameter – oussama ferjani Mar 04 '21 at 08:20
  • Then simply implement `ITSAClient` yourself to call your API. you can use the `TSAClientBouncyCastle` source code for inspiration, merely call your API instead of sending a request to an URL. – mkl Mar 04 '21 at 10:53
  • 1
    If someone needs free timestamp servers, can check this topic: https://stackoverflow.com/a/25053511/1068246 – Muzaffer Galata Dec 22 '22 at 11:38