Skip to content

Commit

Permalink
nv: Built utils
Browse files Browse the repository at this point in the history
  • Loading branch information
vbuch committed Oct 3, 2023
1 parent 7a48944 commit afb3d75
Show file tree
Hide file tree
Showing 35 changed files with 238 additions and 30 deletions.
2 changes: 1 addition & 1 deletion babel.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
"targets": {
"node": "current"
}
}],
}]
]
}
15 changes: 15 additions & 0 deletions packages/utils/dist/SignPdfError.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const ERROR_TYPE_UNKNOWN: 1;
export const ERROR_TYPE_INPUT: 2;
export const ERROR_TYPE_PARSE: 3;
export const ERROR_VERIFY_SIGNATURE: 4;
export class SignPdfError extends Error {
constructor(msg: any, type?: number);
type: number;
}
export namespace SignPdfError {
export { ERROR_TYPE_UNKNOWN as TYPE_UNKNOWN };
export { ERROR_TYPE_INPUT as TYPE_INPUT };
export { ERROR_TYPE_PARSE as TYPE_PARSE };
export { ERROR_VERIFY_SIGNATURE as VERIFY_SIGNATURE };
}
//# sourceMappingURL=SignPdfError.d.ts.map
1 change: 1 addition & 0 deletions packages/utils/dist/SignPdfError.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions packages/utils/dist/SignPdfError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const ERROR_TYPE_UNKNOWN = 1;
export const ERROR_TYPE_INPUT = 2;
export const ERROR_TYPE_PARSE = 3;
export const ERROR_VERIFY_SIGNATURE = 4;
export class SignPdfError extends Error {
constructor(msg, type = ERROR_TYPE_UNKNOWN) {
super(msg);
this.type = type;
}
}

