I'm working on a project using the xml-crypto package in TypeScript to sign XML documents. My goal is to sign the XML and include a reference to the KeyInfo element within the same signature.
Here's what I've done so far:
I've successfully generated the signature for my XML data.
However, I'm encountering two major issues:
the following xpath cannot be signed because it was not found: //*[local-name(.)='KeyInfo']
Here is my current implementation:
private localElemName: string;
private xmlBody: any;
private xmlBuilder = new XMLBuilder({
attributeNamePrefix: '@_',
ignoreAttributes: false,
format: true,
})
createDigitalSignature(xmlObj: any){
this.xmlBody = this.xmlBuilder.build(xmlObj)
this.localElemName = this.getKey(xmlObj)
let sig = new SignedXml({ privateKey: fs.readFileSync(path.join(__dirname, "..", "..", "certificates_keys", "BANK0201.key")),
publicCert: fs.readFileSync(path.join(__dirname, "..", "..", "certificates_keys", "BANK0201_TRANSPORT_TEST.pem"))
});
sig.addReference({
xpath: `//*[local-name(.)='${this.localElemName}']`,
isEmptyUri: true,
transforms: ["http://www.w3.org/2000/09/xmldsig#enveloped-signature","http://www.w3.org/TR/2001/REC-xml-c14n-20010315"],
digestAlgorithm: "http://www.w3.org/2001/04/xmlenc#sha256",
});
sig.canonicalizationAlgorithm = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'
sig.signatureAlgorithm = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
sig.keyInfoAttributes = {
'Id': '_8401036a-cd29-4f5b-a48a-9ecf4d515d98'
}
sig.getKeyInfoContent({
prefix: 'ds'
})
sig.computeSignature(this.xmlBody, {
prefix: "ds",
location: { reference: `//*[local-name(.)='${this.localElemName}']`, action: "after" },
});
sig.addReference({
xpath: `//*[local-name(.)='KeyInfo']`,
uri: '#_8401036a-cd29-4f5b-a48a-9ecf4d515d98',
transforms: ["http://www.w3.org/TR/2001/REC-xml-c14n-20010315"],
digestAlgorithm: 'http://www.w3.org/2001/04/xmlenc#sha256',
})
sig.computeSignature(sig.getSignedXml(), {
prefix: "ds",
location: { reference: `//*[local-name(.)='${this.localElemName}']`, action: "after" },
});
const xmlSigned = sig.getSignedXml()
return xmlSigned
}
getKey(xmlObj: xmlObject){
const key = Object.keys(xmlObj.Document).pop()
return key
}
Questions:
Any guidance or suggestions would be greatly appreciated!
I tried signing the XML document using the xml-crypto package and then adding a reference to the KeyInfo element within the signature. I expected to create a valid signature that includes a reference to KeyInfo.
However, when adding the reference, I encountered an XPath error stating that the KeyInfo element could not be found. Additionally, recomputing the signature after adding the reference either caused the same error or resulted in a second, unwanted signature being appended to the XML.
According to these issue and draft PR (which were created around Apr 10th 2024):
it is not possible without additional enhancements to xml-crypto library.