Hopding / pdf-lib

Create and modify PDF documents in any JavaScript environment
https://pdf-lib.js.org
MIT License
6.76k stars 647 forks source link

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

Closed nrtinio closed 2 years ago

nrtinio commented 2 years ago

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

Additional Notes

No response

nrtinio commented 2 years ago

Hello, sorry to have created another issue for this. Upon further investigation, this was already tackled in multiple issues:

237 #278 #834 #816

All are pointing to Incremental Updates which is included in roadmap:

998

I am closing this now. Thank you all for your efforts.

kingshuaishuai commented 1 year ago

How did you solve this problem? I haven't found a solution yet 😭 @nrtinio

RippleRurigaki commented 1 year ago

Exsample, Signatures in incremental updates. I needed it for my private project. I can't support it, but we will make it public.

https://github.com/RippleRurigaki/sPDF.js