pdf-signature-reader-sl
Version:
Verify digital signatures in PDF documents with content validation and enhanced support for Spanish certificates (FNMT, DNIe, corporate)
65 lines (50 loc) • 1.95 kB
JavaScript
const { Buffer } = require('../packages/buffer');
const VerifyPDFError = require('../VerifyPDFError');
const { getSignatureMeta, preparePDF } = require('./general');
const DEFAULT_BYTE_RANGE_PLACEHOLDER = '**********';
const getByteRange = (pdfBuffer) => {
const byteRangeStrings = pdfBuffer.toString().match(/\/ByteRange\s*\[{1}\s*(?:(?:\d*|\/\*{10})\s+){3}(?:\d+|\/\*{10}){1}\s*\]{1}/g);
if (!byteRangeStrings) {
throw new VerifyPDFError(
'Failed to locate ByteRange.',
VerifyPDFError.TYPE_PARSE,
);
}
const byteRangePlaceholder = byteRangeStrings.find((s) => s.includes(`/${DEFAULT_BYTE_RANGE_PLACEHOLDER}`));
const strByteRanges = byteRangeStrings.map((brs) => brs.match(/[^[\s]*(?:\d|\/\*{10})/g));
const byteRanges = strByteRanges.map((n) => n.map(Number));
return {
byteRangePlaceholder,
byteRanges,
};
};
const extractSignature = (pdf) => {
const pdfBuffer = preparePDF(pdf);
const { byteRanges } = getByteRange(pdfBuffer);
// const lastIndex = byteRanges.length - 1;
// const endOfByteRange = byteRanges[lastIndex][2] + byteRanges[lastIndex][3];
// if (pdfBuffer.length > endOfByteRange) {
// throw new VerifyPDFError(
// 'Failed byte range verification.',
// VerifyPDFError.VERIFY_BYTE_RANGE,
// );
// }
const signatureStr = [];
const signedData = [];
byteRanges.forEach((byteRange) => {
signedData.push(Buffer.concat([
pdfBuffer.slice(byteRange[0], byteRange[0] + byteRange[1]),
pdfBuffer.slice(byteRange[2], byteRange[2] + byteRange[3]),
]));
const signatureHex = pdfBuffer.slice(byteRange[0] + byteRange[1] + 1, byteRange[2]).toString('latin1');
signatureStr.push(Buffer.from(signatureHex, 'hex').toString('latin1'));
});
const signatureMeta = signedData.map((sd) => getSignatureMeta(sd))
return {
byteRanges,
signatureStr,
signedData,
signatureMeta,
};
};
module.exports = extractSignature;