// Shorthand
SignPdfError.TYPE_UNKNOWN = ERROR_TYPE_UNKNOWN;
SignPdfError.TYPE_INPUT = ERROR_TYPE_INPUT;
SignPdfError.TYPE_PARSE = ERROR_TYPE_PARSE;
SignPdfError.VERIFY_SIGNATURE = ERROR_VERIFY_SIGNATURE;
7 changes: 7 additions & 0 deletions packages/utils/dist/const.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const DEFAULT_SIGNATURE_LENGTH: 8192;
export const DEFAULT_BYTE_RANGE_PLACEHOLDER: "**********";
export const SUBFILTER_ADOBE_PKCS7_DETACHED: "adbe.pkcs7.detached";
export const SUBFILTER_ADOBE_PKCS7_SHA1: "adbe.pkcs7.sha1";
export const SUBFILTER_ADOBE_X509_SHA1: "adbe.x509.rsa.sha1";
export const SUBFILTER_ETSI_CADES_DETACHED: "ETSI.CAdES.detached";
//# sourceMappingURL=const.d.ts.map
1 change: 1 addition & 0 deletions packages/utils/dist/const.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions packages/utils/dist/const.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const DEFAULT_SIGNATURE_LENGTH = 8192;
export const DEFAULT_BYTE_RANGE_PLACEHOLDER = '**********';
export const SUBFILTER_ADOBE_PKCS7_DETACHED = 'adbe.pkcs7.detached';
export const SUBFILTER_ADOBE_PKCS7_SHA1 = 'adbe.pkcs7.sha1';
export const SUBFILTER_ADOBE_X509_SHA1 = 'adbe.x509.rsa.sha1';
export const SUBFILTER_ETSI_CADES_DETACHED = 'ETSI.CAdES.detached';
2 changes: 2 additions & 0 deletions packages/utils/dist/extractSignature.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export function extractSignature(pdf: Buffer, signatureCount?: number): any;
//# sourceMappingURL=extractSignature.d.ts.map
1 change: 1 addition & 0 deletions packages/utils/dist/extractSignature.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 48 additions & 0 deletions packages/utils/dist/extractSignature.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { SignPdfError } from './SignPdfError';
const getSubstringIndex = (str, substring, n) => {
let times = 0;
let index = null;
while (times < n && index !== -1) {
index = str.indexOf(substring, index + 1);
times += 1;
}
return index;
};
/**
* Basic implementation of signature extraction.
*
* Really basic. Would work in the simplest of cases where there is only one signature
* in a document and ByteRange is only used once in it.
*
* @param {Buffer} pdf
* @returns {Object} {ByteRange: Number[], signature: Buffer, signedData: Buffer}
*/
export const extractSignature = (pdf, signatureCount = 1) => {
if (!(pdf instanceof Buffer)) {
throw new SignPdfError('PDF expected as Buffer.', SignPdfError.TYPE_INPUT);
}

// const byteRangePos = pdf.indexOf('/ByteRange [');
const byteRangePos = getSubstringIndex(pdf, '/ByteRange [', signatureCount);
if (byteRangePos === -1) {
throw new SignPdfError('Failed to locate ByteRange.', SignPdfError.TYPE_PARSE);
}
const byteRangeEnd = pdf.indexOf(']', byteRangePos);
if (byteRangeEnd === -1) {
throw new SignPdfError('Failed to locate the end of the ByteRange.', SignPdfError.TYPE_PARSE);
}
const byteRange = pdf.slice(byteRangePos, byteRangeEnd + 1).toString();
const matches = /\/ByteRange \[(\d+) +(\d+) +(\d+) +(\d+) *\]/.exec(byteRange);
if (matches === null) {
throw new SignPdfError('Failed to parse the ByteRange.', SignPdfError.TYPE_PARSE);
}
const ByteRange = matches.slice(1).map(Number);
const signedData = Buffer.concat([pdf.slice(ByteRange[0], ByteRange[0] + ByteRange[1]), pdf.slice(ByteRange[2], ByteRange[2] + ByteRange[3])]);
const signatureHex = pdf.slice(ByteRange[0] + ByteRange[1] + 1, ByteRange[2]).toString('binary').replace(/(?:00|>)+$/, '');
const signature = Buffer.from(signatureHex, 'hex').toString('binary');
return {
ByteRange: matches.slice(1, 5).map(Number),
signature,
signedData
};
};
2 changes: 2 additions & 0 deletions packages/utils/dist/findByteRange.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export function findByteRange(pdf: Buffer, placeholder?: string): any;
//# sourceMappingURL=findByteRange.d.ts.map
1 change: 1 addition & 0 deletions packages/utils/dist/findByteRange.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions packages/utils/dist/findByteRange.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { SignPdfError } from './SignPdfError';
import { DEFAULT_BYTE_RANGE_PLACEHOLDER } from './const';

