mirror of
https://github.com/documenso/documenso.git
synced 2025-11-18 02:32:00 +10:00
chore: use rust based cms signing
This commit is contained in:
@ -1,4 +1,3 @@
|
||||
import signer from 'node-signpdf';
|
||||
import {
|
||||
PDFArray,
|
||||
PDFDocument,
|
||||
@ -9,6 +8,8 @@ import {
|
||||
rectangle,
|
||||
} from 'pdf-lib';
|
||||
|
||||
import { BYTE_RANGE_PLACEHOLDER } from '../constants/byte-range';
|
||||
|
||||
export type AddSigningPlaceholderOptions = {
|
||||
pdf: Buffer;
|
||||
};
|
||||
@ -20,9 +21,9 @@ export const addSigningPlaceholder = async ({ pdf }: AddSigningPlaceholderOption
|
||||
const byteRange = PDFArray.withContext(doc.context);
|
||||
|
||||
byteRange.push(PDFNumber.of(0));
|
||||
byteRange.push(PDFName.of(signer.byteRangePlaceholder));
|
||||
byteRange.push(PDFName.of(signer.byteRangePlaceholder));
|
||||
byteRange.push(PDFName.of(signer.byteRangePlaceholder));
|
||||
byteRange.push(PDFName.of(BYTE_RANGE_PLACEHOLDER));
|
||||
byteRange.push(PDFName.of(BYTE_RANGE_PLACEHOLDER));
|
||||
byteRange.push(PDFName.of(BYTE_RANGE_PLACEHOLDER));
|
||||
|
||||
const signature = doc.context.obj({
|
||||
Type: 'Sig',
|
||||
72
packages/signing/helpers/update-signing-placeholder.test.ts
Normal file
72
packages/signing/helpers/update-signing-placeholder.test.ts
Normal file
@ -0,0 +1,72 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { updateSigningPlaceholder } from './update-signing-placeholder';
|
||||
|
||||
describe('updateSigningPlaceholder', () => {
|
||||
const pdf = Buffer.from(`
|
||||
20 0 obj
|
||||
<<
|
||||
/Type /Sig
|
||||
/Filter /Adobe.PPKLite
|
||||
/SubFilter /adbe.pkcs7.detached
|
||||
/ByteRange [ 0 /********** /********** /********** ]
|
||||
/Contents <0000000000000000000000000000000000000000000000000000000>
|
||||
/Reason (Signed by Documenso)
|
||||
/M (D:20210101000000Z)
|
||||
>>
|
||||
endobj
|
||||
`);
|
||||
|
||||
it('should not throw an error', () => {
|
||||
expect(() => updateSigningPlaceholder({ pdf })).not.toThrowError();
|
||||
});
|
||||
|
||||
it('should not modify the original PDF', () => {
|
||||
const result = updateSigningPlaceholder({ pdf });
|
||||
|
||||
expect(result.pdf).not.toEqual(pdf);
|
||||
});
|
||||
|
||||
it('should return a PDF with the same length as the original', () => {
|
||||
const result = updateSigningPlaceholder({ pdf });
|
||||
|
||||
expect(result.pdf).toHaveLength(pdf.length);
|
||||
});
|
||||
|
||||
it('should update the byte range and return it', () => {
|
||||
const result = updateSigningPlaceholder({ pdf });
|
||||
|
||||
expect(result.byteRange).toEqual([0, 184, 241, 92]);
|
||||
});
|
||||
|
||||
it('should only update the last signature in the PDF', () => {
|
||||
const pdf = Buffer.from(`
|
||||
20 0 obj
|
||||
<<
|
||||
/Type /Sig
|
||||
/Filter /Adobe.PPKLite
|
||||
/SubFilter /adbe.pkcs7.detached
|
||||
/ByteRange [ 0 /********** /********** /********** ]
|
||||
/Contents <0000000000000000000000000000000000000000000000000000000>
|
||||
/Reason (Signed by Documenso)
|
||||
/M (D:20210101000000Z)
|
||||
>>
|
||||
endobj
|
||||
21 0 obj
|
||||
<<
|
||||
/Type /Sig
|
||||
/Filter /Adobe.PPKLite
|
||||
/SubFilter /adbe.pkcs7.detached
|
||||
/ByteRange [ 0 /********** /********** /********** ]
|
||||
/Contents <0000000000000000000000000000000000000000000000000000000>
|
||||
/Reason (Signed by Documenso)
|
||||
/M (D:20210101000000Z)
|
||||
>>
|
||||
endobj
|
||||
`);
|
||||
|
||||
const result = updateSigningPlaceholder({ pdf });
|
||||
|
||||
expect(result.byteRange).toEqual([0, 512, 569, 92]);
|
||||
});
|
||||
});
|
||||
39
packages/signing/helpers/update-signing-placeholder.ts
Normal file
39
packages/signing/helpers/update-signing-placeholder.ts
Normal file
@ -0,0 +1,39 @@
|
||||
export type UpdateSigningPlaceholderOptions = {
|
||||
pdf: Buffer;
|
||||
};
|
||||
|
||||
export const updateSigningPlaceholder = ({ pdf }: UpdateSigningPlaceholderOptions) => {
|
||||
const length = pdf.length;
|
||||
|
||||
const byteRangePos = pdf.lastIndexOf('/ByteRange');
|
||||
const byteRangeStart = pdf.indexOf('[', byteRangePos);
|
||||
const byteRangeEnd = pdf.indexOf(']', byteRangePos);
|
||||
|
||||
const byteRangeSlice = pdf.subarray(byteRangeStart, byteRangeEnd + 1);
|
||||
|
||||
const signaturePos = pdf.indexOf('/Contents', byteRangeEnd);
|
||||
const signatureStart = pdf.indexOf('<', signaturePos);
|
||||
const signatureEnd = pdf.indexOf('>', signaturePos);
|
||||
|
||||
const signatureSlice = pdf.subarray(signatureStart, signatureEnd + 1);
|
||||
|
||||
const byteRange = [0, 0, 0, 0];
|
||||
|
||||
byteRange[1] = signatureStart;
|
||||
byteRange[2] = byteRange[1] + signatureSlice.length;
|
||||
byteRange[3] = length - byteRange[2];
|
||||
|
||||
const newByteRange = `[${byteRange.join(' ')}]`.padEnd(byteRangeSlice.length, ' ');
|
||||
|
||||
const updatedPdf = Buffer.concat([
|
||||
pdf.subarray(0, byteRangeStart),
|
||||
Buffer.from(newByteRange),
|
||||
pdf.subarray(byteRangeEnd + 1),
|
||||
]);
|
||||
|
||||
if (updatedPdf.length !== length) {
|
||||
throw new Error('Updated PDF length does not match original length');
|
||||
}
|
||||
|
||||
return { pdf: updatedPdf, byteRange };
|
||||
};
|
||||
Reference in New Issue
Block a user