vbuch / node-signpdf

Simple signing of PDFs in node.
MIT License
674 stars 174 forks source link

Error when trying to sign a pdf document when using @signpdf module #247

Open CristiCh opened 3 months ago

CristiCh commented 3 months ago

I get the following error when trying to sign a document using @signpdf module. Can anyone please help me regarding this issue?

This is the code I use:

const {onRequest} = require("firebase-functions/v2/https");
const {onObjectFinalized} = require("firebase-functions/v2/storage");
const admin = require('firebase-admin')
const {initializeApp} = require("firebase-admin/app");
const {getStorage} = require("firebase-admin/storage");
const logger = require("firebase-functions/logger");
const path = require('path');
const {setGlobalOptions} = require("firebase-functions/v2");
const getRawBody = require('raw-body')
var pdflibAddPlaceholder = require('@signpdf/placeholder-pdf-lib').pdflibAddPlaceholder;
var signpdf = require('@signpdf/signpdf').default;
var P12Signer = require('@signpdf/signer-p12').P12Signer;
var { SUBFILTER_ETSI_CADES_DETACHED } = require('@signpdf/utils');
var PDFDocument = require('pdf-lib').PDFDocument;
var { StandardFonts } = require('@pdf-lib/standard-fonts');
setGlobalOptions({region: "europe-west1"});
initializeApp();

exports.processPDF = onObjectFinalized({}, async (event) => {
  const bucket = admin.storage().bucket()
  const fileBucket = event.data.bucket; // Storage bucket containing the file.
  const filePath = event.data.name; // File path in the bucket.
  const contentType = event.data.contentType; // File content type.
  console.log(filePath);

  const certificatePath = "/certificate/client-identity.p12";
  const file = bucket.file(filePath);
  const certificateFile = bucket.file(certificatePath);

  const fileDir = path.dirname(filePath);
  const fileBasename = path.basename(filePath);

  console.log(fileDir);
  if (fileDir != 'uploads') { return; } //Only continue if the file is uploaded into uploads folder

  getRawBody(file.createReadStream())
      .then((pdfBuffer) => {

          console.log(pdfBuffer.length + ' bytes submitted');

          getRawBody(certificateFile.createReadStream())
              .then((certBuff) => {
                  console.log(certBuff.length + 'bytes cert');

                    PDFDocument.load(pdfBuffer).then(function (pdfDoc) {
                        console.log("loading pdf document");
                        console.log(pdfDoc);
                        var signer = new P12Signer(certBuff, {passphrase: "123456"}); //This is the password's certificate
                        pdflibAddPlaceholder({
                            pdfDoc: pdfDoc,
                            reason: 'The user is declaring consent through JavaScript.',
                            contactInfo: 'signpdf@example.com',
                            name: 'John Doe',
                            location: 'Free Text Str., Free World',
                        });
                        pdfDoc.save().then(function (pdfWithPlaceholderBytes) {
                            // And finally sign the document.
                            signpdf
                                .sign(pdfWithPlaceholderBytes, signer)
                                .then(function (signedPdf) {
                                    console.log('Signed PDF');
                                })
                        })

                    });
             })
              .catch((err) => {
                  console.log(err.message);
              });

      })
      .catch((err) => {

          console.log(err.message);
      });
    });

The error is the following:

TypeError: Cannot read properties of undefined (reading 'push')
>      at pdflibAddPlaceholder (/Users/Desktop/docSignLocal/node_modules/@signpdf/placeholder-pdf-lib/dist/pdflibAddPlaceholder.js:174:10)
>      at /Users/Desktop/docSignLocal/functions/index.js:51:25
>      at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

I tried different libraries for signing a pdf file but none work. The error is "Cannot read properties of undefined (reading 'push')" when using @signpdf module. I need the document to be signed using the placeholder and signer. Thanks!

thmclellan commented 3 months ago

This is hard to troubleshoot without an example PDF file, but one thing to know with pdf-lib is that it has some limitations such as not handling encrypted documents (https://github.com/Hopding/pdf-lib?tab=readme-ov-file#encryption-handling).

Looking at the error message, it seems the placeholder code is having difficulty adding a signature placeholder to a new or existing acroForm at: https://github.com/vbuch/node-signpdf/blob/4a6a2a46a6a786f35d58a3e00c6acd13827445ee/packages/placeholder-pdf-lib/dist/pdflibAddPlaceholder.js#L174

Unfortunately the pdf-lib dependency hasn't been updated in over 2 years. I've been looking for a solution too, and while this node-signpdf does a nice job of its purpose of showing how to sign a typical PDF, it isn't a production-ready library for a full range of existing PDFs.