/**
* Finds ByteRange information within a given PDF Buffer if one exists
*
* @param {Buffer} pdf
* @returns {Object} {byteRangePlaceholder: String, byteRangeStrings: String[], byteRange: String[]}
*/
export const findByteRange = (pdf, placeholder = DEFAULT_BYTE_RANGE_PLACEHOLDER) => {
if (!(pdf instanceof Buffer)) {
throw new SignPdfError('PDF expected as Buffer.', SignPdfError.TYPE_INPUT);
}
const byteRangeStrings = pdf.toString().match(/\/ByteRange\s*\[{1}\s*(?:(?:\d*|\/\*{10})\s+){3}(?:\d+|\/\*{10}){1}\s*]{1}/g);
if (!byteRangeStrings) {
throw new SignPdfError('No ByteRangeStrings found within PDF buffer', SignPdfError.TYPE_PARSE);
}
const byteRangePlaceholder = byteRangeStrings.find(s => s.includes(`/${placeholder}`));
const byteRanges = byteRangeStrings.map(brs => brs.match(/[^[\s]*(?:\d|\/\*{10})/g));
return {
byteRangePlaceholder,
byteRangeStrings,
byteRanges
};
};
6 changes: 6 additions & 0 deletions packages/utils/dist/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export * from "./const";
export * from "./extractSignature";
export * from "./findByteRange";
export * from "./removeTrailingNewLine";
export * from "./SignPdfError";
//# sourceMappingURL=index.d.ts.map
1 change: 1 addition & 0 deletions packages/utils/dist/index.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions packages/utils/dist/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './const';
export * from './extractSignature';
export * from './findByteRange';
export * from './removeTrailingNewLine';
export * from './SignPdfError';
7 changes: 7 additions & 0 deletions packages/utils/dist/readTestResource.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
*
* @param {string} filename
* @return Buffer
*/
export function readTestResource(filename: string): any;
//# sourceMappingURL=readTestResource.d.ts.map
1 change: 1 addition & 0 deletions packages/utils/dist/readTestResource.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions packages/utils/dist/readTestResource.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import fs from 'fs';

/**
*
* @param {string} filename
* @return Buffer
*/
export function readTestResource(filename) {
if (filename === '.' || /(\/|\\|\.\.)/.test(filename)) {
throw new Error(`"${filename}" is invalid filename.`);
}
return fs.readFileSync(`${__dirname}/../../../resources/${filename}`);
}
2 changes: 2 additions & 0 deletions packages/utils/dist/removeTrailingNewLine.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export function removeTrailingNewLine(pdf: Buffer): Buffer;
//# sourceMappingURL=removeTrailingNewLine.d.ts.map
1 change: 1 addition & 0 deletions packages/utils/dist/removeTrailingNewLine.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions packages/utils/dist/removeTrailingNewLine.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { SignPdfError } from './SignPdfError';
const sliceLastChar = (pdf, character) => {
const lastChar = pdf.slice(pdf.length - 1).toString();
if (lastChar === character) {
return pdf.slice(0, pdf.length - 1);
}
return pdf;
};

/**
* Removes a trailing new line if there is such.
*
* Also makes sure the file ends with an EOF line as per spec.
* @param {Buffer} pdf
* @returns {Buffer}
*/
export const removeTrailingNewLine = pdf => {
if (!(pdf instanceof Buffer)) {
throw new SignPdfError('PDF expected as Buffer.', SignPdfError.TYPE_INPUT);
}
let output = pdf;
output = sliceLastChar(output, '\n');
output = sliceLastChar(output, '\r');
const lastLine = output.slice(output.length - 6).toString();
if (lastLine !== '\n%%EOF') {
throw new SignPdfError('A PDF file must end with an EOF line.', SignPdfError.TYPE_PARSE);
}
return output;
};
3 changes: 2 additions & 1 deletion packages/utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"pades",
"digital signature"
],
"main": "dist/signpdf.js",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist",
"LICENSE",
Expand Down
4 changes: 1 addition & 3 deletions packages/utils/src/SignPdfError.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export const ERROR_TYPE_INPUT = 2;
export const ERROR_TYPE_PARSE = 3;
export const ERROR_VERIFY_SIGNATURE = 4;

