PDF Signature - Insert Separately Signed Hash

I am trying to sign a PDF document using two web services on two servers. But it shows that "The document has been modified or damaged since it was signed" in Adobe Reader. Can anyone suggest what is wrong in the following code.

PROCEDURE 1. A Web Service (WS) on Server A, generates a hash from the PDF and sent to WS on Server B for signing. 2. WS on server B stands for hash. 3. The WS on Server A receives the signed hash and is embedded in the PDF document.

CODE

GENERATE HASH

 private PDFHashData generateHash(byte[] content, string userName)
    {
        PdfReader reader = new PdfReader(content);
        MemoryStream ms = new MemoryStream();

        PdfStamper stamper = PdfStamper.CreateSignature(reader, ms, '\0');
        PdfSignatureAppearance appearance = stamper.SignatureAppearance;
        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;
        IExternalSignatureContainer external = new ExternalBlankSignatureContainer(PdfName.ADOBE_PPKLITE, PdfName.ADBE_PKCS7_DETACHED);
        MakeSignature.SignExternalContainer(appearance, external, 8192);

        byte[] hash = SHA256Managed.Create().ComputeHash(appearance.GetRangeStream());

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

        PDFHashData phData= new PDFHashData();
        phData.Hash = hex.ToString();
        phData.Content = Convert.ToBase64String(ms.ToArray());
        return phData;
    }

      

SIGN HASH

    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();
    }
    private Stream getCertificate()
    {
// Base 64 byte - PFX file with private key
        return new MemoryStream(Convert.FromBase64String("..................................AgIEAA=="));
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        Stream stream = Request.InputStream;
        byte[] buffer = new byte[stream.Length];
        stream.Read(buffer, 0, buffer.Length);
        byte[] hash = StringToByteArray(Encoding.UTF8.GetString(buffer));

        Pkcs12Store store = new Pkcs12Store(getCertificate(), "*******".ToCharArray());
        String alias = "";
        foreach (string al in store.Aliases)
            if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate)
            {
                alias = al;
                break;
            }
        AsymmetricKeyEntry pk = store.GetKey(alias);
        X509CertificateEntry[] chain = store.GetCertificateChain(alias);
        List<Org.BouncyCastle.X509.X509Certificate> c = new List<Org.BouncyCastle.X509.X509Certificate>();
        foreach (X509CertificateEntry en in chain)
        {
            c.Add(en.Certificate);
        }
        PrivateKeySignature signature = new PrivateKeySignature(pk.Key, "SHA1");
        String hashAlgorithm = signature.GetHashAlgorithm();
        PdfPKCS7 sgn = new PdfPKCS7(null, c, hashAlgorithm, false);
        DateTime signingTime = DateTime.Now;
        byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CMS);
        byte[] extSignature = signature.Sign(sh);
        sgn.SetExternalDigest(extSignature, null, signature.GetEncryptionAlgorithm());

        Response.Write(Convert.ToBase64String(sgn.GetEncodedPKCS7(hash, null, null, null, CryptoStandard.CMS)));
    }

      

SIGNED SIGNED IN PDF

private byte[] signPDF(byte[] content, string userName, byte[] pk)
    {
        PdfReader reader = new PdfReader(content);
        MemoryStream os = new MemoryStream();
        IExternalSignatureContainer external = new MyExternalSignatureContainer(pk);
        MakeSignature.SignDeferred(reader, signatureFieldName, os, external);
        return os.ToArray();
    }

      

+3


source to share


1 answer


For those interested, I am posting an answer. I ended up using itextsharp 5.5.10. The code is given below,

Initialize PDF object

public PDFSigning(byte[] Content, string UserName)
    {
        content = Content;
        reader = new PdfReader(content);
        ms = new MemoryStream();
        stamper = PdfStamper.CreateSignature(reader, ms, '\0');
        appearance = stamper.SignatureAppearance;
        userName = UserName;
    }

private Stream getCertificate()
    {
        return new MemoryStream(Convert.FromBase64String("************************=="));
    }

      

Create hash

 private string generateHash()
    {
        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 = 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;

        appearance.CryptoDictionary = dic;
        Dictionary<PdfName, int> exclusionSizes = new Dictionary<PdfName, int>();
        exclusionSizes.Add(PdfName.CONTENTS, (csize * 2) + 2);
        appearance.PreClose(exclusionSizes);


        HashAlgorithm sha = new SHA256CryptoServiceProvider();
        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();
    }

      



Hash sign

 public byte[] SignMsg(string hexhash)
    {
        byte[] hash = hexToByteArray(hexhash);
        Pkcs12Store store = new Pkcs12Store(getCertificate(), "*********".ToCharArray());
        String alias = "";
        foreach (string al in store.Aliases)
            if (store.IsKeyEntry(al) && store.GetKey(al).Key.IsPrivate)
            {
                alias = al;
                break;
            }
        AsymmetricKeyEntry pk = store.GetKey(alias);
        X509CertificateEntry[] chain = store.GetCertificateChain(alias);
        List<Org.BouncyCastle.X509.X509Certificate> c = new List<Org.BouncyCastle.X509.X509Certificate>();
        foreach (X509CertificateEntry en in chain)
        {
            c.Add(en.Certificate);
        }
        PrivateKeySignature signature = new PrivateKeySignature(pk.Key, "SHA256");
        String hashAlgorithm = signature.GetHashAlgorithm();
        PdfPKCS7 sgn = new PdfPKCS7(null, c, hashAlgorithm, false);
        DateTime signingTime = DateTime.Now;
        byte[] sh = sgn.getAuthenticatedAttributeBytes(hash, null, null, CryptoStandard.CMS);
        byte[] extSignature = signature.Sign(sh);
        sgn.SetExternalDigest(extSignature, null, signature.GetEncryptionAlgorithm());
        return sgn.GetEncodedPKCS7(hash, null, null, null, CryptoStandard.CMS);

    }

      

PDF sign

private byte[] signPDF(byte[] pk)
    {

        byte[] paddedSig = new byte[csize];
        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);

        //System.IO.File.WriteAllBytes(System.Web.HttpContext.Current.Server.MapPath("~/temp.pdf"), ms.ToArray());
        return ms.ToArray();

    }

      

+4


source







All Articles