vbuch / node-signpdf

Simple signing of PDFs in node.
MIT License
679 stars 176 forks source link

Simple Example Sign PDF #159

Closed hscstudio closed 9 months ago

hscstudio commented 2 years ago

I don't know, why You not create simple example for this library? Not all users know how use this library..

  1. How to import Your library? especially plainAddPlaceholder
  2. How create p12 certificate?
  3. How write signed pdf to file?
  4. How change "Signed by signedpdf signpdf@example.com" in pdf file?

I read this README, but You only reference code tester I have look at issue but You not clear answer, for example (https://github.com/vbuch/node-signpdf/issues/126), but You not answer with clear answer :( You may need to add add 'dist' to the import path. something like 'node-sginpdf/dist/helpers/plainAddPlaceholder' why You dont answer with const { plainAddPlaceholder } = require('node-signpdf/dist/helpers'); I have googling but I don't get anything that help me

For other, if You confuse, You can read this simple example

const signer = require('node-signpdf').default
const fs = require('fs')
const { plainAddPlaceholder } = require('node-signpdf/dist/helpers');

const pdfSignedPath = `./signed.pdf`;
const pdfBuffer = fs.readFileSync(`./source.pdf`);
const certBuffer = fs.readFileSync(`./certificate.p12`);

let inputBuffer = plainAddPlaceholder({
    pdfBuffer,
    reason: 'Signed Certificate.',
    contactInfo: 'sign@example.com',
    name: 'Example',
    location: 'Jakarta',
    signatureLength: certBuffer.length,
});

const signedPdf = signer.sign(
  inputBuffer,
  certBuffer,
  { asn1StrictParsing : true },
);

fs.writeFileSync(pdfSignedPath, signedPdf);

source.pdf is file pdf that will signed signed.pdf is target of signed file certificate.p12 is Your certificate, generate this with openssl or You can use sample in folder 'resources' of this library

JMHAVANCE commented 2 years ago

This was actually extremely helpful for me, as I don't come from a node-js background and the unit tests were very confusing for me to understand as I couldn't figure out how to properly import the library and functions and run them in my own code.

Thank you! (both to the developer of the library and @hscstudio for the clean (and working!) example)

fdimarh commented 2 years ago

Maybe this snippet code will help you get better understanding to signing PDF with this library

import { SignPdf } from 'node-signpdf';
import fs from 'fs';
import { Buffer } from 'buffer';
import { plainAddPlaceholder } from 'node-signpdf/dist/helpers/index.js';

const pathSignedPdf = 'path/to/your/signed.pdf'
const p12Buffer = fs.readFileSync('path/to/your/certificate.p12');
const pdfBuffer = fs.readFileSync('path/to/your/file/need/to/sign.pdf');
const pdfBufferToSign = plainAddPlaceholder({
    pdfBuffer
});
const signer = new SignPdf()
const signedPdf = signer.sign(pdfBufferToSign, p12Buffer, { passphrase: 'your/passphrase' });
const bufferPdf = Buffer.from(signedPdf)

fs.createWriteStream(pathSignedPdf).write(bufferPdf);
AkshayThakurcr commented 2 years ago

How to use this module in code. Can anyone help me?

christianledgard commented 2 years ago

¡Hello! I'm getting the following error while trying to run @hscstudio and @fdimarh example:

throw new _SignPdfError.default(`Expected xref at ${position} but found other content.`, _SignPdfError.default.TYPE_PARSE);
            ^

SignPdfError: Expected xref at NaN but found other content.
    at getXref`

¿What am I missing?

Screen Shot 2022-04-19 at 19 47 36

I tried to run it locally, and I got the same error message. Here is the Replit Link where you can reproduce the issue. Thank you for the help!

vbuch commented 2 years ago

Without reproducing, just looking at the code: the reason is that getLastTrailerPosition returned NaN. That's what the position variable is - the result of getLastTrailerPosition(). Why that happened requires a resource that I don't have - time. So I cannot, at least at the moment, help you any further in debugging.

Edit: I can just guess that you are using PDF features that are not supported. What is the version of you PDF? Does it include streams? That's the usual when there are issues with the trailer.

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had activity in the past 90 days. It will be closed if no further activity occurs. Thank you for your contributions.

bktan81 commented 1 year ago

Hi @vbuch, first of all, thanks for the wonderful library.

@christianledgard I'm getting the same error, have you managed to find the solution?

(node:13193) UnhandledPromiseRejectionWarning: Error: Expected xref at NaN but found other content.
    at getXref (/home/jack/Desktop/temp/nodejs-sign-test/node_modules/node-signpdf/dist/helpers/plainAddPlaceholder/readRefTable.js:36:13)
    at getFullXrefTable (/home/jack/Desktop/temp/nodejs-sign-test/node_modules/node-signpdf/dist/helpers/plainAddPlaceholder/readRefTable.js:88:25)
    at readRefTable (/home/jack/Desktop/temp/nodejs-sign-test/node_modules/node-signpdf/dist/helpers/plainAddPlaceholder/readRefTable.js:108:25)
    at readPdf (/home/jack/Desktop/temp/nodejs-sign-test/node_modules/node-signpdf/dist/helpers/plainAddPlaceholder/readPdf.js:47:46)
    at plainAddPlaceholder (/home/jack/Desktop/temp/nodejs-sign-test/node_modules/node-signpdf/dist/helpers/plainAddPlaceholder/index.js:58:37)
....

The node.js snippet

(async()=>{
    //https://github.com/vbuch/node-signpdf/blob/develop/src/signpdf.test.js#L111
    let signer = new SignPdf();

    const p12Buffer = fs.readFileSync(
        `./certificate.p12`,
    );
    let pdfBuffer = fs.readFileSync(`./pdf-lib_image_embedding_example.pdf`);
    pdfBuffer = plainAddPlaceholder({
        pdfBuffer,
        reason: 'I have reviewed it.',
        signatureLength: 1612,
    });
    pdfBuffer = signer.sign(pdfBuffer, p12Buffer);
    fs.writeFileSync('signed_image.pdf', pdfBuffer);
[pdf-lib_image_embedding_example.pdf](https://github.com/vbuch/node-signpdf/files/9278681/pdf-lib_image_embedding_example.pdf)

})();

pdf-lib_image_embedding_example.pdf

The cert: https://github.com/vbuch/node-signpdf/blob/develop/resources/certificate.p12

artsnr1 commented 1 year ago

Same error here "Uncaught Error: Could not find xref anywhere at or after NaN."

Please someone tell how to resolve it

debchy commented 1 year ago

Without reproducing, just looking at the code: the reason is that getLastTrailerPosition returned NaN. That's what the position variable is - the result of getLastTrailerPosition(). Why that happened requires a resource that I don't have - time. So I cannot, at least at the moment, help you any further in debugging.

Edit: I can just guess that you are using PDF features that are not supported. What is the version of you PDF? Does it include streams? That's the usual when there are issues with the trailer.

for Object streams added into pdf v 1.5 or greater, this plugin is failing to read pdf

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had activity in the past 90 days. It will be closed if no further activity occurs. Thank you for your contributions.

bktan81 commented 1 year ago

Found a solution using pdf-lib on Stackoverflow, the link is as follows: https://stackoverflow.com/questions/69973417/add-graphic-signature-and-digital-signature-to-a-pdf-in-nodejs

and the original answer: https://github.com/Hopding/pdf-lib/issues/112#issuecomment-1049456413

stale[bot] commented 11 months ago

This issue has been automatically marked as stale because it has not had activity in the past 90 days. It will be closed if no further activity occurs. Thank you for your contributions.

20manas commented 10 months ago

Since this issue is serving as a useful basic example, here's a type declarations file that I'm using to add TypeScript support for this package:

declare module 'node-signpdf';

interface PlainAddPlaceholderOptions {
  pdfBuffer: Buffer;
  reason: string;
  contactInfo?: string;
  name?: string;
  location?: string,
  signatureLength?: number;
  subFilter?: string;
}

function plainAddPlaceholder(options: PlainAddPlaceholderOptions): Buffer;

interface SignOptions {
  asn1StrictParsing?: boolean;
  passphrase?: string;
}

class SignPdf {
  sign(pdfBuffer: Buffer, p12CertBuffer: Buffer, options?: SignOptions): Buffer;
}
vbuch commented 9 months ago

@20manas 2.0.0 already has some (limited) TS types generated through JSDoc. Much more will be availale in 3+

vbuch commented 9 months ago

@hscstudio I will include your example in 3+

vbuch commented 9 months ago

https://github.com/vbuch/node-signpdf/releases/tag/v3.0.0

franck-grenier commented 3 days ago

Hello, I just landed here having the same error "getLastTrailerPosition returning NaN" when trying to sign a PDF produced by Gotenberg 8 merge command.

We found a solution by changing Gotenberg PDF engines order (https://gotenberg.dev/docs/configuration#pdf-engines) to have pdftk do the merge rather than pdfcpu.

invoicer-gotenberg:
    image: gotenberg/gotenberg:8
    command:
      - 'gotenberg'
      - '--api-timeout=300s'
      - '--pdfengines-engines=exiftool,libreoffice-pdfengine,pdftk,qpdf,pdfcpu'

The resulting PDF can then be signed with @signpdf/signpdf.

Hope this will be useful for anyone.