Available Now: Explore our latest release with enhanced accessibility and powerful IDP features

Adding a Digital Signature to a PDF using JavaScript with Node.js SDK

By Andrew Varley, Josh Coffey | 2023 Aug 11

Sanity Image
Read time

5 min

Few things are as ubiquitous as Digital Signatures these days, and yet most documents are still signed with physical pens and paper in the world. As more Enterprise processes digitize, the growth in digital signatures will continue to explode, and making sure your application supports this need is more critical than ever. Besides the obvious benefits of being able to sign on a computer, there are several other advantages of Digital signatures, the electronic equivalents of physical or ink-and-paper signatures, such as:

  • Authentication: A digital signature allows for the precise identification of the signer. When a signature is valid, you can safely assume that you know who signed the document.
  • Integrity: A digital signature allows users to easily validate whether the contents of a document have been changed since it was signed.
  • Non-repudiation: A digital signature ensures that the signer cannot deny that they signed the document.

The Apryse SDK is a powerful tool that can be used to create and manage digital signatures. It includes a number of benefits, such as:

  • Import and export signature fields: The Apryse SDK can be used to import and export signature fields from XFDF/FDF files. This makes it easy to integrate with existing document workflows.
  • Built-in support for PKI signing: The Apryse SDK includes built-in support for PKI signing (and PFX digital certificates). This makes it easy to create secure and legally binding digital signatures.
  • Support for custom signature handlers: The Apryse SDK allows you to create custom signature handlers. This gives you the flexibility to customize the appearance and behavior of digital signatures.
  • Sign with images, ink annotations, or entirely custom appearances: The Apryse SDK allows you to sign documents with images, ink annotations, or entirely custom appearances. This gives you the freedom to create digital signatures that are both secure and visually appealing.

Quote

Ensure Legal Compliance and Secure Your Documents - Discover the Benefits of PDF/A and Digital Signatures

In our Ultimate Guide to Digital Signatures, we looked at each area of the digital signature technology stack and how the Apryse Developer Suite can solve your signature use cases. We’ll give a short overview here, though you should refer to that article for the full story since this blog will focus on the actual nuts and bolts of signing a PDF in JavaScript with our Node.js SDK.

Before we begin, you should know there is an important distinction between e-Signatures and Digital Signatures.

E-Signatures and Digital Signatures: What’s the Difference?

Copied to clipboard

E-signatures are electronic annotations that appear in a document. They do not contain any additional identifiable information about the creator other than an author field, which can be altered.

Digital signatures are a more secure form of electronic signature. They use a cryptographic algorithm to uniquely identify the author of a document. Any alterations to the document, including the annotations or e-signature, will result in an invalid digital signature validation.

Here is a table that summarizes the key differences between e-signatures and digital signatures:

Feature:

Information about creator

Security

Tamper resistance

Legal validity

E-signature

Author field only

Less secure

Can be altered

Varies by jurisdiction

Digital signature

Author's public key

More secure

Can't be altered

More widely accepted

With that out of the way, we’ll now walk through how to add an approval signature field and digitally sign it all using Apryse’s Node.js SDK.

Setup for development

Copied to clipboard

To start, head over to our documentation and download the latest SDK build and test files for your operating system. Next, you’ll want to Initialize the Apryse SDK with our trial license, which you can get for free after downloading, see the Get Started link for more details.

Adding a Digital Signature Approval Field

Copied to clipboard

To begin, we need to add an Approval Field to the document, which is used to indicate to the next participant in the process where to digitally sign the field.

Blog image

Original file without a signature field.

We want to put a signature box directly on the file, which will be a rectangle with a height and width set in pixels. This code places the signature annotation onto the PDF and saves the output for the next step in the process.

const { PDFNet } = require('@pdftron/pdfnet-node');

// Initialize PDFNet
PDFNet.initialize(licenseKey);

const inputFilePath = './pdf-sample.pdf';
const outputFilePath = './pdf-sample-with-signature.pdf';

// Open an existing PDF document
const doc = await PDFNet.PDFDoc.createFromFilePath(inputFilePath);

// Create a signature field that we can sign
const signatureWidget = await PDFNet.SignatureWidget.create(doc, PDFNet.Rect(300, 287, 376, 306), 'ApryseApprovalSig');

// Add the signature widget to page 1 of the PDF
const page1 = await doc.getPage(1);
await page1.annotPushBack(signatureWidget);

// Save a new PDF with the signature field
await doc.save(outputFilePath, PDFNet.SDFDoc.SaveOptions.e_remove_unused);
Blog image

Adding a Certified Signature Field to a PDF

Copied to clipboard

In certain scenarios involving a third-party entity between a sender and other parties, the use of a Certificate Authority becomes essential. However, when a CA is unavailable or not required for your use case, a self-signed certificate can be utilized instead, as demonstrated in our digital signature sample or WebViewer demo. Please note that Apryse does not offer CA services; therefore, it is the responsibility of users to incorporate a CA into their digital signature workflow if required for their specific use cases.

