Add field for a digital signature to PDF
Asked Answered
P

1

8

I create a new PDF file using PDFsharp and MigraDoc. Now I want to add a field where the user can click on it and select a certificate for digital signing the file.

I found in the web, that this should be possible with AcroForms. But I wasn't able to use AcroForm because it is always null.

My current example code:

Document document = new Document();

Section section = document.AddSection();
section.AddParagraph("Signature Test");


PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer(false, PdfFontEmbedding.Always);
pdfRenderer.Document = document;
pdfRenderer.RenderDocument();

// NullPointerException at the following line. AcroForm is null 
pdfRenderer.PdfDocument.AcroForm.Elements.Add(PdfAcroForm.Keys.SigFlags, new PdfInteger(3));

const string filename = "HelloWorld.pdf";
pdfRenderer.PdfDocument.Save(filename);
Process.Start(filename);

Why is this property null? What can I do to set this to a correct value?

Or better, how can I add a field to select the digital certificate?

Pycnidium answered 26/8, 2019 at 8:51 Comment(0)
P
4

I found a solution that adds a signature field to the document. Unfortunately I had to use reflection because auf missing access to the requried objects.

using PdfSharp.Pdf;
using PdfSharp.Pdf.Annotations;
using System;
using System.Linq;
using System.Reflection;

internal sealed class MyPdfSignatureField : PdfAnnotation
{
    public MyPdfSignatureField(PdfDocument document, PdfRectangle rect) : base(document)
    {
        Elements.Add("/FT", new PdfName("/Sig"));
        Elements.Add(Keys.T, new PdfString("Signature1"));
        Elements.Add("/Ff", new PdfInteger(132));
        Elements.Add("/DR", new PdfDictionary());
        Elements.Add(Keys.Subtype, new PdfName("/Widget"));
        Elements.Add("/P", document.Pages[0]);


        PdfDictionary sign = new PdfDictionary(document);
        sign.Elements.Add(Keys.Type, new PdfName("/Sig"));
        sign.Elements.Add("/Filter", new PdfName("/Adobe.PPKLite"));
        sign.Elements.Add("/SubFilter", new PdfName("/adbe.pkcs7.detached"));
        sign.Elements.Add(Keys.M, new PdfDate(DateTime.Now));

        var irefTable = document
            .GetType()
            .GetField("_irefTable", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(document);
        var irefTableAdd = irefTable
            .GetType()
            .GetMethods()
            .Where(m => m.Name == "Add").Skip(1).FirstOrDefault();

        irefTableAdd.Invoke(irefTable, new object[] { sign });

        Elements.Add("/V", sign);

        Elements.Add("/Rect", rect);
        Flags = PdfAnnotationFlags.Print;
        Opacity = 1;
    }
}

And to use:

var sig = new MyPdfSignatureField(document, new PdfRectangle(new XPoint(480, 33.75), new XPoint(612.2, 62.1)));
document.Pages[0].Annotations.Add(sig);

This is no very nice solution but it covers my basic requirements. If you have some better idea, please let me know.

This idea of this class comes from here: https://github.com/empira/PDFsharp/pull/11/files

Pycnidium answered 27/8, 2019 at 8:15 Comment(6)
could you please tell me, in this code, where can I add the "Reason", "Location", Signature Mode and Certificate?Steppe
No sorry, I don't know what you mean. But the location of the field is defined by the secont parameter PdfRectangle rectPycnidium
This is create the blank signature box. How to assign certificate to the textbox? What pdf tag needed to identify certificateFlour
Sorry I've no idea. That wasn't a requirement for me.Pycnidium
Any idea how we can achieve it? Your above logic creates the blank box but I need to append the signature on button click event.Flour
Here is the new link that points to the content that @Sam mentioned. Support of digital signatures and Support of Digital Signatures and Attachment Annotations. Unfortunately, these modifications were never merged into the main.Schauer

© 2022 - 2024 — McMap. All rights reserved.