CustomHandler for ESign in PDF C# alongwith Embedded Timestamp

Product: PDFNet

Product Version:9.5

Please give a brief summary of your issue:
(Think of this as an email subject)
Not able to embed a timestamp in signatures printed using CustomHandler.

Please describe your issue and provide steps to reproduce it:
(The more descriptive your answer, the faster we are able to help you)

Please provide a link to a minimal sample where the issue is reproducible:

Our Use Case:
We want to Sign the PDF documents using the Certificates which are stored into the Certificate Store of a windows machine along with the Private Key. Hence, we cannot use other approach listed by PDFTron to pass the Certificate File and Password, because in our case we cannot fetch the password of the certificate installed in certificate store. So as understood from the PDFtron documentation we have only 1 way i.e. to use the Custom Handler where we can read the certificates from the store and then Sign the PDF using the CMSSigner from Microsoft library as suggested in the PDFTron documentation. I have shared below the code developed till now with your inputs which still has some open points. Please look the code below and then the following comments highlighted.
You may simply copy this code in an editor for a better visibility and indentation.

class DotNetCryptoSignatureHandler2 : SignatureHandler //Custom Signature Handler
{
private List m_data;
private string m_signingCert;

    public DotNetCryptoSignatureHandler2(string signingCert)
    {
        m_signingCert = signingCert;
        m_data = new List<byte>();
    }

    public override void AppendData(byte[] data)
    {
        m_data.AddRange(data);
    }

    public override bool Reset()
    {
        m_data.Clear();
        return (true);
    }

    public override byte[] CreateSignature()
    {
        try
        {
            ContentInfo ci = new ContentInfo(m_data.ToArray());
            SignedCms sc = new SignedCms(ci, true);
            var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
            store?.Open(OpenFlags.ReadOnly);
            var certObj = new X509Certificate2();
            foreach (X509Certificate2 x509Certificate2 in store?.Certificates)
            {
                if (x509Certificate2.SubjectName.Name.Equals("CN=" + m_signingCert))
                {
                    certObj = x509Certificate2;
                }
            }
            CmsSigner cs = new CmsSigner(certObj);

            cs.DigestAlgorithm = new Oid("2.16.840.1.101.3.4.2.1");//SHA256
            sc.ComputeSignature(cs);
            byte[] sig = sc.Encode();
            return (sig);
        }
        catch (Exception e)
        {
            Console.Error.WriteLine(e);
        }
        return (null);
    }
    public override string GetName()
    {
        return ("fghfgh");
    }
}

