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: 'contact@example.com',
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
[X] My report includes a Short, Self Contained, Correct (Compilable) Example.
[X] I have attached all PDFs, images, and other files needed to run my SSCCE.
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:
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);
}
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:
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
Additional Notes
No response