Skip to content

Adding signature to an already signed PDF cause previous signature to become invalid #1271

@nrtinio

Description

@nrtinio

What were you trying to do?

I am trying to sign an already signed document (using this library to add placeholder) and then sign again. Multiple people (number depends) need to sign the document.

How did you attempt to do it?

Here's I used the code to add a placeholder:

                const ByteRange = PDFArrayCustom.withContext(pdf.context);
                ByteRange.push(PDFNumber.of(0));
                ByteRange.push(PDFName.of(DEFAULT_BYTE_RANGE_PLACEHOLDER));
                ByteRange.push(PDFName.of(DEFAULT_BYTE_RANGE_PLACEHOLDER));
                ByteRange.push(PDFName.of(DEFAULT_BYTE_RANGE_PLACEHOLDER));

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

Here's my code for adding the image:

                const signatureImageDict = pdf.context.obj({
                    Type: 'XObject',
                    Subtype: 'Form',
                    FormType: 1,
                    BBox: [0, 0, signatureWidth, signatureHeight],
                    Resources: { XObject: { Image: signatureImageObject.ref } },
                });

                var operators = [
                    rotateDegrees(0),
                    ...drawImage('Image', {
                        x: ((signatureWidth) / 2) - (signatureImageScale.width / 2),
                        y: ((signatureHeight) / 2) - (signatureImageScale.height / 2),
                        width: signatureImageScale.width,
                        height: signatureImageScale.height,
                        rotate: degrees(0),
                        xSkew: degrees(0),
                        ySkew: degrees(0),
                    })
                ];

                const signatureImageStream = PDFContentStream.of(signatureImageDict, operators, false);
                const signatureImageStreamDict = pdf.context.register(signatureImageStream);

                const widgetDict = pdf.context.obj({
                    Type: 'Annot',
                    Subtype: 'Widget',
                    FT: 'Sig',
                    Rect: [x1, x2, y1, y2],
                    V: signatureDictRef,
                    T: PDFString.of(`Signature${sigs.length}`),
                    F: 4,
                    P: pages[signature.page - 1].ref,
                    AP: pdf.context.obj({
                        N: signatureImageStreamDict
                    })
                });

                const widgetDictRef = pdf.context.register(widgetDict);

                form.acroForm.addField(widgetDictRef);

                pages[signature.page - 1].node.addAnnot(widgetDictRef);

What actually happened?

Instead of accepting both as revisions, the old signature became invalid:

image

What did you expect to happen?

I expect the document to accept both signatures as valid just like when signing using adobe acrobat e.g.:

image

How can we reproduce the issue?

Using the code above, add a placeholder and signature image. Then sign using the node-signpdf library

            const modifiedPdfBytes = await pdf.save({ useObjectStreams: false });
            const modifiedPdfBuffer = Buffer.from(modifiedPdfBytes);

            //SIGN

            const signedPdf = signer.sign(modifiedPdfBuffer, p12Buffer, {
                passphrase: decrypt(req.session.signer_password)
            });

Version

1.17.1

What environment are you running pdf-lib in?

Node

Checklist

  • My report includes a Short, Self Contained, Correct (Compilable) Example.
  • I have attached all PDFs, images, and other files needed to run my SSCCE.

Additional Notes

No response

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions