Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Embed digital signature(pkcs7) to pdf #1643

Open
2 tasks done
ParitoshKarnatak opened this issue Jun 25, 2024 · 0 comments
Open
2 tasks done

Embed digital signature(pkcs7) to pdf #1643

ParitoshKarnatak opened this issue Jun 25, 2024 · 0 comments

Comments

@ParitoshKarnatak
Copy link

What were you trying to do?

I am implementing signing of a PDF. I have pkcs7 value and I want to embed it in the PDF.

I am using pdf-lib and node-signpdf

The PDF file is getting signed, but when verifying using pdfsign, I am getting this error:

pdfsig signed.pdf
Digital Signature Info of: signed.pdf
Syntax Error (0): Illegal values in ByteRange array
Signature #1:

  • Signer Certificate Common Name: (null)
  • Signer full Distinguished Name: (null)
  • Signing Time: Jun 24 2024 19:49:21
  • Signing Hash Algorithm: unknown
  • Signature Type: adbe.pkcs7.detached
  • Signed Ranges: [0 - 99393], [99403 - 116849]
  • Not total document signed
  • Signature Validation: Signature has not yet been verified.

How did you attempt to do it?

const fs = require('fs');
const { PDFDocument, PDFName, PDFHexString, PDFArray, PDFDict, PDFNumber } = require('pdf-lib');
const { plainAddPlaceholder } = require('node-signpdf/dist/helpers');

async function embedSignatureToPdf(pdfPath, outputPdfPath, base64Signature) {
try {
// Read the PDF
const pdfBuffer = fs.readFileSync(pdfPath);

    // Add a placeholder for the signature
    const pdfWithPlaceholder = plainAddPlaceholder({
        pdfBuffer,
        reason: 'I am the author',
        contactInfo: '[email protected]',
        name: 'Author',
        location: 'Location',
    });

    // Debugging: Log the length of the PDF with placeholder
    console.log('pdfWithPlaceholder length:', pdfWithPlaceholder.length);

    // Convert Base64 signature to Buffer
    const pkcs7Buffer = Buffer.from(base64Signature, 'base64');

    // Find the ByteRange placeholder position
    const byteRangePlaceholder = '**********';
    const byteRangePos = pdfWithPlaceholder.indexOf(byteRangePlaceholder);
    if (byteRangePos === -1) {
        throw new Error('Could not find ByteRange placeholder in the PDF');
    }

    // Calculate the lengths of the first and second ranges
    const length1 = byteRangePos;
    const length2 = pdfWithPlaceholder.length - (length1 + byteRangePlaceholder.length);

    // Calculate ByteRange values
    const byteRange = [
        0, // start1
        length1, // length1
        length1 + byteRangePlaceholder.length, // start2
        length2, // length2
    ];

    // Ensure the ByteRange values are correct
    console.log('ByteRange:', byteRange);
    const totalSignedLength = length1 + length2;
    console.log('totalSignedLength:', totalSignedLength);
    if (totalSignedLength !== pdfWithPlaceholder.length - byteRangePlaceholder.length) {
        throw new Error('ByteRange values do not sum up to the total document length minus the placeholder length');
    }

    // Format ByteRange values as a string
    const byteRangeStr = byteRange.map(val => `0000000000${val}`.slice(-10)).join(' ');

    // Debugging: Log ByteRange string
    console.log('ByteRangeStr:', byteRangeStr);

    // Replace ByteRange placeholder with actual values
    let pdfWithByteRange = Buffer.concat([
        pdfWithPlaceholder.slice(0, byteRangePos),
        Buffer.from(byteRangeStr),
        pdfWithPlaceholder.slice(byteRangePos + byteRangePlaceholder.length),
    ]);

    // Load the PDF document with ByteRange replaced
    const signedPdfDoc = await PDFDocument.load(pdfWithByteRange);

    // Get the AcroForm dictionary
    const acroForm = signedPdfDoc.context.lookup(signedPdfDoc.catalog.get(PDFName.of('AcroForm')));
    if (!acroForm) {
        throw new Error('Could not find AcroForm in the PDF');
    }

    // Get the signature field
    const fields = acroForm.lookup(PDFName.of('Fields'), PDFArray);
    const signatureField = fields.lookup(0, PDFDict);
    const signatureDict = signatureField.lookup(PDFName.of('V'), PDFDict);

    // Set the /ByteRange entry with the calculated ByteRange
    const byteRangeArray = PDFArray.withContext(signedPdfDoc.context);
    byteRange.forEach(val => byteRangeArray.push(PDFNumber.of(val)));
    signatureDict.set(PDFName.of('ByteRange'), byteRangeArray);

    // Set the /Contents entry with the PKCS#7 signature
    const hexSignature = PDFHexString.of(pkcs7Buffer.toString('hex'));

    // Ensure the contents fit in the allocated space
    const placeholderLengthBytes = byteRangePlaceholder.length * 2; // Each byte is represented by 2 hex digits
    const paddedSignature = hexSignature.value.padEnd(placeholderLengthBytes, '0');

    signatureDict.set(PDFName.of('Contents'), PDFHexString.of(paddedSignature));

    // Save the signed PDF
    const signedPdfBytes = await signedPdfDoc.save();
    fs.writeFileSync(outputPdfPath, signedPdfBytes);

    console.log('PDF signed successfully!');
} catch (error) {
    console.error('Error signing PDF:', error);
}

}

What actually happened?

The PDF file is getting signed, but when verifying using pdfsign, I am getting this error:

pdfsig signed.pdf
Digital Signature Info of: signed.pdf
Syntax Error (0): Illegal values in ByteRange array
Signature #1:

  • Signer Certificate Common Name: (null)
  • Signer full Distinguished Name: (null)
  • Signing Time: Jun 24 2024 19:49:21
  • Signing Hash Algorithm: unknown
  • Signature Type: adbe.pkcs7.detached
  • Signed Ranges: [0 - 99393], [99403 - 116849]
  • Not total document signed
  • Signature Validation: Signature has not yet been verified.

What did you expect to happen?

The PDF should be signed with the appropriate digital signature

How can we reproduce the issue?

By running the code along with appropriate pkcs7 certificate value

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant