-
-
Notifications
You must be signed in to change notification settings - Fork 178
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,6 @@ | |
"targets": { | ||
"node": "current" | ||
} | ||
}], | ||
}] | ||
] | ||
} |
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 |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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; |
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 |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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'; |
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 |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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 | ||
}; | ||
}; |
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 |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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 | ||
}; | ||
}; |
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 |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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'; |
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 |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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}`); | ||
} |
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 |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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; | ||
}; |
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, | ||
|
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' |