For our example, we’ll add our certificate into the PDF. We need to first add a text field that can be used to lock the field permissions. It’s also important to add your digital signature field into a Widget, as some PDF Editors will not properly show that field to the user in a friendly way. We can make the dimensions of the widget 0 and add a NoPrint/Invisible flag which will make it invisible. We then set the field-level permissions to be restricted and attach our logo to the widget. Finally, we can add additional information into the signature dictionary of the PDF, including HQ headquarters, website, or contact information.

Quote




Create, annotate, and digitally sign PDFs in your browser with Apryse WebViewer. Start your document workflow now!



// Open existing PDF.
const doc = await PDFNet.PDFDoc.createFromFilePath(in_docpath);
doc.initSecurityHandler();

const page1 = await doc.getPage(1);

// Create a text field that we can lock using the field permissions feature.
const annot1 = await PDFNet.TextWidget.create(doc, new PDFNet.Rect(143, 440, 350, 460), 'asdf_test_field');
await page1.annotPushBack(annot1);

/* Create a new signature form field in the PDFDoc. The name argument is optional;
leaving it empty causes it to be auto-generated. However, you may need the name for later.
Acrobat doesn't show digsigfield in side panel if it's without a widget. Using a
Rect with 0 width and 0 height, or setting the NoPrint/Invisible flags makes it invisible. */
const certification_sig_field = await doc.createDigitalSignatureField(in_cert_field_name);
const widgetAnnot = await PDFNet.SignatureWidget.createWithDigitalSignatureField(doc, new PDFNet.Rect(143, 287, 219, 306), certification_sig_field);
await page1.annotPushBack(widgetAnnot);

// (OPTIONAL) Add an appearance to the signature field.
const img = await PDFNet.Image.createFromFile(doc, in_appearance_image_path);
await widgetAnnot.createSignatureAppearance(img);

// Prepare the document locking permission level. It will be applied upon document certification.
await certification_sig_field.setDocumentPermissions(PDFNet.DigitalSignatureField.DocumentPermissions.e_annotating_formfilling_signing_allowed);

// Prepare to lock the text field that we created earlier.
var fields_to_lock = ['asdf_test_field'];
await certification_sig_field.setFieldPermissions(PDFNet.DigitalSignatureField.FieldPermissions.e_include, fields_to_lock);

await certification_sig_field.certifyOnNextSave(in_private_key_file_path, in_keyfile_password);

// (OPTIONAL) Add more information to the signature dictionary.
await certification_sig_field.setLocation('Denver, CO');
await certification_sig_field.setReason('Document certification.');
await certification_sig_field.setContactInfo('www.apryse.com');

// Save the PDFDoc. Once the method below is called, PDFNet will also sign the document using the information provided.
await doc.save(in_outpath, 0);

Digitally Signing the PDF

Copied to clipboard

Now that the document has an approval field and has been certified, it’s time to digitally sign the PDF. We are using an image of our signature in this example and applying it to the widget and field that we created for the signer. In more complex examples or multi-signature PDF portfolios or pages, we can loop through the DigitalSignatureField to apply the same or different sets of signatures.

// Open an existing PDF
const doc = await PDFNet.PDFDoc.createFromFilePath(in_docpath);
doc.initSecurityHandler();

// Retrieve the unsigned approval signature field.
const found_approval_field = await doc.getField(in_approval_field_name);
const found_approval_signature_digsig_field = await PDFNet.DigitalSignatureField.createFromField(found_approval_field);

// (OPTIONAL) Add an appearance to the signature field.
const img = await PDFNet.Image.createFromFile(doc, in_appearance_img_path);
const found_approval_signature_widget = await PDFNet.SignatureWidget.createFromObj(await found_approval_field.getSDFObj());
await found_approval_signature_widget.createSignatureAppearance(img);

// Prepare the signature and signature handler for signing.
await found_approval_signature_digsig_field.signOnNextSave(in_private_key_file_path, in_keyfile_password);

// The actual approval signing will be done during the following incremental save operation.
await doc.save(in_outpath, PDFNet.SDFDoc.SaveOptions.e_incremental);

The final version of the document now has a digitally trusted signature that can be verified to ensure the document has not been tampered with since being signed.

Blog image

Verified using Apryse’s WebViewer.

Conclusion

Copied to clipboard

And there you have it, a digitally signed and verified PDF document! We hope you have found this guide useful, and you can check out the documentation for our JavaScript and Node.js Digital Signature Library. Don’t forget you can also reach out to us on Discord if you have any issues.

Sanity Image

Andrew Varley

Chief Product Officer

Sanity Image

Josh Coffey

Chief Technology Officer

Share this post

email
linkedIn
twitter