All files / lib/helpers general.js

96.29% Statements 26/27
83.33% Branches 10/12
100% Functions 6/6
96.15% Lines 25/26

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98                  4x 29x 29x 2x   2x                   4x 10x 10x 10x           10x 10x 1x                 4x 13x         13x 13x                           4x       64x 64x 64x 64x   64x           4x   16x 16x                            
import { Buffer } from "node:buffer";
 
import forge from "node-forge";
 
import { VerifyPDFError } from "../VerifyPDFError.js";
 
/**
 * @param {Uint8Array} pdf
 */
const preparePDF = (pdf) => {
	try {
		if (Buffer.isBuffer(pdf)) return pdf;
		return Buffer.from(pdf);
	} catch (error) {
		throw new VerifyPDFError(
			"PDF expected as Buffer.",
			VerifyPDFError.Type.TYPE_INPUT,
		);
	}
};
 
/**
 * @param {Uint8Array} pdfBuffer
 */
const checkForSubFilter = (pdfBuffer) => {
	const matches = pdfBuffer.toString().match(/\/SubFilter\s*\/([\w.]*)/);
	const subFilter = Array.isArray(matches) && matches[1];
	Iif (!subFilter) {
		throw new VerifyPDFError(
			"cannot find subfilter",
			VerifyPDFError.Type.TYPE_PARSE,
		);
	}
	const supportedTypes = ["adbe.pkcs7.detached", "etsi.cades.detached"];
	if (!supportedTypes.includes(subFilter.trim().toLowerCase()))
		throw new VerifyPDFError(
			`subFilter ${subFilter} not supported`,
			VerifyPDFError.Type.UNSUPPORTED_SUBFILTER,
		);
};
 
/**
 * @param {forge.Bytes} signature
 */
const getMessageFromSignature = (signature) => {
	const p7Asn1 = forge.asn1.fromDer(
		signature,
		// @ts-expect-error secret parameter
		{ parseAllBytes: false },
	);
	const message = forge.pkcs7.messageFromAsn1(p7Asn1);
	return {
		/**
		 * @type {forge.pki.Certificate[]}
		 */
		// @ts-expect-error Types are wrong maybe?
		certificates: message.certificates,
		...message,
	};
};
 
/**
 * @param {string} keyName
 */
const getMetaRegexMatch =
	(keyName) =>
	/**
	 * @param {string} str
	 */
	(str) => {
		const regex = new RegExp(`/${keyName}\\s*\\(([\\w.\\s@,]*)`, "g");
		const matches = [...str.matchAll(regex)];
		const meta = matches.length ? matches[matches.length - 1]?.[1] : null;
 
		return meta;
	};
 
/**
 * @param {Uint8Array | string} signedData
 */
const getSignatureMeta = (signedData) => {
	const str =
		signedData instanceof Uint8Array ? signedData.toString() : signedData;
	return {
		reason: getMetaRegexMatch("Reason")(str),
		contactInfo: getMetaRegexMatch("ContactInfo")(str),
		location: getMetaRegexMatch("Location")(str),
		name: getMetaRegexMatch("Name")(str),
	};
};
 
export {
	checkForSubFilter,
	getSignatureMeta,
	getMessageFromSignature,
	preparePDF,
};