Verifying a signature involves two steps: loading the signature element and then checking it against the full XML document.
Important Security Note: To prevent attacks, do not use the data parsed from the original document to perform your business logic. Instead, verify the signature, then use sig.getSignedReferences() to retrieve the actual bytes that were signed. Only use the data extracted from these authenticated bytes.
Constructor Options for Verification:
publicCert (optional): A string (or multiple PEM strings) or a Buffer containing the certificate. Used if getCertFromKeyInfo() returns null.privateKey (optional): A string or Buffer used for verifying symmetrical signatures (HMAC).getCertFromKeyInfo (optional): A function to customize how the certificate is determined from the XML. If it returns null, the constructor falls back to publicCert, then privateKey.
Workflow:
- Parse the XML using a DOM parser (e.g.,
@xmldom/xmldom). - Locate the
<Signature> element using XPath. - Initialize
SignedXml and call loadSignature(signatureElement). - Call
checkSignature(xml). - If successful, retrieve authenticated data via
sig.getSignedReferences().
const { DOMParser } = require("@xmldom/xmldom");
const xpath = require("xpath");
const { SignedXml } = require("xml-crypto");
const fs = require("fs");
// 1. Setup dependencies: npm install @xmldom/xmldom xpath
const xml = fs.readFileSync("signed.xml", "utf8");
const doc = new DOMParser().parseFromString(xml, "text/xml");
// 2. Find the signature element
const signature = xpath.select1(
"//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']",
doc,
);
// 3. Verify
const sig = new SignedXml({ publicCert: fs.readFileSync("client_public.pem") });
sig.loadSignature(signature);
const res = sig.checkSignature(xml);
if (!res) {
throw new Error("Invalid signature");
}
// 4. SECURELY extract authenticated data
const signedBytes = sig.getSignedReferences();
const authenticatedDoc = new DOMParser().parseFromString(signedBytes[0], "text/xml");
// Now it is safe to use authenticatedDoc for parsing business logic