SoFunction
Updated on 2025-03-07

C# uses package to add digital signatures to PDF

background

  • Requirements for digital signature of PDF documents
  • Requirements for adding watermarks to PDF documents
  • The online information version is different or incomplete

All mentioned in this article are used for .NET, and there are versions in other languages ​​before, such as for JAVA;
Mainly used for operating PDFs, and in addition, etc.
It mainly introduces the functions of using component packages to digitally sign and add watermarks to PDF documents in C#, aiming to guide everyone to quickly and easily digitally sign and add watermarks to PDF documents;

Introduction

for .NET is a professional PDF document control component based on the .NET platform. It enables developers to create, read, write, and manipulate PDF documents using .NET applications without using Adobe Acrobat and other external controls. for .NET has rich functions. In addition to basic functions such as: drawing a variety of graphics, pictures, creating form fields, inserting headers and footers, entering data tables, and automatically paging large tables, for .NET also supports PDF digital signatures, converting HTML into PDF format, extracting text information and pictures in PDF documents, etc. Currently, for .NET has two versions, one is the free version and the other is the paid version. If the free version is just to process simple pdf, it is fine, but if the output is pdf, it will only display the first 10 pages, and the eleventh page is the introduction to the scheduled purchase page. I mainly use the digital signature and watermark of the PDF document, so it does not involve outputting pdf;

rely

The sample code in this article depends on the NuGet package that can be introduced in the project.

Source code

Core code

public class DigitalSignature
    {
        /// <summary>
        /// The red warning words at the top of the page cover the white picture Base64.        /// </summary>
        private const string WatermarkCoverBase64 = "/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCABHAycDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD9U6KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA//Z";

        /// <summary>
        /// Constructor.        /// </summary>
        /// <param name="waitSignFile">File to be signed.</param>        /// <param name="imageSign">Signed picture.</param>        /// <param name="pfx">Signature certificate.</param>        /// <param name="pfxPwd">Signature certificate password.</param>        public DigitalSignature(byte[] waitSignFile, byte[] imageSign, byte[] pfx, string pfxPwd)
        {
             = waitSignFile;
             = imageSign;
             = pfx;
             = pfxPwd;
        }

        /// &lt;summary&gt;
        /// Constructor.        /// &lt;/summary&gt;
        /// <param name="waitSignFile">File to be signed.</param>        /// <param name="charactersSign">Signature text.</param>        /// <param name="signRightLeftWidth">Sign Right to Left Width.</param>        /// <param name="signBottomUpHeight">Signature low up height.</param>        /// <param name="pfx">Signature certificate.</param>        /// <param name="pfxPwd">Signature certificate password.</param>        public DigitalSignature(byte[] waitSignFile, string charactersSign, float signRightLeftWidth, float signBottomUpHeight, byte[] pfx, string pfxPwd)
        {
             = waitSignFile;
             = charactersSign;
             = signRightLeftWidth;
             = signBottomUpHeight;
             = pfx;
             = pfxPwd;
        }

        /// &lt;summary&gt;
        /// Constructor.        /// &lt;/summary&gt;
        /// <param name="waitSignFile">File to be signed.</param>        /// <param name="imageSign">Signed picture.</param>        /// <param name="charactersSign">Signature text.</param>        /// <param name="pfx">Signature certificate.</param>        /// <param name="pfxPwd">Signature certificate password.</param>        public DigitalSignature(byte[] waitSignFile, byte[] imageSign, string charactersSign, byte[] pfx, string pfxPwd)
        {
             = waitSignFile;
             = imageSign;
             = charactersSign;
             = pfx;
             = pfxPwd;
        }

        /// &lt;summary&gt;
        /// Gets or sets File to be signed.        /// &lt;/summary&gt;
        public byte[] WaitSignFile { get; set; }

        /// &lt;summary&gt;
        /// Gets or sets graph signature.        /// &lt;/summary&gt;
        public byte[] ImageSign { get; set; }

        /// &lt;summary&gt;
        /// Gets or sets Text signature.        /// &lt;/summary&gt;
        public string CharactersSign { get; set; }

        /// &lt;summary&gt;
        /// Gets or sets Signature right to left width.        /// &lt;/summary&gt;
        public float? SignRightLeftWidth { get; set; }

        /// &lt;summary&gt;
        /// Gets or sets Signature top up height.        /// &lt;/summary&gt;
        public float? SignBottomUpHeight { get; set; }

        /// &lt;summary&gt;
        /// Gets or sets Signature index page (not specifying all pages for signature by default).        /// &lt;/summary&gt;
        public int? SignIndexPages { get; set; }

        /// &lt;summary&gt;
        /// Gets or sets Pfx certificate.        /// &lt;/summary&gt;
        public byte[] Pfx { get; set; }

        /// &lt;summary&gt;
        /// Gets or sets Pfx certificate password.        /// &lt;/summary&gt;
        public string PfxPwd { get; set; }

        public Stream Signature()
        {
            ///Load PDF document            PdfDocument pdf = new PdfDocument();
            ();

            if (pdf?.Pages?.Count &lt;= 0)
            {
                throw new Exception("The file is wrong");
            }

            X509Certificate2 x509 = new X509Certificate2(, );
            PdfOrdinarySignatureMaker signatureMaker = new PdfOrdinarySignatureMaker(pdf, x509);

            var appearance = new PdfCustomSignatureAppearance(, , , );
            IPdfSignatureAppearance signatureAppearance = appearance;

            // Pictures on white background            PdfRubberStampAnnotation logoStamp = new PdfRubberStampAnnotation(new RectangleF(new PointF(0, 0), new SizeF(350, 22)));
            PdfAppearance logoApprearance = new PdfAppearance(logoStamp);
            //var logoPath =  + "\\";
            byte[] byt = Convert.FromBase64String(WatermarkCoverBase64);
            Stream streamByLogo = new MemoryStream(byt);
            PdfImage image = (streamByLogo);
            PdfTemplate template = new PdfTemplate(350, 22);
            (image, 0, 0);
             = template;
             = logoApprearance;

            if ()
            {
                if ( &lt; 0 ||  &gt; pdf?.Pages?.Count)
                {
                    throw new Exception("The signature index page is incorrect");
                }

                var page = [];

                // Add white background image to cover the top mark on the page                (logoStamp);

                // Add a visual signature at the specified location in the page                ("signName_", page,  - ,  - , , , signatureAppearance);
            }
            else
            {
                foreach (PdfPageBase page in )
                {
                    // Add white background image to cover the top mark on the page                    (logoStamp);

                    // Add a visual signature at the specified location in the page                    ("signName_", page,  - ,  - , , , signatureAppearance);
                }
            }

            MemoryStream stream = new MemoryStream();
            (stream, );
            ();
            return stream;
        }

        /// &lt;summary&gt;
        /// Use third-party plug-in =》 to remove Evaluation Warning : The document was created with for .NET.        /// &lt;/summary&gt;
        /// <param name="sourcePdfs">original file address</param>        //private static MemoryStream ClearPdfFilesFirstPage(MemoryStream sourcePdf)
        //{
        //     reader = null;
        //     document = new ();
        //     page = null;
        //     pdfCpy = null;
        //    int n = 0;
        //    reader = new (sourcePdf);
        //    ();
        //    n = ;
        //    document = new ((1));
        //    MemoryStream memoryStream = new MemoryStream();
        //    pdfCpy = new (document, memoryStream);
        //    ();
        //    for (int j = 2; j &lt;= n; j++)
        //    {
        //        page = (reader, j);
        //        (page);

        //    }
        //    ();
        //    ();
        //    return memoryStream;
        //}
    }


    public class PdfCustomSignatureAppearance : IPdfSignatureAppearance
    {
        public PdfCustomSignatureAppearance(string charactersSign, byte[] sign, float? signRightLeftWidth, float? signBottomUpHeight)
        {
             = charactersSign;

            if (sign != null &amp;&amp;  &gt; 0)
            {
                 = sign;
                MemoryStream ms = new MemoryStream(sign);
                var image = (ms);
                if (!)
                {
                    signRightLeftWidth = ;
                }

                if (!)
                {
                    signBottomUpHeight = ;
                }
            }

             = ;
             = ;
        }

        /// &lt;summary&gt;
        /// Gets or sets signature.        /// &lt;/summary&gt;
        public byte[] Sign { get; set; }

        /// &lt;summary&gt;
        /// Gets or sets Signature right to left width.        /// &lt;/summary&gt;
        public float SignRightLeftWidth { get; set; }

        /// &lt;summary&gt;
        /// Gets or sets Signature top up height.        /// &lt;/summary&gt;
        public float SignBottomUpHeight { get; set; }

        /// &lt;summary&gt;
        /// Gets or sets Text signature.        /// &lt;/summary&gt;
        public string CharactersSign { get; set; }

        public void Generate(PdfCanvas g)
        {
            if (!(CharactersSign))
            {
                float fontSize = 15;
                var font = new ("Arial", fontSize);
                PdfTrueTypeFont fontByPdf = new PdfTrueTypeFont(font, true);
                (CharactersSign, fontByPdf, , new PointF(0, 0));
            }

            if ( != null &amp;&amp;  &gt; 0)
            {
                Stream stream = new MemoryStream();
                ((stream), new PointF(20, 20));
            }
        }
    }

