vbuch / node-signpdf

Simple signing of PDFs in node.
MIT License
696 stars 175 forks source link

How-to Sign already create PDF document #22

Closed moshebeeri closed 5 years ago

moshebeeri commented 5 years ago

Hi Guys,

Grate work... I'll will appreciate to create and submit a demo of using node-signpdf for the ones using jsPDF. The problem is that I can not find how to create the placeholders as shows on the tests

const signature = pdf.ref({ Type: 'Sig', Filter: 'Adobe.PPKLite', SubFilter: 'adbe.pkcs7.detached', ByteRange: [ 0, DEFAULT_BYTE_RANGE_PLACEHOLDER, DEFAULT_BYTE_RANGE_PLACEHOLDER, DEFAULT_BYTE_RANGE_PLACEHOLDER, ], Contents: Buffer.from(String.fromCharCode(0).repeat(signatureLength)), Reason: new String(reason), // eslint-disable-line no-new-wrappers M: new Date(), }); When looking on the jsPDF I could not find the equivalent to pdf.ref, but I am sure there is a way to do that, any idea?

vbuch commented 5 years ago

Can't really help with jspdf. But I read a bit through the specs of the PDF format and adding an item to the document should be relatively easy with simple string operations. I am willing to do it but don't really have the time at the moment.

  1. you need to read the trailer and see if there already is a form. If there is one, you will need to reuse it. If there is not, add one.
  2. Then add the sig element etc.
  3. It is even really simple to implement incremental updates to allow multiple signatures by adding a new trailer.

Once I have the time to do that, I will as it will much enhance this package. If you, on the other hand, have the time, we would appreciate a PR.

vbuch commented 5 years ago

Heads up: What the ref function basically does in pdfkit is store an item an enumerate it. So just reading the trailer will give you the current number of items. Use that number for you next added item and increase the number in the trailer. Link the AcroForm in the root descriptor. That's all you need to do. The pdf spec is available at http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf

vbuch commented 5 years ago

I've started playing with this a bit: https://github.com/vbuch/node-signpdf/tree/play-with-trailers It's hell lot of string/buffer operations that need to be done, but seems like it is doable at least to the bare minimum functionality. Will let you know once I have something working. This would enable adding signature placeholder to any PDF (currently only thinking about really limited options) so it won't matter if you created your document with PdfKit, jsPDF or another tool. Not sure the code will be that readable so I will keep the pdfkit examples in the helpers somehow as well.

vbuch commented 5 years ago

@moshebeeri could you give this peace of code a try?

https://github.com/vbuch/node-signpdf/blob/play-with-trailers/src/signpdf.test.js#L132

It does work following the happiest path possible. Try loading your jspdf created file into a Buffer, then call plainAdd() (that's a temporary name), then .sign()

moshebeeri commented 5 years ago

@vbuch You are the best !!! It works great

vbuch commented 5 years ago

Why did you close it, @moshebeeri? Does it work? It's still in a branch and unofficial. Ill keep the issue open until this is released.

Edit: i see now that you have edited your comment and it works. Nice to see that.

vbuch commented 5 years ago

This is out with 1.0.0

aronmoles commented 5 years ago

This method deletes the metadata from the file. Would it be possible to maintain these metadata?

Thanks

aronmoles commented 4 years ago

Can you help me @vbuch?

Thanks

vbuch commented 4 years ago

Ive missed that previous comment. Sorry @aronmoles This is a closed issue. Create a new one please and provide example pdf so I can see where there is an issue.

inane commented 3 years ago

Hello, is it possible to update again this link? https://github.com/vbuch/node-signpdf/issues/22#issuecomment-485344073

I am trying to sign and add a plain placeholder but it is not being possible. Sign is correct but not plain placeholder. Any clue or help @vbuch ? Thank you in advance.

vbuch commented 3 years ago

No. Not much, @inane This comment was pointing to the branch where plainAddPlaceholder was initially created. It has evolved since. A good hint for you would be that it only works for PDF versions <= 1.3. I think noone reported issues with those so far. On the other hand there are lots of issues with PDF > 1.3. So... if you have a 1.3 pdf, you could use the plainAddPlaceholder. If you have a >1.3, we will all appreciate a PR that know how to do the magic.

inane commented 3 years ago

I have used a web converter to downgrade my pdf document to 1.3 version and result is the same. :-(

Is it possible to modify those preferences or version in nodejs?

Could you please upload again this link? https://github.com/vbuch/node-signpdf/blob/master/src/helpers.js#L12

vbuch commented 3 years ago

No. That was some work in progress. The code has evolved since then. The linked code is in some form in our dev and master branches at the moment. I don't understand how signature is correct but placeholder isn't. Please open a new issue and provide examples if you want someone to take a look at your issue. This one is closed. Here are some tests that demonstrate plainAddPlaceholder

inane commented 3 years ago

Thank you for your last response. I was reading link about plainAddPlaceHolder and I added this code in the function:

async function signDocument ( req, res ) {
  const passphrase = 'DA5cJvezM6Px6JLR',
        p12Buffer  = fs.readFileSync ( `${ __dirname }/WktYaXJlM1VOY0RxdG1kQw==.p12` ),
        payload    = {
          documento : req.file.path
        }
  let pdfBuffer    = fs.readFileSync ( req.file.path )

  pdfBuffer = helpers.plainAddPlaceholder ( {
    pdfBuffer,
    reason: 'TESTING',
    signatureLength: 15544,
  } )
  pdfBuffer = signer.default.sign ( pdfBuffer, p12Buffer, { passphrase } )

  fs.writeFileSync ( `${ __dirname }/` + req.file.originalname, pdfBuffer )
  await models.Firma.create ( payload )
  response.successResponse ( req, res, req.body, 'DOCUMENT_SIGNED_SUCCESSFUL' )
}

I am using "multer" node module to get a formdata sent from the client, req.file.pathis from there.. Are you seeing something wrong?