Search code examples
typescriptxmlxpathxml-signaturexml-crypto

How to Add Reference to KeyInfo in XML Signature Using xml-crypto in TypeScript?


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:

  1. Adding Key Info Reference Using XPath: When I try to add a reference to the KeyInfo element using XPath, I receive the following error: the following xpath cannot be signed because it was not found: //*[local-name(.)='KeyInfo']
  2. Recomputing the Signature: My attempt to compute the signature first and then add the reference to the KeyInfo element later either results in the error mentioned above or appends a second signature into the already signed XML, which is not the desired outcome

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:

  1. How can I correctly add a reference to the KeyInfo element without encountering the XPath error?
  2. Is there a proper way to recompute the signature to include a reference to KeyInfo without appending a second signature?

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.


Solution

  • According to these issue and draft PR (which were created around Apr 10th 2024):

    1. https://github.com/node-saml/xml-crypto/issues/463
    2. https://github.com/node-saml/xml-crypto/pull/464

    it is not possible without additional enhancements to xml-crypto library.

    BTW. I know that this should have been comment but I do not have enought reputation at the moment to add comments.