Skip to content

Instantly share code, notes, and snippets.

@cmjunior
Created July 1, 2023 16:25
Show Gist options
  • Save cmjunior/91e4fcfac27328a1da77849b93b515b3 to your computer and use it in GitHub Desktop.
Save cmjunior/91e4fcfac27328a1da77849b93b515b3 to your computer and use it in GitHub Desktop.
Code where I convert the Fortify certificate to the correct format.
var el = document.createElement('peculiar-fortify-certificates');
el.debug = true;
el.filters = {
onlyWithPrivateKey: true
};
el.addEventListener('cancel', function() {
alert('"cancel" callback');
});
el.addEventListener('continue', function(event) {
continueHandler(event, modifiedPdfBuffer);
});
document.getElementsByTagName('section')[0].prepend(el);
};
async function continueHandler(event, pdfBuffer) {
// Here I get the fortify certificate
var provider = await event.detail.server.getCrypto(event.detail.providerId);
provider.sign = provider.subtle.sign.bind(provider.subtle);
pkijs.setEngine(
"newEngine",
provider,
new pkijs.CryptoEngine({
name: "",
crypto: provider,
subtle: provider.subtle,
})
);
var cert = await provider.certStorage.getItem(event.detail.certificateId);
var privateKey = await provider.keyStorage.getItem(event.detail.privateKeyId);
var certRawData = await provider.certStorage.exportCert('raw', cert);
var pkiCert = new pkijs.Certificate({
schema: asn1js.fromBER(certRawData).result,
});
const hashBuffer = await provider.subtle.digest('SHA-256', pdf);
const signedAttr = [];
signedAttr.push(new pkijs.Attribute({
type: "1.2.840.113549.1.9.3",// contentType (PKCS #9)
values: [
new asn1js.ObjectIdentifier({ value: "1.2.840.113549.1.7.1" })// data (PKCS #7)
]
})); // contentType
signedAttr.push(new pkijs.Attribute({
type: "1.2.840.113549.1.9.5",// signingTime (PKCS #9)
values: [
new asn1js.UTCTime({ valueDate: new Date() })
]
})); // signingTime
signedAttr.push(new pkijs.Attribute({
type: "1.2.840.113549.1.9.4",// messageDigest (PKCS #9)
values: [
new asn1js.OctetString({ valueHex: hashBuffer })
]
})); // messageDigest
var signedData = new pkijs.SignedData({
version: 1,
digestAlgorithms: [
new pkijs.AlgorithmIdentifier({
algorithmId: "1.3.14.3.2.26",
algorithmParams: new asn1js.Null()
}),
],
encapContentInfo: new pkijs.EncapsulatedContentInfo({
eContentType: "1.2.840.113549.1.7.1", // "data" content type
}),
signerInfos: [
new pkijs.SignerInfo({
version: 1,
sid: new pkijs.IssuerAndSerialNumber({
issuer: pkiCert.issuer,
serialNumber: pkiCert.serialNumber,
}),
digestAlgorithm: new pkijs.AlgorithmIdentifier({algorithmId: "1.3.14.3.2.26", algorithmParams: new asn1js.Null()}),
signatureAlgorithm: new pkijs.AlgorithmIdentifier({algorithmId: "1.2.840.113549.1.1.5", algorithmParams: new asn1js.Null()}),
signedAttrs: new pkijs.SignedAndUnsignedAttributes({
type: "0",
attributes: signedAttr,
}),
}),
],
certificates: [pkiCert],
});
await signedData.sign(privateKey, 0, 'SHA-256', pdf);
const cms = new pkijs.ContentInfo({
contentType: "1.2.840.113549.1.7.2",
content: signedData.toSchema(true),
});
const result = cms.toSchema().toBER(false);
let stringSignature = Array.prototype.map.call(new Uint8Array(result), x => (`00${x.toString(16)}`).slice(-2)).join('');
let lenSignature = result.byteLength;
if ( (placeholderLength / 2) - lenSignature > 0 ) {
stringSignature += Buffer
.from(String.fromCharCode(0).repeat((placeholderLength / 2) - lenSignature))
.toString('hex');
};
let output = Buffer.concat([
pdf.slice(0, byteRange[1]),
Buffer.from(`<${stringSignature}>`),
pdf.slice(byteRange[1])
]);
const a = document.createElement('a');
const blob = new Blob([output], { type: 'application/pdf' });
a.href = URL.createObjectURL(blob);
a.download = 'pdf-signed.pdf';
a.click();
@akhateeb22
Copy link

@cmjunior
Thanks for the code, I still getting problem in getting the /ByteRange of a pdf, could you please provide more details about the process of reading the pdf as buffer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment