DigitalSignature

Sample JavaScript code to use Apryse SDK's high-level digital signature API for digitally signing and/or certifying PDF files. Learn more about our Web SDK and PDF Digital Signature Library.

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 Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales