Use iText to create signature with complete own ap

2019-07-07 19:52发布

问题:

I need to create signatures, which consists only of the signing name and date. Additionally, these two fields have to be placed at exact coordinates as the two fields have to be placed in a predefined "revision table".

Is this possible?

Here´s my code, which is pretty (!) much the same as of Bruno Lowagie´s samples and is probably not even near to the problem´s solution:

namespace signatures.chapter3 {
    public class C3_11_SignWithToken
    {
        public static String SRC = "../../../../resources/hello.pdf";
        public static String DEST = "../../../../results/chapter3/hello_token.pdf";

        public void Sign(String src, String dest,
                         ICollection<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);
                // os = new FileStream(dest, FileMode.Create, FileAccess.Write);

                //Activate MultiSignatures
                stamper = PdfStamper.CreateSignature(reader, os, '\0', null, true);
                //To disable Multi signatures uncomment this line : every new signature will invalidate older ones !
                //stamper = PdfStamper.CreateSignature(reader, os, '\0');


                // Creating the appearance
                PdfSignatureAppearance appearance = stamper.SignatureAppearance;
                //appearance.Location = location;
                //appearance.SetVisibleSignature(new Rectangle(36, 612, 144, 644), 1, "sig4");

                appearance.Reason = "marked as changed";
                appearance.Location = location;
                //appearance.SetVisibleSignature("Reason");
                appearance.Layer2Text = "Signed on " + DateTime.Now;
                appearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.DESCRIPTION;


                // Creating the signature
                IExternalSignature pks = new X509Certificate2Signature(pk, digestAlgorithm);
                MakeSignature.SignDetached(appearance, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);

            }

            catch (Exception ex) {
                Console.WriteLine("GMA: " + ex.Message);
            }
            finally
            {
                if (reader != null)
                    reader.Close();
                if (stamper != null)
                    stamper.Close();
                if (os != null)
                    os.Close();
            }
        }
    }

Thanks a lot!

回答1:

Thanks @mkl. Your hint was very helpful and has solved the knot. Here´s my code which works like a charm:

public class SignWithToken   {
    public void Sign(String src, String dest,
                     ICollection<X509Certificate> chain, X509Certificate2 pk,
                     String digestAlgorithm, CryptoStandard subfilter,
                     String reason, String location,
                     ICollection<ICrlClient> crlList,
                     IOcspClient ocspClient,
                     ITSAClient tsaClient,
                     int estimatedSize, int RowIdx, int RowHeight, int x, int y, int NameWidth, int DateWidth, 
                     String RevIndex, String RevStep, String Reason, String Name, String Date)
    {

        // 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);
            // os = new FileStream(dest, FileMode.Create, FileAccess.Write);

            //Activate MultiSignatures
            stamper = PdfStamper.CreateSignature(reader, os, '\0', null, true);
            //To disable Multi signatures uncomment this line : every new signature will invalidate older ones !
            //stamper = PdfStamper.CreateSignature(reader, os, '\0');


            // Creating the appearance
            PdfSignatureAppearance appearance = stamper.SignatureAppearance;

            Rectangle rectangle = new Rectangle(x, y + RowIdx * RowHeight, x + NameWidth + DateWidth, y + (RowIdx+1) * RowHeight);
            appearance.SetVisibleSignature(rectangle, 1, "Revision " + RevIndex + "|" + RevStep);

            appearance.Reason = "marked as changed";
            appearance.Location = location;

            appearance.Layer2Text = "Signed on " + DateTime.Now;
            appearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.DESCRIPTION;
            PdfTemplate n2 = appearance.GetLayer(2);
            Font font = new Font();
            font.SetColor(255, 0, 0);
            font.Size = 10;

            ColumnText ct1 = new ColumnText(n2);
            ct1.SetSimpleColumn(new Phrase(Name, font), 0, 0, NameWidth, rectangle.Height, 15, Element.ALIGN_LEFT);
            ct1.Go();

            ColumnText ct2 = new ColumnText(n2);
            ct2.SetSimpleColumn(new Phrase(Date, font), NameWidth, 0, rectangle.Width, rectangle.Height, 15, Element.ALIGN_LEFT);
            ct2.Go();

            //n2.ConcatCTM(1, 0, 0, -1, 0, 0);
            //n2.SaveState();

            // Creating the signature
            IExternalSignature pks = new X509Certificate2Signature(pk, digestAlgorithm);
            MakeSignature.SignDetached(appearance, pks, chain, crlList, ocspClient, tsaClient, estimatedSize, subfilter);
        }

        catch (Exception ex)
        {
            Console.WriteLine("GMA: " + ex.Message);
        }
        finally
        {
            if (reader != null)
                reader.Close();
            if (stamper != null)
                stamper.Close();
            if (os != null)
                os.Close();
        }
    }
}