class SignPdfError extends Error {
export class SignPdfError extends Error {
constructor(msg, type = ERROR_TYPE_UNKNOWN) {
super(msg);
this.type = type;
Expand All @@ -15,5 +15,3 @@ SignPdfError.TYPE_UNKNOWN = ERROR_TYPE_UNKNOWN;
SignPdfError.TYPE_INPUT = ERROR_TYPE_INPUT;
SignPdfError.TYPE_PARSE = ERROR_TYPE_PARSE;
SignPdfError.VERIFY_SIGNATURE = ERROR_VERIFY_SIGNATURE;

export default SignPdfError;
3 changes: 2 additions & 1 deletion packages/utils/src/SignPdfError.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import SignPdfError, {
import {
SignPdfError,
ERROR_TYPE_UNKNOWN,
ERROR_TYPE_INPUT,
ERROR_TYPE_PARSE,
Expand Down
6 changes: 2 additions & 4 deletions packages/utils/src/extractSignature.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import SignPdfError from './SignPdfError';
import {SignPdfError} from './SignPdfError';

const getSubstringIndex = (str, substring, n) => {
let times = 0; let
Expand All @@ -20,7 +20,7 @@ const getSubstringIndex = (str, substring, n) => {
* @param {Buffer} pdf
* @returns {Object} {ByteRange: Number[], signature: Buffer, signedData: Buffer}
*/
const extractSignature = (pdf, signatureCount = 1) => {
export const extractSignature = (pdf, signatureCount = 1) => {
if (!(pdf instanceof Buffer)) {
throw new SignPdfError(
'PDF expected as Buffer.',
Expand Down Expand Up @@ -72,5 +72,3 @@ const extractSignature = (pdf, signatureCount = 1) => {
signedData,
};
};

export default extractSignature;
7 changes: 3 additions & 4 deletions packages/utils/src/extractSignature.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import fs from 'fs';
import extractSignature from './extractSignature';
import SignPdfError from './SignPdfError';
import readTestResource from './readTestResource';
import {extractSignature} from './extractSignature';
import {SignPdfError} from './SignPdfError';
import {readTestResource} from './readTestResource';

describe(extractSignature, () => {
it('expects PDF to be Buffer', () => {
Expand Down
6 changes: 2 additions & 4 deletions packages/utils/src/findByteRange.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import SignPdfError from './SignPdfError';
import {SignPdfError} from './SignPdfError';
import {DEFAULT_BYTE_RANGE_PLACEHOLDER} from './const';

/**
Expand All @@ -7,7 +7,7 @@ import {DEFAULT_BYTE_RANGE_PLACEHOLDER} from './const';
* @param {Buffer} pdf
* @returns {Object} {byteRangePlaceholder: String, byteRangeStrings: String[], byteRange: String[]}
*/
const findByteRange = (pdf, placeholder = DEFAULT_BYTE_RANGE_PLACEHOLDER) => {
export const findByteRange = (pdf, placeholder = DEFAULT_BYTE_RANGE_PLACEHOLDER) => {
if (!(pdf instanceof Buffer)) {
throw new SignPdfError(
'PDF expected as Buffer.',
Expand All @@ -33,5 +33,3 @@ const findByteRange = (pdf, placeholder = DEFAULT_BYTE_RANGE_PLACEHOLDER) => {
byteRanges,
};
};

export default findByteRange;
6 changes: 3 additions & 3 deletions packages/utils/src/findByteRange.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import PDFDocument from 'pdfkit';
import findByteRange from './findByteRange';
import SignPdfError from './SignPdfError';
import readTestResource from './readTestResource';
import {findByteRange} from './findByteRange';
import {SignPdfError} from './SignPdfError';
import {readTestResource} from './readTestResource';

describe(findByteRange, () => {
it('expects PDF to be Buffer', () => {
Expand Down
5 changes: 5 additions & 0 deletions packages/utils/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './const'
export * from './extractSignature'
export * from './findByteRange'
export * from './removeTrailingNewLine'
export * from './SignPdfError'
4 changes: 1 addition & 3 deletions packages/utils/src/readTestResource.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@ import fs from 'fs';
* @param {string} filename
* @return Buffer
*/
function readTestResource(filename) {
export function readTestResource(filename) {
if (filename === '.' || (/(\/|\\|\.\.)/).test(filename)) {
throw new Error(`"${filename}" is invalid filename.`);
}
return fs.readFileSync(`${__dirname}/../../../resources/${filename}`);
}

export default readTestResource;
6 changes: 2 additions & 4 deletions packages/utils/src/removeTrailingNewLine.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import SignPdfError from './SignPdfError';
import {SignPdfError} from './SignPdfError';

const sliceLastChar = (pdf, character) => {
const lastChar = pdf.slice(pdf.length - 1).toString();
Expand All @@ -16,7 +16,7 @@ const sliceLastChar = (pdf, character) => {
* @param {Buffer} pdf
* @returns {Buffer}
*/
const removeTrailingNewLine = (pdf) => {
export const removeTrailingNewLine = (pdf) => {
if (!(pdf instanceof Buffer)) {
throw new SignPdfError(
'PDF expected as Buffer.',
Expand All @@ -38,5 +38,3 @@ const removeTrailingNewLine = (pdf) => {

return output;
};

export default removeTrailingNewLine;
4 changes: 2 additions & 2 deletions packages/utils/src/removeTrailingNewLine.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import removeTrailingNewLine from './removeTrailingNewLine';
import SignPdfError from './SignPdfError';
import {removeTrailingNewLine} from './removeTrailingNewLine';
import {SignPdfError} from './SignPdfError';

describe(removeTrailingNewLine, () => {
it('expects PDF to be Buffer', () => {
Expand Down
Loading

0 comments on commit afb3d75

Please sign in to comment.