Sign embedding to PDF, Document has been altered or corrupted since it was signed problem

69 Views Asked by At

I want to write two services. First service is responsible to generate the hash of pdf and send that hash to second service. Second service is responsible for signing that hash and returning it to first service. Here is my hash generate code:

public string GenerateHash()
{
    string Reason = "Ferid";
    string Location = "Baku";
    string Contact = "Huseynlyi";

    string signatureFieldName = null;
    // appearance.SetVisibleSignature(new Rectangle(500, 150, 400, 200), 1, signatureFieldName);
    appearance.SignDate = DateTime.Now;
    appearance.Reason = Reason;
    appearance.Location = Location;
    appearance.Contact = Contact;
    StringBuilder buf = new StringBuilder();
    buf.Append("Digitally signed by");
    buf.Append("\n");
    buf.Append(userName);
    buf.Append("\n");
    buf.Append("Date: " + appearance.SignDate);
    appearance.Layer2Text = buf.ToString();
    appearance.Acro6Layers = true;
    appearance.CertificationLevel = 0;

    PdfSignature dic = GeneratePdfSignature();

    appearance.CryptoDictionary = dic;

    Dictionary<PdfName, int> exclusionSizes = new Dictionary<PdfName, int>();
    exclusionSizes.Add(PdfName.CONTENTS, (RESERVED_SPACE_SIGNATURE * 2) + 2); // RESERVED_SPACE_SIGNATURE = 3072
    appearance.PreClose(exclusionSizes);

    System.Security.Cryptography.HashAlgorithm sha = new SHA1CryptoServiceProvider();
    Stream s = appearance.GetRangeStream();
    int read = 0;
    byte[] buff = new byte[0x2000];
    while ((read = s.Read(buff, 0, 0x2000)) > 0)
    {
        sha.TransformBlock(buff, 0, read, buff, 0);
    }
    sha.TransformFinalBlock(buff, 0, 0);

    StringBuilder hex = new StringBuilder(sha.Hash.Length * 2);
    foreach (byte b in sha.Hash)
        hex.AppendFormat("{0:x2}", b);

    return hex.ToString();
}

private PdfSignature GeneratePdfSignature()
{
    PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED)
    {
        Date = new PdfDate(appearance.SignDate),
        Name = userName
    };
    dic.Reason = appearance.Reason;
    dic.Location = appearance.Location;
    dic.Contact = appearance.Contact;
    return dic;
}

And here is my hash signing code:

 public byte[] SignHash_(string hexhash, string password)
 {
     byte[] hash = StringToByteArray(hexhash);

     X509Certificate2 signerCer = null;
     X509Store store_ = new X509Store(StoreName.My, StoreLocation.CurrentUser);
     store_.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
     X509Certificate2Collection colSign = store_.Certificates.Find(X509FindType.FindBySerialNumber, "11e618d4956fb5eb000300029bb5", false);
     store_.Close();
     X509Certificate2 certificate = colSign[0];

     AsymmetricAlgorithm privateKey = certificate.GetRSAPrivateKey();
     RSA rsa = privateKey as RSA;
     if (rsa == null)
     {
         throw new Exception("The certificate does not have an RSA private key.");
     }
     HashAlgorithmName hashAlgorithm = HashAlgorithmName.SHA1;
     rsa.SignData(hash, hashAlgorithm, RSASignaturePadding.Pkcs1);
     ContentInfo content = new ContentInfo(hash);
     SignedCms signedCms = new SignedCms(content, true);
     CmsSigner signer = new CmsSigner(certificate);
     signer.DigestAlgorithm = new Oid(hashAlgorithm.Name);
     signer.IncludeOption = X509IncludeOption.EndCertOnly;
     signedCms.ComputeSignature(signer, false);
     return signedCms.Encode();
 }

private static byte[] StringToByteArray(string hex)
{
    return Enumerable.Range(0, hex.Length)
                    .Where(x => x % 2 == 0)
                    .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
                    .ToArray();
}

And this is my code to embed to that pdf:

 public byte[] SignPDFToMemory(byte[] pk)
 {
     byte[] paddedSig = new byte[RESERVED_SPACE_SIGNATURE];
     System.Array.Copy(pk, 0, paddedSig, 0, pk.Length);

     PdfDictionary dic2 = new PdfDictionary();
     dic2.Put(PdfName.CONTENTS, new PdfString(paddedSig).SetHexWriting(true));
     appearance.Close(dic2);

     return ms.ToArray();
 }

 public void SignPDFToNewFile(byte[] pk, string destinyPDFSigned)
 {
     var pdfInMemory = SignPDFToMemory(pk);

     File.WriteAllBytes(destinyPDFSigned, pdfInMemory);
 }

RESERVED_SPACE_SIGNATURE is 3072. The code works well but it gives Document has been altered or corrupted since it was signed problem. Why is that?

0

There are 0 best solutions below