XML sign using nodeJs:
- You can get sample signature from any website who provide DSC .
The sample format should be in.pfx format because for application signing it’s thumb rule that you should have .pfx file and this pfx file will use tho sign both type of document xml and PDF.
The given website we have downloaded sample. You can go through it and download file and name will be document signer certificate.
https://www.e-mudhra.com/repository/
Once you will download you should have password to open and read certificate and other details.
Demo :emudhra
- Once you will get this file then you need to upload your file in particular directory/bucket.
For uploading you can use same file upload process with given NPM package
https://www.npmjs.com/package/express-fileupload
- Include this NPM Package
letforge = require(“node-forge”);
forge.options.usePureJavaScript = true; //For Javascript Strict Rule
- Once you will upload your .pfx file you need to pass the location of uploaded file.
request.body.data = This is the json data you are getting from front-end
Let uploadedPfxUrl = request.body.pfx_url
Now follow the given code and same use in your code
// get file into buffer from the uploaded bucket/Directory.
letcertificateFile = await axios.get(uploadedPfxUrl, {
responseType:”arraybuffer”,
});
Convert into base64
letreturnedB64 = Buffer.from(certificateFile.data).toString(“base64”);
Get P12Der
let p12Der = forge.util.decode64(returnedB64);
Convert into P12Asn1
let p12Asn1 = forge.asn1.fromDer(p12Der);
Get P12
let p12 = forge.pkcs12.pkcs12FromAsn1(
p12Asn1,
request.body.data.password //Pass your pfx password
);
// get the public key, the forge library I have included in top
Let certBags = p12.getBags({ bagType:forge.pki.oids.certBag });
// console.log(“certBags”, certBags);
//Get the private key
Let pkeyBags = p12.getBags({
bagType:forge.pki.oids.pkcs8ShroudedKeyBag,
});
It will return the array so you need to pass the value as per index
Let certBag = certBags[forge.pki.oids.certBag][0];
// console.log(“certBag”, certBag);
// fetching keyBag
Let keybag = pkeyBags[forge.pki.oids.pkcs8ShroudedKeyBag][0];
Pem Value public and private get
Let privateKeyPem = forge.pki.privateKeyToPem(keybag.key);
// console.log(“privateKeyPem”, privateKeyPem);
// generate pem from cert
Let certificate = forge.pki.certificateToPem(certBag.cert); // with header and footer
//For XML value
letcertDer = forge.pki.pemToDer(certificate);
letp12b64 = forge.util.encode64(certDer.data); // without header and footer
//Base 64 Certificate Get
Let cert = forge.pki.certificateFromPem(certificate);
//Save the particular value from object that you will need to pass when you sign the xml file
Let email = cert.extensions.find((o) =>o.name === “subjectAltName”);
Const md = forge.md.sha1.create();
md.update(
forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes()
);
//Thumb Print Get
Const hex = md.digest().toHex();
Let hexSignature = forge.util.bytesToHex(cert.signature);
// console.log(“hexSignature”, hexSignature);
Let certificateDataObj = {
validity:cert.validity,
partyName:cert.subject,
certificateNumber:cert.serialNumber,
certificateIssuer:cert.issuer,
email:email.altNames,
thumbPrint:hex,
certificate:p12b64,
// certificate: certificate,
signature:privateKeyPem,
};
return { certificateDataObj };
}
//Generate Modulus
// get public exponent & modulus as base64 encoded
Let modulus = forge.util.encode64(
forge.util.hexToBytes(forgePrivateKey.n.toString(16))
);
//Generate Exponent
Let exponent = forge.util.encode64(
forge.util.hexToBytes(forgePrivateKey.e.toString(16))
);
3) Now reading part done so now you need to sign xml file.
Here, you need a reference tag to add signature,
Let xref = “.//*[local-name(.)=’TAG Name’]”;
Let xmlString = “ALL xml tag string”
Let pvtKey= You all ready have which you have read from .pfx file
Let pubKey = You all ready have which you have read from .pfx file
Let modulus = You all ready have which you have read from .pfx file
Let exponent = You all ready have which you have read from .pfx file
letsignXML = (xmlString, xmlRef, pvtKey, pubKey, modulus, exponent) => {
// instance for sign xml
letsig = newSignedXml();
// added xml node path &propoerties for sign
sig.addReference(
xmlRef,
[
“http://www.w3.org/2000/09/xmldsig#enveloped-signature”,
“http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments”,
],
“http://www.w3.org/2000/09/xmldsig#sha1”,
“”,
“”,
“”,
true
);
// putting algos for sign
sig.signatureAlgorithm = “http://www.w3.org/2000/09/xmldsig#rsa-sha1”;
sig.canonicalizationAlgorithm =
“http://www.w3.org/TR/2001/REC-xml-c14n-20010315”;
// added pvt key pem
sig.signingKey = pvtKey;
// added public key for verification
sig.keyInfoProvider = {
getKeyInfo: (key, prefix) => {
return`<X509Data><X509Certificate>${pubKey}</X509Certificate></X509Data><KeyValue><RSAKeyValue><Modulus>${modulus}</Modulus><Exponent>${exponent}</Exponent></RSAKeyValue></KeyValue>`;
},
};
//sign the xml doc with the data
sig.computeSignature(xmlString);
returnsig.getSignedXml(); // return signed xml file
};
Digital Signature process to sign XML File with nodejs:
- Uploading and reading part you have to follow same process
- Now you need to add signature, for signature you can use given library
https://www.npmjs.com/package/node-signpdf
Include this library as per given below
let forge = require(“node-forge”);
forge.options.usePureJavaScript = true;
const signer = require(“node-signpdf”).default;
- You also need to get placeholder to add signature
Const signedDoc = signer.sign(pdfBufferToSign, pfxFileBuffer.data, {
passphrase:password,
});