From 50e8e9c33689cfc9f24a8ceaeb57a5e6427b62fb Mon Sep 17 00:00:00 2001 From: Chris Barth Date: Wed, 8 Nov 2023 19:29:44 -0600 Subject: [PATCH] Remove default for transformation algorithm --- README.md | 46 ++++++++++++++++-------- src/signed-xml.ts | 8 +++-- test/hmac-tests.spec.ts | 1 + test/key-info-tests.spec.ts | 1 + test/signature-integration-tests.spec.ts | 7 +++- test/signature-unit-tests.spec.ts | 18 ++++++++++ 6 files changed, 64 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 2f285552..6dec5e7d 100644 --- a/README.md +++ b/README.md @@ -49,14 +49,6 @@ This will enable HMAC and disable digital signature algorithms. Due to key confusion issues, it is risky to have both HMAC-based and public key digital signature algorithms enabled at same time. -By default the following algorithms are used: - -_Canonicalization/Transformation Algorithm:_ Exclusive Canonicalization - -_Hashing/Digest Algorithm:_ Must be specified by the user - -_Signature Algorithm:_ Must be specified by the user - [You are able to extend xml-crypto with custom algorithms.](#customizing-algorithms) ## Signing Xml documents @@ -77,7 +69,13 @@ var SignedXml = require("xml-crypto").SignedXml, var xml = "" + "" + "Harry Potter" + "" + ""; var sig = new SignedXml({ privateKey: fs.readFileSync("client.pem") }); -sig.addReference({ xpath: "//*[local-name(.)='book']" }); +sig.addReference({ + xpath: "//*[local-name(.)='book']", + 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(xml); fs.writeFileSync("signed.xml", sig.getSignedXml()); ``` @@ -243,7 +241,7 @@ The `SignedXml` constructor provides an abstraction for sign and verify xml docu - `idAttribute` - string - default `Id` or `ID` or `id` - the name of the attribute that contains the id of the element - `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 - default `http://www.w3.org/2000/09/xmldsig#rsa-sha1` - the signature algorithm to use +- `signatureAlgorithm` - string - the signature algorithm to use - `canonicalizationAlgorithm` - string - default `undefined` - the canonicalization algorithm to use - `inclusiveNamespacesPrefixList` - string - default `null` - a list of namespace prefixes to include during canonicalization - `implicitTransforms` - string[] - default `[]` - a list of implicit transforms to use during verification @@ -257,7 +255,7 @@ A `SignedXml` object provides the following methods: To sign xml documents: -- `addReference(xpath, [transforms], [digestAlgorithm])` - adds a reference to a xml element where: +- `addReference(xpath, transforms, digestAlgorithm)` - adds a reference to a xml element where: - `xpath` - a string containing a XPath expression referencing a xml element - `transforms` - an array of [transform algorithms](#canonicalization-and-transformation-algorithms), the referenced element will be transformed for each value in the array - `digestAlgorithm` - one of the supported [hashing algorithms](#hashing-algorithms) @@ -391,7 +389,13 @@ function signXml(xml, xpath, key, dest) { digestAlgorithm: "http://myDigestAlgorithm", }); - sig.addReference({ xpath }); + sig.addReference({ + xpath, + transforms: ["http://MyTransformation"], + digestAlgorithm: "http://myDigestAlgorithm", + }); + sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#"; + sig.signatureAlgorithm = "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; sig.computeSignature(xml); fs.writeFileSync(dest, sig.getSignedXml()); } @@ -424,6 +428,8 @@ function AsyncSignatureAlgorithm() { var sig = new SignedXml({ signatureAlgorithm: "http://asyncSignatureAlgorithm" }); sig.SignatureAlgorithms["http://asyncSignatureAlgorithm"] = AsyncSignatureAlgorithm; +sig.signatureAlgorithm = "http://asyncSignatureAlgorithm"; +sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#"; sig.computeSignature(xml, opts, function (err) { var signedResponse = sig.getSignedXml(); }); @@ -474,7 +480,13 @@ var SignedXml = require("xml-crypto").SignedXml, var xml = "" + "" + "Harry Potter" + "" + ""; var sig = new SignedXml({ privateKey: fs.readFileSync("client.pem") }); -sig.addReference({ xpath: "//*[local-name(.)='book']" }); +sig.addReference({ + xpath: "//*[local-name(.)='book']", + 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(xml, { prefix: "ds", }); @@ -497,7 +509,13 @@ var SignedXml = require("xml-crypto").SignedXml, var xml = "" + "" + "Harry Potter" + "" + ""; var sig = new SignedXml({ privateKey: fs.readFileSync("client.pem") }); -sig.addReference({ xpath: "//*[local-name(.)='book']" }); +sig.addReference({ + xpath: "//*[local-name(.)='book']", + 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(xml, { location: { reference: "//*[local-name(.)='book']", action: "after" }, //This will place the signature after the book element }); diff --git a/src/signed-xml.ts b/src/signed-xml.ts index 5a4af693..4c7ad70f 100644 --- a/src/signed-xml.ts +++ b/src/signed-xml.ts @@ -639,7 +639,7 @@ export class SignedXml { * Adds a reference to the signature. * * @param xpath The XPath expression to select the XML nodes to be referenced. - * @param transforms An array of transform algorithms to be applied to the selected nodes. Defaults to ["http://www.w3.org/2001/10/xml-exc-c14n#"]. + * @param transforms An array of transform algorithms to be applied to the selected nodes. * @param digestAlgorithm The digest algorithm to use for computing the digest value. * @param uri The URI identifier for the reference. If empty, an empty URI will be used. * @param digestValue The expected digest value for the reference. @@ -648,7 +648,7 @@ export class SignedXml { */ addReference({ xpath, - transforms = ["http://www.w3.org/2001/10/xml-exc-c14n#"], + transforms, digestAlgorithm, uri = "", digestValue, @@ -659,6 +659,10 @@ export class SignedXml { throw new Error("digestAlgorithm is required"); } + if (!utils.isArrayHasLength(transforms)) { + throw new Error("transforms must contain at least one transform algorithm"); + } + this.references.push({ xpath, transforms, diff --git a/test/hmac-tests.spec.ts b/test/hmac-tests.spec.ts index 299a92fb..6ef31db0 100644 --- a/test/hmac-tests.spec.ts +++ b/test/hmac-tests.spec.ts @@ -50,6 +50,7 @@ describe("HMAC tests", function () { sig.addReference({ xpath: "//*[local-name(.)='book']", 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.computeSignature(xml); diff --git a/test/key-info-tests.spec.ts b/test/key-info-tests.spec.ts index 3daf78c8..19c8f4a7 100644 --- a/test/key-info-tests.spec.ts +++ b/test/key-info-tests.spec.ts @@ -32,6 +32,7 @@ describe("KeyInfo tests", function () { sig.addReference({ xpath: "//*[local-name(.)='book']", 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.computeSignature(xml); diff --git a/test/signature-integration-tests.spec.ts b/test/signature-integration-tests.spec.ts index c2d04593..befcab1f 100644 --- a/test/signature-integration-tests.spec.ts +++ b/test/signature-integration-tests.spec.ts @@ -11,7 +11,11 @@ describe("Signature integration tests", function () { sig.privateKey = fs.readFileSync("./test/static/client.pem"); xpath.map(function (n) { - sig.addReference({ xpath: n, digestAlgorithm: "http://www.w3.org/2000/09/xmldsig#sha1" }); + sig.addReference({ + xpath: n, + digestAlgorithm: "http://www.w3.org/2000/09/xmldsig#sha1", + transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"], + }); }); sig.canonicalizationAlgorithm = canonicalizationAlgorithm; @@ -175,6 +179,7 @@ describe("Signature integration tests", function () { sig.addReference({ xpath: "//*[local-name(.)='book']", digestAlgorithm: "http://www.w3.org/2000/09/xmldsig#sha1", + transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"], }); sig.privateKey = fs.readFileSync("./test/static/client.pem"); sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#"; diff --git a/test/signature-unit-tests.spec.ts b/test/signature-unit-tests.spec.ts index 16cc5d70..0db89a49 100644 --- a/test/signature-unit-tests.spec.ts +++ b/test/signature-unit-tests.spec.ts @@ -25,14 +25,17 @@ describe("Signature unit tests", function () { sig.addReference({ xpath: "//*[local-name(.)='x']", digestAlgorithm: "http://www.w3.org/2000/09/xmldsig#sha1", + transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"], }); sig.addReference({ xpath: "//*[local-name(.)='y']", digestAlgorithm: "http://www.w3.org/2000/09/xmldsig#sha1", + transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"], }); sig.addReference({ xpath: "//*[local-name(.)='w']", 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#"; @@ -70,6 +73,7 @@ describe("Signature unit tests", function () { sig.addReference({ xpath: "//*[@wsu:Id]", 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#"; @@ -95,6 +99,7 @@ describe("Signature unit tests", function () { sig.addReference({ xpath: "//*[local-name(.)='x']", 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"; @@ -129,6 +134,7 @@ describe("Signature unit tests", function () { sig.addReference({ xpath: "//*[local-name(.)='name']", 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#"; @@ -165,6 +171,7 @@ describe("Signature unit tests", function () { sig.addReference({ xpath: "//*[local-name(.)='name']", 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"; @@ -188,6 +195,7 @@ describe("Signature unit tests", function () { 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#"], }); sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#"; @@ -219,6 +227,7 @@ describe("Signature unit tests", function () { 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#"], }); sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#"; @@ -249,6 +258,7 @@ describe("Signature unit tests", function () { 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#"], }); sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#"; @@ -280,6 +290,7 @@ describe("Signature unit tests", function () { 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#"], }); sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#"; @@ -635,14 +646,17 @@ describe("Signature unit tests", function () { sig.addReference({ xpath: "//*[local-name(.)='x']", digestAlgorithm: "http://www.w3.org/2000/09/xmldsig#sha1", + transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"], }); sig.addReference({ xpath: "//*[local-name(.)='y']", digestAlgorithm: "http://www.w3.org/2000/09/xmldsig#sha1", + transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"], }); sig.addReference({ xpath: "//*[local-name(.)='w']", 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#"; @@ -713,14 +727,17 @@ describe("Signature unit tests", function () { sig.addReference({ xpath: "//*[local-name(.)='x']", digestAlgorithm: "http://www.w3.org/2000/09/xmldsig#sha1", + transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"], }); sig.addReference({ xpath: "//*[local-name(.)='y']", digestAlgorithm: "http://www.w3.org/2000/09/xmldsig#sha1", + transforms: ["http://www.w3.org/2001/10/xml-exc-c14n#"], }); sig.addReference({ xpath: "//*[local-name(.)='w']", 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#"; @@ -983,6 +1000,7 @@ describe("Signature unit tests", function () { 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 {