static void CertifyPDF(string in_docpath,
string in_cert_field_name, //CommonName of certificate in store
string in_outpath, bool flag)
{

        // Open an existing PDF
        using (PDFDoc doc = new PDFDoc(in_docpath))
        {

            Page page1 = doc.GetPage(1);

            DigitalSignatureField certification_sig_field = doc.CreateDigitalSignatureField(Guid.NewGuid().ToString());

            SignatureWidget widgetAnnot = SignatureWidget.Create(doc, new Rect(143, 287 , 419, 406), certification_sig_field);

            widgetAnnot.SetFontSize(30);
            widgetAnnot.SetTextColor(new ColorPt(255), 3);
            widgetAnnot.RefreshAppearance();
            widgetAnnot.SetAppearance(CreateCustomButtonAppearance(doc, false, in_cert_field_name));
            widgetAnnot.SetBorderStyle(new Annot.BorderStyle(Annot.BorderStyle.Style.e_solid, 2));
            widgetAnnot.SetBorderColor(new ColorPt(0, 0, 0), 3);

            page1.AnnotPushBack(widgetAnnot);

            certification_sig_field.SetDocumentPermissions(DigitalSignatureField.DocumentPermissions.e_annotating_formfilling_signing_allowed);

            doc.Save(in_outpath, SDFDoc.SaveOptions.e_incremental);

            DotNetCryptoSignatureHandler2 sigHandler = new DotNetCryptoSignatureHandler2(in_cert_field_name);
            SignatureHandlerId sigHandlerId = doc.AddSignatureHandler(sigHandler);
            certification_sig_field.SignOnNextSaveWithCustomHandler(sigHandlerId);

            Obj f_obj = certification_sig_field.GetSDFObj();
            f_obj.FindObj("V").PutName("SubFilter", "adbe.pkcs7.detached");
            
            // (OPTIONAL) Add more information to the signature dictionary.
            certification_sig_field.SetLocation("Pune " + Guid.NewGuid());
            certification_sig_field.SetReason("Document eSign." + Guid.NewGuid());
            certification_sig_field.SetContactInfo("CIS_PQM_team" + Guid.NewGuid());

            doc.Save(in_outpath, SDFDoc.SaveOptions.e_incremental); //{Till this line all the code is executed successfully, I can see the sign In //output PDF file, now I execute the further code to embed the timestamp which is required}
			
            TimestampingConfiguration tst_config = new TimestampingConfiguration("http://rfc3161timestamp.globalsign.com/advanced");
            VerificationOptions opts = new VerificationOptions(VerificationOptions.SignatureVerificationSecurityLevel.e_compatibility_and_archiving);
            opts.AddTrustedCertificate(@"C:\Users\ABC\Downloads\Root-R3.crt");
            opts.EnableOnlineCRLRevocationChecking(true);
            TimestampingResult result = certification_sig_field.GenerateContentsWithEmbeddedTimestamp(tst_config, opts);

            if (!result.GetStatus())
            {
                Console.WriteLine(result.GetString());
                throw new Exception();
            }
            doc.SaveCustomSignature(result.GetData(), certification_sig_field, in_outpath);//{This line gives error saying insufficient space. Detailed error message is below this code : }
        }
        Console.Out.WriteLine("================================================================================");
    }

Exception:
Message: An error occurred while trying to save the file.
The file might be locked, corrupt, or unavailable.
Detailed error:
Insufficient space reserved for signature within DigitalSignatureField digital signature dictionary’s Contents string. To fix, clear this signature if editing an existing signature, then create a new signature dictionary with more space, then attempt to sign again. Required space (bytes): 7820, available space (bytes): 1259
Conditional expression: false
Version : 9.5.0-1bc49d6a54
Platform : .Net Framework
Architecture : x86
Filename : SDFDocImplSave.cpp
Function : trn::SDF::DocImpl::SaveCustomSignatureToPath
Linenumber : 1413

Can you please help us with an approach where I can reserve more space for the signature?
I tried the below code, but this is not allowed when we are using CustomHandler. Is there any way we can embed the timestamp using CustomHandler to sign a document.
certification_sig_field.CreateSigDictForCustomCertification(“fghfgh”, DigitalSignatureField.SubFilterType.e_adbe_pkcs7_detached,
8200);

Or how can we embed the timestamp in the custom handler itself?

Thanks and Regards,
Mayuresh Deshmukh.
mayuresh.deshmukh@siemens.com

Thank you for contacting us about this. We are looking into this and will get back to you soon with an update.

I had the same thing happening to me a few days ago.
I fixed by establishing more bytes on the line where I assign the adbe.pkcs7.detached subfilter. (the example had 9500, I bumped up to 23000)
My code is in C++ but you will get gist of it.
On C++ the function CreateSigDictForCustomCertification takes a number of bytes argument at the end, maybe there is an equivalent con C# instead of what you are using.

Hope it helps.

Santiago G.

// Create a digital signature dictionary inside the digital signature field, in preparation for signing.
    digsig_field.CreateSigDictForCustomCertification("Adobe.PPKLite", PDF::DigitalSignatureField::SubFilterType::e_adbe_pkcs7_detached, 23000);

Please see below for a full C# code sample on how to use our custom handler to sign using a certificate from the Microsoft Windows Certificate store:

dig_sig.cs (4.0 KB)

1 Like

Hi, This doesn’t works with Custom Handler approach. Thanks.

Thanks Shakthi. This works perfectly fine.