I am having trouble signing an xml using xml-crypto library. Here is my code:
const fs = require("fs");
const xmlCrypto = require("xml-crypto");
const xpath = require("xpath");
const dom = require("xmldom").DOMParser;
var xml = "<book><title>Harry Potter</title></book>";
var xmlDocument = new dom().parseFromString(xml, "text/xml");
var node = xpath.select("//title", xmlDocument)[0];
console.log(node.localName + ": " + node.firstChild.data);
console.log("Node: " + node.toString());
const privateKey = fs.readFileSync(
"./certifications/universal-pk.pem",
"utf-8"
);
console.log("privateKey", privateKey);
const reference = {
uri: "",
transforms: ["canonicalize", "c14n"],
digestAlgorithm: "http://www.w3.org/2001/04/xmlenc#sha256",
};
const sig = new xmlCrypto.SignedXml();
sig.addReference(reference);
sig.signingKey = privateKey;
sig.computeSignature(node);
And the console log:
title: Harry Potter
Node: <title>Harry Potter</title>
privateKey -----BEGIN PRIVATE KEY-----
.......
-----END PRIVATE KEY-----
[xmldom error] invalid doc source
@#[line:0,col:undefined]
\api\node_modules\xml-crypto\node_modules\xpath\xpath.js:1278
throw new Error("XPath parse error");
^
Error: XPath parse error
I also tried the sample code from https://www.npmjs.com/package/xml-crypto
However, I also received the exact same error message.
The problem is that you're not passing correct input to computeSignature
method.
The docs say:
computeSignature(xml, [options]) - compute the signature of the given xml where:
xml - a string containing a xml document
https://www.npmjs.com/package/xml-crypto#signing-xml-documents
So, it takes an XML string, but node
variable which you are sending here
sig.computeSignature(node);
is actually an xmldom
object, hence the error.
So, send an XML string instead:
sig.computeSignature(node.toString());
Also, it seems you're using some older version, so when changed in accordance with the current docs, your code should look like this:
(note that you don't really need to use DOMParser, you can pass xml string and modify xpath selector in reference)
var sig = new xmlCrypto.SignedXml({ privateKey });
sig.addReference({
xpath: "//*[local-name(.)='title']",
digestAlgorithm: "http://www.w3.org/2000/09/xmldsig#sha1",
transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"],
});
sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
sig.signatureAlgorithm = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";
sig.computeSignature(node.toString()); // or just xml and modify xpath..