vbuch / node-signpdf

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

node-signpdf signature placeholder not visible #181

Closed DevMesh18 closed 1 year ago

DevMesh18 commented 1 year ago

Not able to render signature placeholder on pdf I am trying to digitally sign pdf file its signing but signature rect and widget is not available for that. My code is:


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

async function main() {
let pdfBuffer = fs.readFileSync('1.pdf');
const pdfBufferToSign = plainAddPlaceholder({
  pdfBuffer,
  reason          : 'I have reviewed it.',
  signatureLength : 15544,
});

const p12Buffer = fs.readFileSync('cer.pfx');
pdfBuffer = signer.sign(pdfBufferToSign, p12Buffer, {
  passphrase: 'emudhra',
});
fs.writeFile('1-withcer.pdf', pdfBuffer, err => { 
    if (err) { console.error(err); }   // file written successfully
});

}

main().catch(err => console.error(err));
DevMesh18 commented 1 year ago

Closing this issue solved by exploring more on git hub pages: Add signature field and push this to widgetDict will work for me

const signatureDict = pdfDoc.context.obj({
    Type: 'Sig',
    Filter: 'Adobe.PPKLite',
    SubFilter: 'adbe.pkcs7.detached',
    ByteRange,
    Contents: PDFHexString.of('A'.repeat(SIGNATURE_LENGTH)),
    Reason: PDFString.of('We need your signature for reasons...'),
    M: PDFString.fromDate(new Date())
  });
  const signatureDictRef = pdfDoc.context.register(signatureDict);

  const widgetDict = pdfDoc.context.obj({
    Type: 'Annot',
    Subtype: 'Widget',
    FT: 'Sig',
    Rect: [485, 400, 585, 460],
    V: signatureDictRef,
    //N: 'testhsdjkfhajsdhfkjshdlhakSDHFAKJSDJHFJKAHSDJFHAJKSHDLA',
    T: PDFString.of('sig'),
    F: 1,
    P: pages[0].ref,
    //AP: pdfDoc.context.obj({N: 'testetste'})
  });
  const widgetDictRef = pdfDoc.context.register(widgetDict);

  // Add our signature widget to the first page
var pageCount =pdfDoc.getPages;
//loop on pages
pages[0].node.set(PDFName.of('Annots'), pdfDoc.context.obj([widgetDictRef]));
pages[1].node.set(PDFName.of('Annots'), pdfDoc.context.obj([widgetDictRef]));

  // Create an AcroForm object containing our signature widget
  pdfDoc.catalog.set(
    PDFName.of('AcroForm'),
    pdfDoc.context.obj({
      SigFlags: 3,
      Fields: [widgetDictRef],
    }),
  );

const  pdfLibSigImg = await pdfDoc.embedPng(images[0]);
  const pdfLibSigImgName = 'PDF_LIB_SIG_IMG';

  const form = pdfDoc.getForm();

  const sig = form.getSignature('sig');
  sig.acroField.getWidgets().forEach((widget) => {
    const { context } = widget.dict;
    var { width, height } = widget.getRectangle();
    const appearance = [
      ...drawRectangle({
        x: 0,
        y: 0,
        width,
        height,
        borderWidth: 1,
        //color: rgb(0, 0, 0),
        borderColor: rgb(0, 0, 0),
        rotate: degrees(0),
        xSkew: degrees(0),
        ySkew: degrees(0),
      }),
      ...drawImage(pdfLibSigImgName, {
        x: 5,
        y: 5,
        width: width - 10,
        height: height - 10,
        rotate: degrees(0),
        xSkew: degrees(0),
        ySkew: degrees(0),
      }),

    ];

    const stream = context.formXObject(appearance, {
      Resources: { XObject: { [pdfLibSigImgName]: pdfLibSigImg.ref } },
      BBox: context.obj([0, 0, width, height]),
      Matrix: context.obj([1, 0, 0, 1, 0, 0]),
    });
    const streamRef = context.register(stream);

    widget.setNormalAppearance(streamRef);
  });
vbuch commented 8 months ago

Passing the widgetDict is coming to the placeholder helpers via https://github.com/vbuch/node-signpdf/pull/200