From c362ec88339a3221d97d55eaea2ec443348b57d4 Mon Sep 17 00:00:00 2001 From: Chris Barth Date: Mon, 14 Sep 2026 20:19:35 -0500 Subject: [PATCH 1/4] test: cover idAttribute, implicitTransforms and fail-closed error paths `idAttribute` and `implicitTransforms` were documented and never executed. Tests show that signing reuses an id already held in the named attribute, that verification resolves a Reference through it and fails without it, and that it widens the duplicate-id wrapping check. A signer that applied exclusive C14N without declaring it verifies only when `implicitTransforms` names it. The README example listed Canonical XML 1.0 as the implicit transform, which xml-crypto already applies wherever the transforms end without a canonicalization, so the example changed nothing. It now uses exclusive C14N, with a note on where Canonical XML 1.0 is applied. The `idAttribute` entry said it replaced the default id attributes; it adds one ahead of them. "signer appends signature to a non-existing reference node" passed on `Missing canonicalizationAlgorithm`. It now configures signing fully and asserts the message it is named for. Error contracts that keep signing from inheriting a default and keep verification failing closed: - addReference with no digestAlgorithm, or no or empty transforms - computeSignature with no signatureAlgorithm - loadSignature on a Signature missing a Reference, CanonicalizationMethod, DigestMethod or its Algorithm, DigestValue or its value, or carrying two DigestValues - checkSignature's own Reference guard, and checkSignature with no signature loaded Refs #573 Co-Authored-By: Claude Opus 5 --- README.md | 9 +- test/signature-integration-tests.spec.ts | 107 ++++++++++++++++- test/signature-unit-tests.spec.ts | 141 +++++++++++++++++++++-- 3 files changed, 245 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index c7e6f77..8560bfa 100644 --- a/README.md +++ b/README.md @@ -294,16 +294,19 @@ If you keep failing verification, it is worth trying to guess such a hidden tran ```javascript const sig = new SignedXml({ - implicitTransforms: ["http://www.w3.org/TR/2001/REC-xml-c14n-20010315"], + implicitTransforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"], publicCert: fs.readFileSync("client_public.pem"), }); sig.loadSignature(signature); const res = sig.checkSignature(xml); ``` +Implicit transforms run after the transforms a `` declares. Where the transforms would +otherwise end without a canonicalization, xml-crypto applies Canonical XML 1.0, so an implicit +`http://www.w3.org/TR/2001/REC-xml-c14n-20010315` changes nothing there. + You might find it difficult to guess such transforms, but there are typical transforms you can try. -- - - - @@ -315,7 +318,7 @@ You might find it difficult to guess such transforms, but there are typical tran The `SignedXml` constructor provides an abstraction for sign and verify xml documents. The object is constructed using `new SignedXml(options?: SignedXmlOptions)` where the possible options are: - `idMode` - default `null` - if the value of `wssecurity` is passed it will create/validate id's with the ws-security namespace. -- `idAttribute` - string - default `Id` or `ID` or `id` - the name of the attribute that contains the id of the element +- `idAttribute` - string - default `undefined` - the name of an additional attribute that holds an element's id; it is checked before `Id`, `ID` and `id` - `privateKey` - string or Buffer - default `null` - the private key to use for signing - `publicCert` - string or Buffer - default `null` - the public certificate to use for verifying - `signatureAlgorithm` - string - the signature algorithm to use diff --git a/test/signature-integration-tests.spec.ts b/test/signature-integration-tests.spec.ts index 2fd41c5..bb2040d 100644 --- a/test/signature-integration-tests.spec.ts +++ b/test/signature-integration-tests.spec.ts @@ -1,6 +1,7 @@ import * as xpath from "xpath"; import * as xmldom from "@xmldom/xmldom"; -import { SignedXml, SignedXmlOptions } from "../src/index"; +import { SignedXml, SignedXmlOptions, findAncestorNs } from "../src/index"; +import * as crypto from "crypto"; import * as fs from "fs"; import { expect } from "chai"; import * as isDomNode from "@xmldom/is-dom-node"; @@ -1154,4 +1155,108 @@ describe("Signature integration tests", function () { ]); }); }); + + describe("options", function () { + const exclusiveC14n = "http://www.w3.org/2001/10/xml-exc-c14n#"; + const privateKey = fs.readFileSync("./test/static/client.pem"); + const publicCert = fs.readFileSync("./test/static/client_public.pem"); + + function sign(xml: string, options: SignedXmlOptions, transforms: string[]): string { + const sig = new SignedXml({ + ...options, + privateKey, + canonicalizationAlgorithm: exclusiveC14n, + signatureAlgorithm: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", + }); + sig.addReference({ + xpath: "//*[local-name(.)='book']", + transforms, + digestAlgorithm: "http://www.w3.org/2001/04/xmlenc#sha256", + }); + sig.computeSignature(xml); + return sig.getSignedXml(); + } + + function verifier(xml: string, options: SignedXmlOptions): SignedXml { + const signature = xpath.select1( + "//*[local-name(.)='Signature']", + new xmldom.DOMParser().parseFromString(xml), + ); + isDomNode.assertIsNodeLike(signature); + const sig = new SignedXml({ ...options, publicCert }); + sig.loadSignature(signature); + return sig; + } + + describe("idAttribute", function () { + const idAttribute = "AssertionID"; + const signBook = () => + sign( + 'Harry Potter', + { idAttribute }, + [exclusiveC14n], + ); + + it("signs an element by the id it already carries in that attribute", function () { + const signed = signBook(); + + expect(signed).to.include(''); + expect(signed).to.include(''); + }); + + it("resolves a reference through that attribute when verifying", function () { + const signed = signBook(); + + expect(verifier(signed, {}).checkSignature(signed)).to.be.false; + expect(verifier(signed, { idAttribute }).checkSignature(signed)).to.be.true; + }); + + it("rejects a document where a default id attribute repeats that id", function () { + const signed = signBook().replace( + "", + 'Forged', + ); + + expect(() => verifier(signed, { idAttribute }).checkSignature(signed)).to.throw( + /in order to prevent signature wrapping attack/, + ); + }); + }); + + describe("implicitTransforms", function () { + it("applies a transform the signer used but did not declare", function () { + const declared = sign( + 'Harry Potter', + {}, + ["http://www.w3.org/2000/09/xmldsig#enveloped-signature", exclusiveC14n], + ); + // A signer that applied exclusive C14N without declaring it: drop the Transform, then sign + // SignedInfo again. + const undeclared = declared.replace(``, ""); + expect(undeclared).to.not.equal(declared); + + const doc = new xmldom.DOMParser().parseFromString(undeclared); + const signedInfo = xpath.select1("//*[local-name(.)='SignedInfo']", doc); + isDomNode.assertIsNodeLike(signedInfo); + const canonSignedInfo = new SignedXml().getCanonXml([exclusiveC14n], signedInfo, { + ancestorNamespaces: findAncestorNs(doc, "//*[local-name(.)='SignedInfo']"), + }); + const signatureValue = crypto + .createSign("RSA-SHA256") + .update(canonSignedInfo) + .sign(privateKey, "base64"); + const signed = undeclared.replace( + /[^<]*/, + `${signatureValue}`, + ); + + expect(verifier(signed, {}).checkSignature(signed)).to.be.false; + const sig = verifier(signed, { implicitTransforms: [exclusiveC14n] }); + expect(sig.checkSignature(signed)).to.be.true; + expect(sig.getSignedReferences()).to.deep.equal([ + 'Harry Potter', + ]); + }); + }); + }); }); diff --git a/test/signature-unit-tests.spec.ts b/test/signature-unit-tests.spec.ts index 269f97e..64852fd 100644 --- a/test/signature-unit-tests.spec.ts +++ b/test/signature-unit-tests.spec.ts @@ -1071,6 +1071,89 @@ describe("Signature unit tests", function () { failInvalidSignature("./test/static/invalid_signature_without_transforms_element.xml"); }); }); + + describe("reject malformed signature", function () { + const validXml = fs.readFileSync("./test/static/valid_signature.xml", "utf8"); + const publicCert = fs.readFileSync("./test/static/client_public.pem"); + + function signatureOf(xml: string): Node { + const signature = xpath.select1( + "//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']", + new xmldom.DOMParser().parseFromString(xml), + ); + isDomNode.assertIsNodeLike(signature); + return signature; + } + + function malform(pattern: RegExp, replacement: string): string { + expect(validXml).to.match(pattern); + return validXml.replace(pattern, replacement); + } + + const cases: Array<[string, () => string, string | RegExp]> = [ + [ + "no Reference", + () => malform(//, ""), + "could not find any Reference elements", + ], + [ + "no CanonicalizationMethod", + () => malform(/]*\/>/, ""), + "could not find CanonicalizationMethod/@Algorithm element", + ], + [ + "a Reference without DigestMethod", + () => malform(/]*\/>/, ""), + /^could not find DigestMethod in reference /, + ], + [ + "a DigestMethod without Algorithm", + () => malform(/]*\/>/, ""), + /^could not find Algorithm attribute in node /, + ], + [ + "a Reference without DigestValue", + () => malform(/[^<]*<\/DigestValue>/, ""), + /^could not find DigestValue node in reference /, + ], + [ + "a Reference with two DigestValues", + () => malform(/[^<]*<\/DigestValue>/, "$&$&"), + /^could not load reference for a node that contains multiple DigestValue nodes: /, + ], + [ + "an empty DigestValue", + () => malform(/[^<]*<"), + /^could not find the value of DigestValue in /, + ], + ]; + + for (const [problem, xml, error] of cases) { + it(`with ${problem}`, function () { + const sig = new SignedXml({ publicCert }); + + expect(() => sig.loadSignature(signatureOf(xml()))).to.throw(error); + }); + } + + it("with no Reference, even when the caller carries on after loadSignature throws", function () { + const xml = malform(//, ""); + const sig = new SignedXml({ publicCert }); + expect(() => sig.loadSignature(signatureOf(xml))).to.throw(); + + expect(() => sig.checkSignature(xml)).to.throw("could not find any Reference elements"); + }); + }); + + it("throws when checking a signature that was never loaded", function () { + const sig = new SignedXml({ + publicCert: fs.readFileSync("./test/static/client_public.pem"), + }); + + expect(() => + sig.checkSignature(fs.readFileSync("./test/static/valid_signature.xml", "utf8")), + ).to.throw("No signature found."); + }); }); it("allow empty reference uri when signing", function () { @@ -1100,26 +1183,26 @@ describe("Signature unit tests", function () { it("signer appends signature to a non-existing reference node", function () { const xml = "xml-cryptogithub"; - const sig = new SignedXml(); + const sig = new SignedXml({ + privateKey: fs.readFileSync("./test/static/client.pem"), + canonicalizationAlgorithm: "http://www.w3.org/2001/10/xml-exc-c14n#", + signatureAlgorithm: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", + }); - sig.privateKey = fs.readFileSync("./test/static/client.pem"); sig.addReference({ xpath: "//*[local-name(.)='repository']", digestAlgorithm: "http://www.w3.org/2000/09/xmldsig#sha1", transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"], }); - try { + expect(() => sig.computeSignature(xml, { location: { reference: "/root/foobar", action: "append", }, - }); - expect.fail("Expected an error to be thrown"); - } catch (err) { - expect(err).not.to.be.an.instanceof(TypeError); - } + }), + ).to.throw("the following xpath cannot be used because it was not found: /root/foobar"); }); it("signer adds existing prefixes", function () { @@ -1460,6 +1543,48 @@ describe("Signature unit tests", function () { ); }); + it("should throw if a reference has no digestAlgorithm", () => { + const sig = new SignedXml(); + + expect(() => + sig.addReference({ + xpath: "//*[local-name(.)='x']", + transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"], + }), + ).to.throw("digestAlgorithm is required"); + }); + + for (const transforms of [undefined, []]) { + it(`should throw if a reference has ${transforms ? "empty" : "no"} transforms`, () => { + const sig = new SignedXml(); + + expect(() => + sig.addReference({ + xpath: "//*[local-name(.)='x']", + transforms, + digestAlgorithm: "http://www.w3.org/2001/04/xmlenc#sha256", + }), + ).to.throw("transforms must contain at least one transform algorithm"); + }); + } + + it("should throw if signing without a signatureAlgorithm", () => { + const sig = new SignedXml({ + privateKey: fs.readFileSync("./test/static/client.pem"), + canonicalizationAlgorithm: "http://www.w3.org/2001/10/xml-exc-c14n#", + }); + + sig.addReference({ + xpath: "//*[local-name(.)='x']", + digestAlgorithm: "http://www.w3.org/2001/04/xmlenc#sha256", + transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"], + }); + + expect(() => sig.computeSignature("")).to.throw( + "signatureAlgorithm is required", + ); + }); + it("should sign references when the Id attribute is prefixed", () => { const xml = ''; const sig = new SignedXml({ From 6696f416574b55b5f153233c6553a9c24ab4aea5 Mon Sep 17 00:00:00 2001 From: Chris Barth Date: Mon, 14 Sep 2026 20:34:21 -0500 Subject: [PATCH 2/4] docs: limit the implicit Canonical XML 1.0 note to node-set output A custom transform that returns octets is not canonicalized afterwards, so an implicit Canonical XML 1.0 can matter there; keep it in the list to try. Co-Authored-By: Claude Opus 5 --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8560bfa..26a33a8 100644 --- a/README.md +++ b/README.md @@ -301,12 +301,14 @@ sig.loadSignature(signature); const res = sig.checkSignature(xml); ``` -Implicit transforms run after the transforms a `` declares. Where the transforms would -otherwise end without a canonicalization, xml-crypto applies Canonical XML 1.0, so an implicit -`http://www.w3.org/TR/2001/REC-xml-c14n-20010315` changes nothing there. +Implicit transforms run after the transforms a `` declares. xml-crypto converts a +node-set left after the last transform to octets with Canonical XML 1.0, so an implicit +`http://www.w3.org/TR/2001/REC-xml-c14n-20010315` changes nothing where the transforms end in a +node-set, such as when there are none or the last one is enveloped-signature. You might find it difficult to guess such transforms, but there are typical transforms you can try. +- - - - From 9bb6fc90268fee688c1d3943f286be2eb83c6bd9 Mon Sep 17 00:00:00 2001 From: Chris Barth Date: Mon, 14 Sep 2026 21:06:20 -0500 Subject: [PATCH 3/4] test: keep only the tests backed by the XMLDSig schema or a security guarantee Drop the tests that pinned documented or incidental behavior: idAttribute signing and resolution, implicitTransforms, the location.reference message, addReference's transforms guard (ReferenceType has Transforms minOccurs=0 and #542 removes it for 7.0), an empty DigestValue (base64Binary allows it), and the two checkSignature guards whose removal still fails closed. The location.reference test returns to its master form. Co-Authored-By: Claude Opus 5 --- test/signature-integration-tests.spec.ts | 127 +++++------------------ test/signature-unit-tests.spec.ts | 53 ++-------- 2 files changed, 35 insertions(+), 145 deletions(-) diff --git a/test/signature-integration-tests.spec.ts b/test/signature-integration-tests.spec.ts index bb2040d..a848f10 100644 --- a/test/signature-integration-tests.spec.ts +++ b/test/signature-integration-tests.spec.ts @@ -1,7 +1,6 @@ import * as xpath from "xpath"; import * as xmldom from "@xmldom/xmldom"; -import { SignedXml, SignedXmlOptions, findAncestorNs } from "../src/index"; -import * as crypto from "crypto"; +import { SignedXml, SignedXmlOptions } from "../src/index"; import * as fs from "fs"; import { expect } from "chai"; import * as isDomNode from "@xmldom/is-dom-node"; @@ -1156,107 +1155,35 @@ describe("Signature integration tests", function () { }); }); - describe("options", function () { + it("rejects a document where a default id attribute repeats the id held in idAttribute", function () { const exclusiveC14n = "http://www.w3.org/2001/10/xml-exc-c14n#"; - const privateKey = fs.readFileSync("./test/static/client.pem"); - const publicCert = fs.readFileSync("./test/static/client_public.pem"); - - function sign(xml: string, options: SignedXmlOptions, transforms: string[]): string { - const sig = new SignedXml({ - ...options, - privateKey, - canonicalizationAlgorithm: exclusiveC14n, - signatureAlgorithm: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", - }); - sig.addReference({ - xpath: "//*[local-name(.)='book']", - transforms, - digestAlgorithm: "http://www.w3.org/2001/04/xmlenc#sha256", - }); - sig.computeSignature(xml); - return sig.getSignedXml(); - } - - function verifier(xml: string, options: SignedXmlOptions): SignedXml { - const signature = xpath.select1( - "//*[local-name(.)='Signature']", - new xmldom.DOMParser().parseFromString(xml), - ); - isDomNode.assertIsNodeLike(signature); - const sig = new SignedXml({ ...options, publicCert }); - sig.loadSignature(signature); - return sig; - } - - describe("idAttribute", function () { - const idAttribute = "AssertionID"; - const signBook = () => - sign( - 'Harry Potter', - { idAttribute }, - [exclusiveC14n], - ); - - it("signs an element by the id it already carries in that attribute", function () { - const signed = signBook(); - - expect(signed).to.include(''); - expect(signed).to.include(''); - }); - - it("resolves a reference through that attribute when verifying", function () { - const signed = signBook(); - - expect(verifier(signed, {}).checkSignature(signed)).to.be.false; - expect(verifier(signed, { idAttribute }).checkSignature(signed)).to.be.true; - }); - - it("rejects a document where a default id attribute repeats that id", function () { - const signed = signBook().replace( - "", - 'Forged', - ); - - expect(() => verifier(signed, { idAttribute }).checkSignature(signed)).to.throw( - /in order to prevent signature wrapping attack/, - ); - }); + const idAttribute = "AssertionID"; + const signer = new SignedXml({ + idAttribute, + privateKey: fs.readFileSync("./test/static/client.pem"), + canonicalizationAlgorithm: exclusiveC14n, + signatureAlgorithm: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", }); + signer.addReference({ + xpath: "//*[local-name(.)='book']", + transforms: [exclusiveC14n], + digestAlgorithm: "http://www.w3.org/2001/04/xmlenc#sha256", + }); + signer.computeSignature( + 'Harry Potter', + ); + const signed = signer + .getSignedXml() + .replace("", 'Forged'); - describe("implicitTransforms", function () { - it("applies a transform the signer used but did not declare", function () { - const declared = sign( - 'Harry Potter', - {}, - ["http://www.w3.org/2000/09/xmldsig#enveloped-signature", exclusiveC14n], - ); - // A signer that applied exclusive C14N without declaring it: drop the Transform, then sign - // SignedInfo again. - const undeclared = declared.replace(``, ""); - expect(undeclared).to.not.equal(declared); - - const doc = new xmldom.DOMParser().parseFromString(undeclared); - const signedInfo = xpath.select1("//*[local-name(.)='SignedInfo']", doc); - isDomNode.assertIsNodeLike(signedInfo); - const canonSignedInfo = new SignedXml().getCanonXml([exclusiveC14n], signedInfo, { - ancestorNamespaces: findAncestorNs(doc, "//*[local-name(.)='SignedInfo']"), - }); - const signatureValue = crypto - .createSign("RSA-SHA256") - .update(canonSignedInfo) - .sign(privateKey, "base64"); - const signed = undeclared.replace( - /[^<]*/, - `${signatureValue}`, - ); - - expect(verifier(signed, {}).checkSignature(signed)).to.be.false; - const sig = verifier(signed, { implicitTransforms: [exclusiveC14n] }); - expect(sig.checkSignature(signed)).to.be.true; - expect(sig.getSignedReferences()).to.deep.equal([ - 'Harry Potter', - ]); - }); + const verifier = new SignedXml({ + idAttribute, + publicCert: fs.readFileSync("./test/static/client_public.pem"), }); + verifier.loadSignature(signer.getSignatureXml()); + + expect(() => verifier.checkSignature(signed)).to.throw( + /in order to prevent signature wrapping attack/, + ); }); }); diff --git a/test/signature-unit-tests.spec.ts b/test/signature-unit-tests.spec.ts index 64852fd..f411bfe 100644 --- a/test/signature-unit-tests.spec.ts +++ b/test/signature-unit-tests.spec.ts @@ -1121,11 +1121,6 @@ describe("Signature unit tests", function () { () => malform(/[^<]*<\/DigestValue>/, "$&$&"), /^could not load reference for a node that contains multiple DigestValue nodes: /, ], - [ - "an empty DigestValue", - () => malform(/[^<]*<"), - /^could not find the value of DigestValue in /, - ], ]; for (const [problem, xml, error] of cases) { @@ -1135,24 +1130,6 @@ describe("Signature unit tests", function () { expect(() => sig.loadSignature(signatureOf(xml()))).to.throw(error); }); } - - it("with no Reference, even when the caller carries on after loadSignature throws", function () { - const xml = malform(//, ""); - const sig = new SignedXml({ publicCert }); - expect(() => sig.loadSignature(signatureOf(xml))).to.throw(); - - expect(() => sig.checkSignature(xml)).to.throw("could not find any Reference elements"); - }); - }); - - it("throws when checking a signature that was never loaded", function () { - const sig = new SignedXml({ - publicCert: fs.readFileSync("./test/static/client_public.pem"), - }); - - expect(() => - sig.checkSignature(fs.readFileSync("./test/static/valid_signature.xml", "utf8")), - ).to.throw("No signature found."); }); }); @@ -1183,26 +1160,26 @@ describe("Signature unit tests", function () { it("signer appends signature to a non-existing reference node", function () { const xml = "xml-cryptogithub"; - const sig = new SignedXml({ - privateKey: fs.readFileSync("./test/static/client.pem"), - canonicalizationAlgorithm: "http://www.w3.org/2001/10/xml-exc-c14n#", - signatureAlgorithm: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", - }); + const sig = new SignedXml(); + sig.privateKey = fs.readFileSync("./test/static/client.pem"); sig.addReference({ xpath: "//*[local-name(.)='repository']", digestAlgorithm: "http://www.w3.org/2000/09/xmldsig#sha1", transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"], }); - expect(() => + try { sig.computeSignature(xml, { location: { reference: "/root/foobar", action: "append", }, - }), - ).to.throw("the following xpath cannot be used because it was not found: /root/foobar"); + }); + expect.fail("Expected an error to be thrown"); + } catch (err) { + expect(err).not.to.be.an.instanceof(TypeError); + } }); it("signer adds existing prefixes", function () { @@ -1554,20 +1531,6 @@ describe("Signature unit tests", function () { ).to.throw("digestAlgorithm is required"); }); - for (const transforms of [undefined, []]) { - it(`should throw if a reference has ${transforms ? "empty" : "no"} transforms`, () => { - const sig = new SignedXml(); - - expect(() => - sig.addReference({ - xpath: "//*[local-name(.)='x']", - transforms, - digestAlgorithm: "http://www.w3.org/2001/04/xmlenc#sha256", - }), - ).to.throw("transforms must contain at least one transform algorithm"); - }); - } - it("should throw if signing without a signatureAlgorithm", () => { const sig = new SignedXml({ privateKey: fs.readFileSync("./test/static/client.pem"), From a0c5d33aa5b92785585252504d0872fcc313333c Mon Sep 17 00:00:00 2001 From: Chris Barth Date: Mon, 14 Sep 2026 21:25:52 -0500 Subject: [PATCH 4/4] test: remove the location.reference test that never reached the lookup It threw 'Missing canonicalizationAlgorithm' before computeSignature looked up location.reference, and asserted only that the error was not a TypeError. #583 decides what an invalid location.reference reports in 7.0. Co-Authored-By: Claude Opus 5 --- test/signature-unit-tests.spec.ts | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/test/signature-unit-tests.spec.ts b/test/signature-unit-tests.spec.ts index f411bfe..4d16b44 100644 --- a/test/signature-unit-tests.spec.ts +++ b/test/signature-unit-tests.spec.ts @@ -1158,30 +1158,6 @@ describe("Signature unit tests", function () { expect(URI.value, `uri should be empty but instead was ${URI.value}`).to.equal(""); }); - it("signer appends signature to a non-existing reference node", function () { - const xml = "xml-cryptogithub"; - const sig = new SignedXml(); - - sig.privateKey = fs.readFileSync("./test/static/client.pem"); - sig.addReference({ - xpath: "//*[local-name(.)='repository']", - digestAlgorithm: "http://www.w3.org/2000/09/xmldsig#sha1", - transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"], - }); - - try { - sig.computeSignature(xml, { - location: { - reference: "/root/foobar", - action: "append", - }, - }); - expect.fail("Expected an error to be thrown"); - } catch (err) { - expect(err).not.to.be.an.instanceof(TypeError); - } - }); - it("signer adds existing prefixes", function () { function getKeyInfoContentWithAssertionId({ assertionId }) { return (