Calling implementation

static void Main(string[] args)
        {

            /*
                 Preface: Recently, there is a requirement to digitally sign documents;
                 Description: This example digitally signs PDF based on components, demonstrating
                     Signing certificate usage project
             CreateSelfSignedCertificateByBouncyCastle(/daileass/)
                     The generated self-signed certificate pfx solves the warning on the head of the document after digital signature.

             */

            var fileCert =  + "\\Cert\\";
            var file =  + "\\File\\";
            var filePath = file + "";
            var newFilePath = file + $"dome_{("yyyyMMddHHmmss")}.pdf";
            var pfxFilePath = fileCert + "";
            var pfxFilePwd = "ABCD123456";
            var signFilePath = file + "";

            // Digital signature            var digitalSignature = new DigitalSignature(
                File2Bytes(filePath),
                File2Bytes(signFilePath),
                "Sign Here:",
                File2Bytes(pfxFilePath),
                pfxFilePwd
                );
            var stream = ();

            // Save signed file            using (var fileStream = (newFilePath))
            {
                (0, );
                (fileStream);
            }

            ("OK");
            ();
        }

        /// &lt;summary&gt;
        /// Convert file to byte array        /// &lt;/summary&gt;
        /// <param name="path">File address</param>        /// <returns>Converted byte array</returns>        public static byte[] File2Bytes(string path)
        {
            if (!(path))
            {
                return new byte[0];
            }

            FileInfo fi = new FileInfo(path);
            byte[] buff = new byte[];

            FileStream fs = ();
            (buff, 0, Convert.ToInt32());
            ();

            return buff;
        }

Source code download:/daileass/PDFDigitalSignatureBySelfSignedCertificate

This is the article about adding digital signatures to PDFs using packages. For more related content to add digital signatures to C# PDFs, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!