Sample JavaScript code to use Apryse SDK's high-level digital signature API for digitally signing and/or certifying PDF files.
This sample is utilizing the option to run code programmatically, without the Viewer. Need this functionality in another language or framework? Check out Server SDK Digital Signature Sample.
Learn more about our Web SDK and PDF Digital Signature Library.
Step 1: Follow get started in your preferred web stack for WebViewer
Step 2: Follow set up to implement Full API code without viewer
Step 3: Add the sample code provided in this guide
1//---------------------------------------------------------------------------------------
2// Copyright (c) 2001-2023 by Apryse Software Inc. All Rights Reserved.
3// Consult legal.txt regarding legal and license information.
4//---------------------------------------------------------------------------------------
5
6(exports => {
7  exports.runDigitalSignaturesTest = () => {
8    const PDFNet = exports.Core.PDFNet;
9
10    const input_path = '../TestFiles/';
11
12    const VerifySimple = async (in_docpath, in_public_key_file_path) => {
13      const doc = await PDFNet.PDFDoc.createFromURL(in_docpath);
14      doc.initSecurityHandler();
15      doc.lock();
16      console.log('==========');
17      const opts = await PDFNet.VerificationOptions.create(PDFNet.VerificationOptions.SecurityLevel.e_compatibility_and_archiving);
18
19      // Add trust root to store of trusted certificates contained in VerificationOptions.
20      await opts.addTrustedCertificateFromURL(
21        in_public_key_file_path,
22        {},
23        PDFNet.VerificationOptions.CertificateTrustFlag.e_default_trust + PDFNet.VerificationOptions.CertificateTrustFlag.e_certification_trust
24      );
25
26      const result = await doc.verifySignedDigitalSignatures(opts);
27      switch (result) {
28        case PDFNet.PDFDoc.SignaturesVerificationStatus.e_unsigned:
29          console.log('Document has no signed signature fields.');
30          return false;
31        /* e_failure == bad doc status, digest status, or permissions status
32        (i.e. does not include trust issues, because those are flaky due to being network/config-related) */
33        case PDFNet.PDFDoc.SignaturesVerificationStatus.e_failure:
34          console.log('Hard failure in verification on at least one signature.');
35          return false;
36        case PDFNet.PDFDoc.SignaturesVerificationStatus.e_untrusted:
37          console.log('Could not verify trust for at least one signature.');
38          return false;
39        case PDFNet.PDFDoc.SignaturesVerificationStatus.e_unsupported:
40          /* If necessary, call GetUnsupportedFeatures on VerificationResult to check which
41          unsupported features were encountered (requires verification using 'detailed' APIs) */
42          console.log('At least one signature contains unsupported features.');
43          return false;
44        // unsigned sigs skipped; parts of document may be unsigned (check GetByteRanges on signed sigs to find out)
45        case PDFNet.PDFDoc.SignaturesVerificationStatus.e_verified:
46          console.log('All signed signatures in document verified.');
47          return true;
48      }
49
50      return false;
51    };
52
53    const VerifyAllAndPrint = async (in_docpath, in_public_key_file_path) => {
54      const doc = await PDFNet.PDFDoc.createFromURL(in_docpath);
55      doc.initSecurityHandler();
56      doc.lock();
57      console.log('==========');
58      const opts = await PDFNet.VerificationOptions.create(PDFNet.VerificationOptions.SecurityLevel.e_compatibility_and_archiving);
59
60      // Add trust root to store of trusted certificates contained in VerificationOptions.
61      // Use trust level corresponding to an identity trusted even for certification signatures.
62      await opts.addTrustedCertificateFromURL(
63        in_public_key_file_path,
64        {},
65        PDFNet.VerificationOptions.CertificateTrustFlag.e_default_trust + PDFNet.VerificationOptions.CertificateTrustFlag.e_certification_trust
66      );
67
68      // Iterate over the signatures and verify all of them.
69      const digsig_fitr = await doc.getDigitalSignatureFieldIteratorBegin();
70      let verification_status = true;
71      for (; await digsig_fitr.hasNext(); await digsig_fitr.next()) {
72        const curr = await digsig_fitr.current();
73        const result = await curr.verify(opts);
74        if (await result.getVerificationStatus()) {
75          console.log('Signature verified, objnum: ' + (await (await curr.getSDFObj()).getObjNum()));
76        } else {
77          console.log('Signature verification failed, objnum: ' + (await (await curr.getSDFObj()).getObjNum()));
78          verification_status = false;
79        }
80
81        switch (await result.getDigestAlgorithm()) {
82          case PDFNet.DigestAlgorithm.Type.e_SHA1:
83            console.log('Digest algorithm: SHA-1');
84            break;
85          case PDFNet.DigestAlgorithm.Type.e_SHA256:
86            console.log('Digest algorithm: SHA-256');
87            break;
88          case PDFNet.DigestAlgorithm.Type.e_SHA384:
89            console.log('Digest algorithm: SHA-384');
90            break;
91          case PDFNet.DigestAlgorithm.Type.e_SHA512:
92            console.log('Digest algorithm: SHA-512');
93            break;
94          case PDFNet.DigestAlgorithm.Type.e_RIPEMD160:
95            console.log('Digest algorithm: RIPEMD-160');
96            break;
97          case PDFNet.DigestAlgorithm.Type.e_unknown_digest_algorithm:
98            console.log('Digest algorithm: unknown');
99            break;
100        }
101
102        console.log(
103          'Detailed verification result: \n\t' +
104            (await result.getDocumentStatusAsString()) +
105            '\n\t' +
106            (await result.getDigestStatusAsString()) +
107            '\n\t' +
108            (await result.getTrustStatusAsString()) +
109            '\n\t' +
110            (await result.getPermissionsStatusAsString())
111        );
112
113        const changes = await result.getDisallowedChanges();
114        for (let i = 0; i < changes.length; ++i) {
115          const change = changes[i];
116          console.log('\tDisallowed change: ' + (await change.getTypeAsString()) + ', objnum: ' + (await change.getObjNum()));
117        }
118
119        // Get and print all the detailed trust-related results, if they are available.
120        if (await result.hasTrustVerificationResult()) {
121          const trust_verification_result = await result.getTrustVerificationResult();
122          console.log((await trust_verification_result.wasSuccessful()) ? 'Trust verified.' : 'Trust not verifiable.');
123          console.log(await trust_verification_result.getResultString());
124
125          const tmp_time_t = await trust_verification_result.getTimeOfTrustVerification();
126          switch (await trust_verification_result.getTimeOfTrustVerificationEnum()) {
127            case PDFNet.VerificationOptions.TimeMode.e_current:
128              console.log('Trust verification attempted with respect to current time (as epoch time):' + tmp_time_t);
129              break;
130            case PDFNet.VerificationOptions.TimeMode.e_signing:
131              console.log('Trust verification attempted with respect to signing time (as epoch time): ' + tmp_time_t);
132              break;
133            case PDFNet.VerificationOptions.TimeMode.e_timestamp:
134              console.log('Trust verification attempted with respect to secure embedded timestamp (as epoch time): ' + tmp_time_t);
135              break;
136          }
137
138          const cert_path = await trust_verification_result.getCertPath();
139          if (cert_path.length === 0) {
140            console.log('Could not print certificate path.');
141          } else {
142            console.log('Certificate path:');
143            for (let i = 0; i < cert_path.length; i++) {
144              console.log('\tCertificate:');
145              const full_cert = cert_path[i];
146              console.log('\t\tIssuer names:');
147              const issuer_dn = await (await full_cert.getIssuerField()).getAllAttributesAndValues();
148              for (let j = 0; j < issuer_dn.length; j++) {
149                console.log('\t\t\t' + (await issuer_dn[j].getStringValue()));
150              }
151              console.log('\t\tSubject names:');
152              const subject_dn = await (await full_cert.getSubjectField()).getAllAttributesAndValues();
153              for (let j = 0; j < subject_dn.length; j++) {
154                console.log('\t\t\t' + (await subject_dn[j].getStringValue()));
155              }
156              console.log('\t\tExtensions:');
157              const extension_dn = await full_cert.getExtensions();
158              for (let j = 0; j < extension_dn.length; j++) {
159                console.log('\t\t\t' + (await extension_dn[j].toString()));
160              }
161            }
162          }
163        } else {
164          console.log('No detailed trust verification result available.');
165        }
166
167        console.log('==========');
168      }
169
170      return verification_status;
171    };
172
173    const CertifyPDF = async (in_docpath, in_cert_field_name, in_private_key_file_path, in_keyfile_password, in_appearance_image_path, in_outpath) => {
174      console.log('================================================================================');
175      console.log('Certifying PDF document');
176
177      // Open existing PDF.
178      const doc = await PDFNet.PDFDoc.createFromURL(in_docpath);
179      doc.initSecurityHandler();
180      doc.lock();
181
182      console.log('PDFDoc has ' + ((await doc.hasSignatures()) ? 'signatures' : 'no signatures'));
183
184      const page1 = await doc.getPage(1);
185
186      // Create a text field that we can lock using the field permissions feature.
187      const annot1 = await PDFNet.TextWidget.create(doc, new PDFNet.Rect(50, 550, 350, 600), 'asdf_test_field');
188      await page1.annotPushBack(annot1);
189
190      /* Create a new signature form field in the PDFDoc. The name argument is optional;
191      leaving it empty causes it to be auto-generated. However, you may need the name for later.
192      Acrobat doesn't show digsigfield in side panel if it's without a widget. Using a
193      Rect with 0 width and 0 height, or setting the NoPrint/Invisible flags makes it invisible. */
194      const certification_sig_field = await doc.createDigitalSignatureField(in_cert_field_name);
195      const widgetAnnot = await PDFNet.SignatureWidget.createWithDigitalSignatureField(doc, new PDFNet.Rect(0, 100, 200, 150), certification_sig_field);
196      await page1.annotPushBack(widgetAnnot);
197
198      // (OPTIONAL) Add an appearance to the signature field.
199      const img = await PDFNet.Image.createFromURL(doc, in_appearance_image_path);
200      await widgetAnnot.createSignatureAppearance(img);
201
202      // Prepare the document locking permission level. It will be applied upon document certification.
203      console.log('Adding document permissions.');
204      await certification_sig_field.setDocumentPermissions(PDFNet.DigitalSignatureField.DocumentPermissions.e_annotating_formfilling_signing_allowed);
205
206      // Prepare to lock the text field that we created earlier.
207      console.log('Adding field permissions.');
208      const fields_to_lock = ['asdf_test_field'];
209      await certification_sig_field.setFieldPermissions(PDFNet.DigitalSignatureField.FieldPermissions.e_include, fields_to_lock);
210
211      await certification_sig_field.certifyOnNextSaveFromURL(in_private_key_file_path, in_keyfile_password);
212
213      // (OPTIONAL) Add more information to the signature dictionary.
214      await certification_sig_field.setLocation('Vancouver, BC');
215      await certification_sig_field.setReason('Document certification.');
216      await certification_sig_field.setContactInfo('www.pdftron.com');
217
218      // Save the PDFDoc. Once the method below is called, PDFNet will also sign the document using the information provided.
219      const docbuf = await doc.saveMemoryBuffer(0);
220      saveBufferAsPDFDoc(docbuf, in_outpath);
221
222      console.log('================================================================================');
223
224      return docbuf;
225    };
226
227    const SignPDF = async (in_docpath, in_approval_field_name, in_private_key_file_path, in_keyfile_password, in_appearance_img_path, in_outpath) => {
228      console.log('================================================================================');
229      console.log('Signing PDF document');
230
231      // Open an existing PDF
232      const doc = await PDFNet.PDFDoc.createFromURL(in_docpath);
233      doc.initSecurityHandler();
234      doc.lock();
235
236      // Retrieve the unsigned approval signature field.
237      const found_approval_field = await doc.getField(in_approval_field_name);
238      const found_approval_signature_digsig_field = await PDFNet.DigitalSignatureField.createFromField(found_approval_field);
239
240      // (OPTIONAL) Add an appearance to the signature field.
241      const img = await PDFNet.Image.createFromURL(doc, in_appearance_img_path);
242      const found_approval_signature_widget = await PDFNet.SignatureWidget.createFromObj(await found_approval_field.getSDFObj());
243      await found_approval_signature_widget.createSignatureAppearance(img);
244
245      // Prepare the signature and signature handler for signing.
246      await found_approval_signature_digsig_field.signOnNextSaveFromURL(in_private_key_file_path, in_keyfile_password);
247
248      // The actual approval signing will be done during the following incremental save operation.
249      const docbuf = await doc.saveMemoryBuffer(PDFNet.SDFDoc.SaveOptions.e_incremental);
250      saveBufferAsPDFDoc(docbuf, in_outpath);
251
252      console.log('================================================================================');
253
254      return docbuf;
255    };
256
257    const ClearSignature = async (in_docpath, in_digsig_field_name, in_outpath) => {
258      console.log('================================================================================');
259      console.log('Clearing certification signature');
260
261      const doc = await PDFNet.PDFDoc.createFromURL(in_docpath);
262      doc.initSecurityHandler();
263      doc.lock();
264
265      const digsig = await PDFNet.DigitalSignatureField.createFromField(await doc.getField(in_digsig_field_name));
266
267      console.log('Clearing signature: ' + in_digsig_field_name);
268      await digsig.clearSignature();
269
270      if (!(await digsig.hasCryptographicSignature())) {
271        console.log('Cryptographic signature cleared properly.');
272      }
273
274      // Save incrementally so as to not invalidate other signatures from previous saves.
275      const docbuf = await doc.saveMemoryBuffer(PDFNet.SDFDoc.SaveOptions.e_incremental);
276      saveBufferAsPDFDoc(docbuf, in_outpath);
277
278      console.log('================================================================================');
279
280      return docbuf;
281    };
282
283    const PrintSignaturesInfo = async in_docbuffer => {
284      console.log('================================================================================');
285      console.log('Reading and printing digital signature information');
286
287      const doc = await PDFNet.PDFDoc.createFromBuffer(in_docbuffer);
288      doc.initSecurityHandler();
289      doc.lock();
290      if (!(await doc.hasSignatures())) {
291        console.log('Doc has no signatures.');
292        console.log('================================================================================');
293        return;
294      }
295      console.log('Doc has signatures.');
296
297      for (const fitr = await doc.getFieldIteratorBegin(); await fitr.hasNext(); await fitr.next()) {
298        const field = await fitr.current();
299        // eslint-disable-next-line no-unused-expressions
300        (await field.isLockedByDigitalSignature()) ? console.log('==========\nField locked by a digital signature') : console.log('==========\nField not locked by a digital signature');
301
302        console.log('Field name: ' + (await field.getName()));
303        console.log('==========');
304      }
305
306      console.log('====================\nNow iterating over digital signatures only.\n====================');
307
308      const digsig_fitr = await doc.getDigitalSignatureFieldIteratorBegin();
309      for (; await digsig_fitr.hasNext(); await digsig_fitr.next()) {
310        console.log('==========');
311        const digsigfield = await digsig_fitr.current();
312        console.log('Field name of digital signature: ' + (await (await PDFNet.Field.create(await digsigfield.getSDFObj())).getName()));
313
314        if (!(await digsigfield.hasCryptographicSignature())) {
315          console.log(
316            'Either digital signature field lacks a digital signature dictionary, ' +
317              'or digital signature dictionary lacks a cryptographic Contents entry. ' +
318              'Digital signature field is not presently considered signed.\n' +
319              '=========='
320          );
321          continue;
322        }
323
324        const cert_count = await digsigfield.getCertCount();
325        console.log('Cert count: ' + cert_count);
326        for (let i = 0; i < cert_count; i++) {
327          const cert = await digsigfield.getCert(i);
328          console.log('Cert #' + i + ' size: ' + cert.byteLength);
329        }
330
331        const subfilter = await digsigfield.getSubFilter();
332
333        console.log('Subfilter type: ' + subfilter);
334
335        if (subfilter !== PDFNet.DigitalSignatureField.SubFilterType.e_ETSI_RFC3161) {
336          console.log("Signature's signer: " + (await digsigfield.getSignatureName()));
337
338          const signing_time = await digsigfield.getSigningTime();
339          if (await signing_time.isValid()) {
340            console.log('Signing time is valid.');
341          }
342
343          console.log('Location: ' + (await digsigfield.getLocation()));
344          console.log('Reason: ' + (await digsigfield.getReason()));
345          console.log('Contact info: ' + (await digsigfield.getContactInfo()));
346        } else {
347          console.log('SubFilter == e_ETSI_RFC3161 (DocTimeStamp; no signing info)');
348        }
349
350        console.log((await digsigfield.hasVisibleAppearance()) ? 'Visible' : 'Not visible');
351
352        const digsig_doc_perms = await digsigfield.getDocumentPermissions();
353        const locked_fields = await digsigfield.getLockedFields();
354        for (let i = 0; i < locked_fields.length; i++) {
355          console.log('This digital signature locks a field named: ' + locked_fields[i]);
356        }
357
358        switch (digsig_doc_perms) {
359          case PDFNet.DigitalSignatureField.DocumentPermissions.e_no_changes_allowed:
360            console.log('No changes to the document can be made without invalidating this digital signature.');
361            break;
362          case PDFNet.DigitalSignatureField.DocumentPermissions.e_formfilling_signing_allowed:
363            console.log('Page template instantiation, form filling, and signing digital signatures are allowed without invalidating this digital signature.');
364            break;
365          case PDFNet.DigitalSignatureField.DocumentPermissions.e_annotating_formfilling_signing_allowed:
366            console.log('Annotating, page template instantiation, form filling, and signing digital signatures are allowed without invalidating this digital signature.');
367            break;
368          case PDFNet.DigitalSignatureField.DocumentPermissions.e_unrestricted:
369            console.log('Document not restricted by this digital signature.');
370            break;
371        }
372        console.log('==========');
373      }
374
375      console.log('================================================================================');
376    };
377
378    const CustomSigningAPI = async (
379      doc_path,
380      cert_field_name,
381      private_key_file_path,
382      keyfile_password,
383      public_key_file_path,
384      appearance_image_path,
385      digest_algorithm_type,
386      PAdES_signing_mode,
387      output_path
388    ) => {
389      console.log('================================================================================');
390      console.log('Custom signing PDF document');
391
392      const doc = await PDFNet.PDFDoc.createFromURL(doc_path);
393      doc.initSecurityHandler();
394
395      const page1 = await doc.getPage(1);
396
397      const digsig_field = await doc.createDigitalSignatureField(cert_field_name);
398      const widgetAnnot = await PDFNet.SignatureWidget.createWithDigitalSignatureField(doc, new PDFNet.Rect(143, 287, 219, 306), digsig_field);
399      await page1.annotPushBack(widgetAnnot);
400
401      // (OPTIONAL) Add an appearance to the signature field.
402      const img = await PDFNet.Image.createFromURL(doc, appearance_image_path);
403      await widgetAnnot.createSignatureAppearance(img);
404
405      // Create a digital signature dictionary inside the digital signature field, in preparation for signing.
406      await digsig_field.createSigDictForCustomSigning(
407        'Adobe.PPKLite',
408        PAdES_signing_mode ? PDFNet.DigitalSignatureField.SubFilterType.e_ETSI_CAdES_detached : PDFNet.DigitalSignatureField.SubFilterType.e_adbe_pkcs7_detached,
409        7500
410      ); // 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.
411      //          ... or, if you want to apply a certification signature, use CreateSigDictForCustomCertification instead.
412
413      // (OPTIONAL) Set the signing time in the signature dictionary, if no secure embedded timestamping support is available from your signing provider.
414      const current_date = new PDFNet.Date();
415      await current_date.setCurrentTime();
416      await digsig_field.setSigDictTimeOfSigning(current_date);
417
418      await doc.saveMemoryBuffer(PDFNet.SDFDoc.SaveOptions.e_incremental);
419
420      // Digest the relevant bytes of the document in accordance with ByteRanges surrounding the signature.
421      const pdf_digest = await digsig_field.calculateDigest(digest_algorithm_type);
422
423      const signer_cert = await PDFNet.X509Certificate.createFromURL(public_key_file_path);
424
425      // Optionally, you can add a custom signed attribute at this point, such as one of the PAdES ESS attributes.
426      // The function we provide takes care of generating the correct PAdES ESS attribute depending on your digest algorithm.
427      const pades_versioned_ess_signing_cert_attribute = await PDFNet.DigitalSignatureField.generateESSSigningCertPAdESAttribute(signer_cert, digest_algorithm_type);
428
429      // Generate the signedAttrs component of CMS, passing any optional custom signedAttrs (e.g. PAdES ESS).
430      // The signedAttrs are certain attributes that become protected by their inclusion in the signature.
431      const signedAttrs = await PDFNet.DigitalSignatureField.generateCMSSignedAttributes(pdf_digest, pades_versioned_ess_signing_cert_attribute);
432      const signedAttrsCopy = signedAttrs.slice(); // make a copy for PDFNet.DigitalSignatureField.generateCMSSignature()
433
434      // Calculate the digest of the signedAttrs (i.e. not the PDF digest, this time).
435      const signedAttrs_digest = await PDFNet.DigestAlgorithm.calculateDigest(digest_algorithm_type, signedAttrs);
436
437      // ///////////////////////// custom digest signing starts ////////////////////////////
438      // At this point, you can sign the digest (for example, with HSM). We use our own SignDigest function instead here as an example,
439      // which you can also use for your purposes if necessary as an alternative to the handler/callback APIs (i.e. Certify/SignOnNextSave).
440      const signature_value = await PDFNet.DigestAlgorithm.signDigestWithKeyfileFromURL(signedAttrs_digest, digest_algorithm_type, private_key_file_path, keyfile_password);
441      // ///////////////////////// custom digest signing ends //////////////////////////////
442
443      // Then, load all your chain certificates into a container of X509Certificate.
444      const chain_certs = [];
445
446      // Then, create ObjectIdentifiers for the algorithms you have used.
447      // Here we use digest_algorithm_type (usually SHA256) for hashing, and RSAES-PKCS1-v1_5 (specified in the private key) for signing.
448      const digest_algorithm_oid = await PDFNet.ObjectIdentifier.createFromDigestAlgorithm(digest_algorithm_type);
449      const signature_algorithm_oid = await PDFNet.ObjectIdentifier.createFromPredefined(PDFNet.ObjectIdentifier.Predefined.e_RSA_encryption_PKCS1);
450
451      // Then, put the CMS signature components together.
452      const cms_signature = await PDFNet.DigitalSignatureField.generateCMSSignature(signer_cert, chain_certs, digest_algorithm_oid, signature_algorithm_oid, signature_value, signedAttrsCopy);
453
454      // Write the signature to the document.
455      const docbuf = await doc.saveCustomSignatureBuffer(cms_signature, digsig_field);
456      saveBufferAsPDFDoc(docbuf, output_path);
457
458      console.log('================================================================================');
459    };
460
461    // eslint-disable-next-line @typescript-eslint/no-unused-vars
462    const TimestampAndEnableLTV = async (in_docpath, in_trusted_cert_path, in_appearance_img_path, in_outpath) => {
463      const doc = await PDFNet.PDFDoc.createFromURL(in_docpath);
464      doc.initSecurityHandler();
465      doc.lock();
466      const doctimestamp_signature_field = await doc.createDigitalSignatureField();
467      const tst_config = await PDFNet.TimestampingConfiguration.createFromURL('http://rfc3161timestamp.globalsign.com/advanced');
468      const opts = await PDFNet.VerificationOptions.create(PDFNet.VerificationOptions.SecurityLevel.e_compatibility_and_archiving);
469      /* It is necessary to add to the VerificationOptions a trusted root certificate corresponding to
470      the chain used by the timestamp authority to sign the timestamp token, in order for the timestamp
471      response to be verifiable during DocTimeStamp signing. It is also necessary in the context of this
472      function to do this for the later LTV section, because one needs to be able to verify the DocTimeStamp
473      in order to enable LTV for it, and we re-use the VerificationOptions opts object in that part. */
474      await opts.addTrustedCertificateFromURL(in_trusted_cert_path);
475      /* By default, we only check online for revocation of certificates using the newer and lighter
476      OCSP protocol as opposed to CRL, due to lower resource usage and greater reliability. However,
477      it may be necessary to enable online CRL revocation checking in order to verify some timestamps
478      (i.e. those that do not have an OCSP responder URL for all non-trusted certificates). */
479      await opts.enableOnlineCRLRevocationChecking(true);
480
481      const widgetAnnot = await PDFNet.SignatureWidget.createWithDigitalSignatureField(doc, new PDFNet.Rect(0, 100, 200, 150), doctimestamp_signature_field);
482      await (await doc.getPage(1)).annotPushBack(widgetAnnot);
483
484      // (OPTIONAL) Add an appearance to the signature field.
485      const img = await PDFNet.Image.createFromURL(doc, in_appearance_img_path);
486      await widgetAnnot.createSignatureAppearance(img);
487
488      console.log('Testing timestamping configuration.');
489      const config_result = await tst_config.testConfiguration(opts);
490      if (await config_result.getStatus()) {
491        console.log('Success: timestamping configuration usable. Attempting to timestamp.');
492      } else {
493        // Print details of timestamping failure.
494        console.log(await config_result.getString());
495        if (await config_result.hasResponseVerificationResult()) {
496          const tst_result = await config_result.getResponseVerificationResult();
497          console.log('CMS digest status: ' + (await tst_result.getCMSDigestStatusAsString()));
498          console.log('Message digest status: ' + (await tst_result.getMessageImprintDigestStatusAsString()));
499          console.log('Trust status: ' + (await tst_result.getTrustStatusAsString()));
500        }
501        return false;
502      }
503
504      await doctimestamp_signature_field.timestampOnNextSave(tst_config, opts);
505
506      // Save/signing throws if timestamping fails.
507      let docbuf = await doc.saveMemoryBuffer(PDFNet.SDFDoc.SaveOptions.e_incremental);
508      saveBufferAsPDFDoc(docbuf, in_outpath);
509
510      console.log('Timestamping successful. Adding LTV information for DocTimeStamp signature.');
511
512      // Add LTV information for timestamp signature to document.
513      const timestamp_verification_result = await doctimestamp_signature_field.verify(opts);
514      if (!(await doctimestamp_signature_field.enableLTVOfflineVerification(timestamp_verification_result))) {
515        console.log('Could not enable LTV for DocTimeStamp.');
516        return false;
517      }
518      docbuf = await doc.saveMemoryBuffer(PDFNet.SDFDoc.SaveOptions.e_incremental);
519      saveBufferAsPDFDoc(docbuf, in_outpath);
520      console.log('Added LTV information for DocTimeStamp signature successfully.');
521
522      return true;
523    };
524
525    const main = async () => {
526      let ret = 0;
527
528      // ////////////////// TEST 0:
529      /* Create an approval signature field that we can sign after certifying.
530      (Must be done before calling CertifyOnNextSave/SignOnNextSave/WithCustomHandler.) */
531      try {
532        const doc = await PDFNet.PDFDoc.createFromURL(input_path + 'waiver.pdf');
533        doc.initSecurityHandler();
534        doc.lock();
535        const approval_signature_field = await doc.createDigitalSignatureField('PDFTronApprovalSig');
536        const widgetAnnotApproval = await PDFNet.SignatureWidget.createWithDigitalSignatureField(doc, new PDFNet.Rect(300, 300, 500, 200), approval_signature_field);
537        const page1 = await doc.getPage(1);
538        await page1.annotPushBack(widgetAnnotApproval);
539        const docbuf = await doc.saveMemoryBuffer(PDFNet.SDFDoc.SaveOptions.e_remove_unused);
540        saveBufferAsPDFDoc(docbuf, 'waiver_withApprovalField_output.pdf');
541      } catch (err) {
542        console.log(err);
543        ret = 1;
544      }
545
546      // ////////////////// TEST 1: certify a PDF.
547      try {
548        const docbuf = await CertifyPDF(
549          input_path + 'waiver_withApprovalField.pdf',
550          'PDFTronCertificationSig',
551          input_path + 'pdftron.pfx',
552          'password',
553          input_path + 'pdftron.bmp',
554          'waiver_withApprovalField_certified_output.pdf'
555        );
556        await PrintSignaturesInfo(docbuf);
557      } catch (err) {
558        console.log(err);
559        ret = 1;
560      }
561
562      // ////////////////// TEST 2: sign a PDF with a certification and an unsigned signature field in it.
563      try {
564        const docbuf = await SignPDF(
565          input_path + 'waiver_withApprovalField_certified.pdf',
566          'PDFTronApprovalSig',
567          input_path + 'pdftron.pfx',
568          'password',
569          input_path + 'signature.jpg',
570          'waiver_withApprovalField_certified_approved_output.pdf'
571        );
572        await PrintSignaturesInfo(docbuf);
573      } catch (err) {
574        console.log(err);
575        ret = 1;
576      }
577
578      // ////////////////// TEST 3: Clear a certification from a document that is certified and has an approval signature.
579      try {
580        const docbuf = await ClearSignature(
581          input_path + 'waiver_withApprovalField_certified_approved.pdf',
582          'PDFTronCertificationSig',
583          'waiver_withApprovalField_certified_approved_certcleared_output.pdf'
584        );
585        await PrintSignaturesInfo(docbuf);
586      } catch (err) {
587        console.log(err);
588        ret = 1;
589      }
590
591      // ////////////////// TEST 4: Verify a document's digital signatures.
592      // EXPERIMENTAL. Digital signature verification is undergoing active development, but currently does not support a number of features. If we are missing a feature that is important to you, or if you have files that do not act as expected, please contact us using one of the following forms: https://apryse.com/form/trial-support or https://apryse.com/form/request
593      try {
594        if (!(await VerifyAllAndPrint(input_path + 'waiver_withApprovalField_certified_approved.pdf', input_path + 'pdftron.cer'))) {
595          ret = 1;
596        }
597      } catch (err) {
598        console.log(err);
599        ret = 1;
600      }
601
602      // ////////////////// TEST 5: Verify a document's digital signatures in a simple fashion using the document API.
603      try {
604        if (!(await VerifySimple(input_path + 'waiver_withApprovalField_certified_approved.pdf', input_path + 'pdftron.cer'))) {
605          ret = 1;
606        }
607      } catch (err) {
608        console.log(err);
609        ret = 1;
610      }
611
612      // ///////////////// TEST 6: Custom signing API.
613      // The Apryse custom signing API is a set of APIs related to cryptographic digital signatures
614      // which allows users to customize the process of signing documents. Among other things, this
615      // includes the capability to allow for easy integration of PDF-specific signing-related operations
616      // with access to Hardware Security Module (HSM) tokens/devices, access to cloud keystores, access
617      // to system keystores, etc.
618      try {
619        await CustomSigningAPI(
620          input_path + 'waiver.pdf',
621          'PDFTronCertificationSig',
622          input_path + 'pdftron.pfx',
623          'password',
624          input_path + 'pdftron.cer',
625          input_path + 'signature.jpg',
626          PDFNet.DigestAlgorithm.Type.e_SHA256,
627          true,
628          'waiver_custom_signed.pdf'
629        );
630      } catch (err) {
631        console.log(err);
632        ret = 1;
633      }
634
635      // //////////////////// TEST 7: Timestamp a document, then add Long Term Validation (LTV) information for the DocTimeStamp.
636      // try {
637      //   if (!(await TimestampAndEnableLTV(input_path + 'waiver.pdf',
638      //     input_path + 'GlobalSignRootForTST.cer',
639      //     input_path + 'signature.jpg',
640      //     'waiver_DocTimeStamp_LTV.pdf'))) {
641      //     ret = 1;
642      //   }
643      // } catch (err) {
644      //   console.log(err);
645      //   ret = 1;
646      // }
647
648      // ////////////////// End of tests. ////////////////////
649      if (!ret) {
650        console.log('Tests successful.\n==========');
651      } else {
652        console.log('Tests FAILED!!!\n==========');
653      }
654    };
655
656    // add your own license key as the second parameter, e.g. PDFNet.runWithCleanup(main, 'YOUR_LICENSE_KEY')
657    PDFNet.runWithCleanup(main);
658  };
659})(window);
660// eslint-disable-next-line spaced-comment
661//# sourceURL=DigitalSignaturesTest.js
Did you find this helpful?
Trial setup questions?
Ask experts on DiscordNeed other help?
Contact SupportPricing or product questions?
Contact Sales