Custom Signing using JavaScript

The Apryse custom signing API is a set of APIs related to cryptographic digital signatures which allows users to customize the process of signing documents. Among other things, this includes the capability to allow for easy integration of PDF-specific signing-related operations with access to Hardware Security Module (HSM) tokens/devices, access to cloud keystores, access to system keystores, etc. The intent behind this API is to remove the old, tricky, and complicated requirement for users with specific needs to create custom SignatureHandler functor objects.

What follows is a simple code guide to the use of the custom signing API. Please note: any of the steps can be replaced with your own code that provides some custom functionality.

JavaScript (v8.0+)

1const doc = await documentViewer.getDocument().getPDFDoc();
2
3const page1 = await doc.getPage(1);
4
5// Create a digital signature field and associated widget.
6const digsig_field = await doc.createDigitalSignatureField(in_sig_field_name);
7const widgetAnnot = await PDFNet.SignatureWidget.createWithDigitalSignatureField(doc, new PDFNet.Rect(143, 287, 219, 306), digsig_field);
8await page1.annotPushBack(widgetAnnot);
9
10// Create a digital signature dictionary inside the digital signature field, in preparation for signing.
11await digsig_field.createSigDictForCustomSigning("Adobe.PPKLite",
12 in_PAdES_signing_mode? PDFNet.DigitalSignatureField.SubFilterType.e_ETSI_CAdES_detached : PDFNet.DigitalSignatureField.SubFilterType.e_adbe_pkcs7_detached,
13 7500); // For security reasons, set the contents size to a value greater than but as close as possible to the size you expect your final signature to be, in bytes.
14// ... or, if you want to apply a certification signature, use createSigDictForCustomCertification instead.
15
16// (OPTIONAL) Set the signing time in the signature dictionary, if no secure embedded timestamping support is available from your signing provider.
17const current_date = new PDFNet.Date();
18await current_date.setCurrentTime();
19await digsig_field.setSigDictTimeOfSigning(current_date);
20
21await doc.saveMemoryBuffer(PDFNet.SDFDoc.SaveOptions.e_incremental);
22
23// Digest the relevant bytes of the document in accordance with ByteRanges surrounding the signature.
24const pdf_digest = await digsig_field.calculateDigest(PDFNet.DigestAlgorithm.Type.e_SHA256);
25
26const signer_cert = await PDFNet.X509Certificate.createFromBuffer(in_cert_buf);
27
28/* Optionally, you can add a custom signed attribute at this point, such as one of the PAdES ESS attributes.
29The function we provide takes care of generating the correct PAdES ESS attribute depending on your digest algorithm. */
30const pades_versioned_ess_signing_cert_attribute = await PDFNet.DigitalSignatureField.generateESSSigningCertPAdESAttribute(signer_cert, PDFNet.DigestAlgorithm.Type.e_SHA256);
31
32// Generate the signedAttrs component of CMS, passing any optional custom signedAttrs (e.g. PAdES ESS). The signedAttrs are certain attributes that become protected by their inclusion in the signature.
33const signedAttrs = await PDFNet.DigitalSignatureField.generateCMSSignedAttributes(pdf_digest,
34 pades_versioned_ess_signing_cert_attribute);
35const signedAttrsCopy = signedAttrs.slice(); // make a copy for PDFNet.DigitalSignatureField.generateCMSSignature()
36
37// Calculate the digest of the signedAttrs (i.e. not the PDF digest, this time).
38const signedAttrs_digest = await PDFNet.DigestAlgorithm.calculateDigest(PDFNet.DigestAlgorithm.Type.e_SHA256, signedAttrs);

At this point, use your signing provider (e.g. HSM device, cloud keystore) to sign the digest of signedAttrs. Your input should be the variable signedAttrs_digest. In the following code, we assume the output is in a variable named signature_value.

JavaScript (v8.0+)

1// Then, load all your chain certificates into a container of X509Certificate.
2var chain_certs = [];
3
4// Then, create ObjectIdentifiers for the algorithms you have used.
5const digest_algorithm_oid = await PDFNet.ObjectIdentifier.createFromDigestAlgorithm(PDFNet.DigestAlgorithm.Type.e_SHA256);
6const signature_algorithm_oid = await PDFNet.ObjectIdentifier.createFromPredefined(PDFNet.ObjectIdentifier.Predefined.e_RSA_encryption_PKCS1);
7
8// Then, put the CMS signature components together.
9const cms_signature = await PDFNet.DigitalSignatureField.generateCMSSignature(
10 signer_cert, chain_certs, digest_algorithm_oid, signature_algorithm_oid, signature_value,
11 signedAttrsCopy);
12
13// Write the signature to the document.
14const buf = await doc.saveCustomSignatureBuffer(cms_signature, digsig_field);

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales