Skip to content

Commit 5629be4

Browse files
authored
Remove default canonicalization algorithm (#405)
1 parent e044d7a commit 5629be4

10 files changed

+313
-256
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ by default the following algorithms are used:
5353

5454
_Canonicalization/Transformation Algorithm:_ Exclusive Canonicalization <http://www.w3.org/2001/10/xml-exc-c14n#>
5555

56-
_Hashing Algorithm:_ SHA1 digest <http://www.w3.org/2000/09/xmldsig#sha1>
56+
_Hashing/Digest Algorithm:_ SHA1 digest <http://www.w3.org/2000/09/xmldsig#sha1>
5757

5858
_Signature Algorithm:_ RSA-SHA1 <http://www.w3.org/2000/09/xmldsig#rsa-sha1>
5959

@@ -244,7 +244,7 @@ The `SignedXml` constructor provides an abstraction for sign and verify xml docu
244244
- `privateKey` - string or Buffer - default `null` - the private key to use for signing
245245
- `publicCert` - string or Buffer - default `null` - the public certificate to use for verifying
246246
- `signatureAlgorithm` - string - default `http://www.w3.org/2000/09/xmldsig#rsa-sha1` - the signature algorithm to use
247-
- `canonicalizationAlgorithm` - string - default `http://www.w3.org/TR/2001/REC-xml-c14n-20010315` - the canonicalization algorithm to use
247+
- `canonicalizationAlgorithm` - string - default `undefined` - the canonicalization algorithm to use
248248
- `inclusiveNamespacesPrefixList` - string - default `null` - a list of namespace prefixes to include during canonicalization
249249
- `implicitTransforms` - string[] - default `[]` - a list of implicit transforms to use during verification
250250
- `keyInfoAttributes` - object - default `{}` - a hash of attributes and values `attrName: value` to add to the KeyInfo node
@@ -313,7 +313,7 @@ function MyDigest() {
313313
}
314314
```
315315

316-
A custom signing algorithm. The default is RSA-SHA1.
316+
A custom signing algorithm.
317317

318318
```javascript
319319
function MySignatureAlgorithm() {
@@ -328,7 +328,7 @@ function MySignatureAlgorithm() {
328328
}
329329
```
330330

331-
Custom transformation algorithm. The default is exclusive canonicalization.
331+
Custom transformation algorithm.
332332

333333
```javascript
334334
function MyTransformation() {

src/c14n-canonicalization.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ import * as utils from "./utils";
88
import * as isDomNode from "@xmldom/is-dom-node";
99

1010
export class C14nCanonicalization implements CanonicalizationOrTransformationAlgorithm {
11-
includeComments = false;
11+
protected includeComments = false;
12+
13+
constructor() {
14+
this.includeComments = false;
15+
}
1216

1317
attrCompare(a, b) {
1418
if (!a.namespaceURI && b.namespaceURI) {

src/enveloped-signature.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ import type {
88
} from "./types";
99

1010
export class EnvelopedSignature implements CanonicalizationOrTransformationAlgorithm {
11-
includeComments = false;
11+
protected includeComments = false;
12+
13+
constructor() {
14+
this.includeComments = false;
15+
}
16+
1217
process(node: Node, options: CanonicalizationOrTransformationAlgorithmProcessOptions): Node {
1318
if (null == options.signatureNode) {
1419
const signature = xpath.select1(

src/exclusive-canonicalization.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ function isPrefixInScope(prefixesInScope, prefix, namespaceURI) {
1818
}
1919

2020
export class ExclusiveCanonicalization implements CanonicalizationOrTransformationAlgorithm {
21-
includeComments = false;
21+
protected includeComments = false;
22+
23+
constructor() {
24+
this.includeComments = false;
25+
}
2226

2327
attrCompare(a, b) {
2428
if (!a.namespaceURI && b.namespaceURI) {

src/signed-xml.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ export class SignedXml {
4141
/**
4242
* Rules used to convert an XML document into its canonical form.
4343
*/
44-
canonicalizationAlgorithm: CanonicalizationAlgorithmType =
45-
"http://www.w3.org/2001/10/xml-exc-c14n#";
44+
canonicalizationAlgorithm?: CanonicalizationAlgorithmType = undefined;
4645
/**
4746
* It specifies a list of namespace prefixes that should be considered "inclusive" during the canonicalization process.
4847
*/
@@ -140,7 +139,7 @@ export class SignedXml {
140139
this.privateKey = privateKey;
141140
this.publicCert = publicCert;
142141
this.signatureAlgorithm = signatureAlgorithm ?? this.signatureAlgorithm;
143-
this.canonicalizationAlgorithm = canonicalizationAlgorithm ?? this.canonicalizationAlgorithm;
142+
this.canonicalizationAlgorithm = canonicalizationAlgorithm;
144143
if (typeof inclusiveNamespacesPrefixList === "string") {
145144
this.inclusiveNamespacesPrefixList = inclusiveNamespacesPrefixList.split(" ");
146145
} else if (utils.isArrayHasLength(inclusiveNamespacesPrefixList)) {
@@ -286,6 +285,9 @@ export class SignedXml {
286285
if (this.signatureNode == null) {
287286
throw new Error("No signature found.");
288287
}
288+
if (typeof this.canonicalizationAlgorithm !== "string") {
289+
throw new Error("Missing canonicalizationAlgorithm when trying to get signed info for XML");
290+
}
289291

290292
const signedInfo = utils.findChildren(this.signatureNode, "SignedInfo");
291293
if (signedInfo.length === 0) {
@@ -312,6 +314,7 @@ export class SignedXml {
312314
const c14nOptions = {
313315
ancestorNamespaces: ancestorNamespaces,
314316
};
317+
315318
return this.getCanonXml([this.canonicalizationAlgorithm], signedInfo[0], c14nOptions);
316319
}
317320

@@ -354,12 +357,14 @@ export class SignedXml {
354357
}
355358

356359
private findCanonicalizationAlgorithm(name: CanonicalizationOrTransformAlgorithmType) {
357-
const algo = this.CanonicalizationAlgorithms[name];
358-
if (algo) {
359-
return new algo();
360-
} else {
361-
throw new Error(`canonicalization algorithm '${name}' is not supported`);
360+
if (name != null) {
361+
const algo = this.CanonicalizationAlgorithms[name];
362+
if (algo) {
363+
return new algo();
364+
}
362365
}
366+
367+
throw new Error(`canonicalization algorithm '${name}' is not supported`);
363368
}
364369

365370
private findHashAlgorithm(name: HashAlgorithmType) {
@@ -1024,6 +1029,11 @@ export class SignedXml {
10241029
*
10251030
*/
10261031
private createSignedInfo(doc, prefix) {
1032+
if (typeof this.canonicalizationAlgorithm !== "string") {
1033+
throw new Error(
1034+
"Missing canonicalizationAlgorithm when trying to create signed info for XML",
1035+
);
1036+
}
10271037
const transform = this.findCanonicalizationAlgorithm(this.canonicalizationAlgorithm);
10281038
const algo = this.findSignatureAlgorithm(this.signatureAlgorithm);
10291039
let currentPrefix;

src/types.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,6 @@ export interface CanonicalizationOrTransformationAlgorithm {
143143
): Node | string;
144144

145145
getAlgorithmName(): CanonicalizationOrTransformAlgorithmType;
146-
147-
includeComments: boolean;
148146
}
149147

150148
/** Implement this to create a new HashAlgorithm */

test/hmac-tests.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ describe("HMAC tests", function () {
4848
sig.privateKey = fs.readFileSync("./test/static/hmac.key");
4949
sig.signatureAlgorithm = "http://www.w3.org/2000/09/xmldsig#hmac-sha1";
5050
sig.addReference({ xpath: "//*[local-name(.)='book']" });
51+
sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
5152
sig.computeSignature(xml);
5253

5354
const doc = new xmldom.DOMParser().parseFromString(sig.getSignedXml());

test/key-info-tests.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ describe("KeyInfo tests", function () {
1111
const sig = new SignedXml();
1212
sig.privateKey = fs.readFileSync("./test/static/client.pem");
1313
sig.publicCert = fs.readFileSync("./test/static/client_public.pem");
14+
sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
1415
sig.computeSignature(xml);
1516
const signedXml = sig.getSignedXml();
1617
const doc = new xmldom.DOMParser().parseFromString(signedXml);
@@ -28,6 +29,7 @@ describe("KeyInfo tests", function () {
2829
sig.signatureAlgorithm = "http://www.w3.org/2000/09/xmldsig#hmac-sha1";
2930
sig.enableHMAC();
3031
sig.addReference({ xpath: "//*[local-name(.)='book']" });
32+
sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
3133
sig.computeSignature(xml);
3234

3335
const doc = new xmldom.DOMParser().parseFromString(sig.getSignedXml());

test/signature-integration-tests.spec.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ import { expect } from "chai";
66
import * as isDomNode from "@xmldom/is-dom-node";
77

88
describe("Signature integration tests", function () {
9-
function verifySignature(xml, expected, xpath) {
9+
function verifySignature(xml, expected, xpath, canonicalizationAlgorithm) {
1010
const sig = new SignedXml();
1111
sig.privateKey = fs.readFileSync("./test/static/client.pem");
1212

1313
xpath.map(function (n) {
1414
sig.addReference({ xpath: n });
1515
});
1616

17+
sig.canonicalizationAlgorithm = canonicalizationAlgorithm;
1718
sig.computeSignature(xml);
1819
const signed = sig.getSignedXml();
1920

@@ -24,11 +25,12 @@ describe("Signature integration tests", function () {
2425
it("verify signature", function () {
2526
const xml =
2627
'<root><x xmlns="ns"></x><y z_attr="value" a_attr1="foo"></y><z><ns:w ns:attr="value" xmlns:ns="myns"></ns:w></z></root>';
27-
verifySignature(xml, "./test/static/integration/expectedVerify.xml", [
28-
"//*[local-name(.)='x']",
29-
"//*[local-name(.)='y']",
30-
"//*[local-name(.)='w']",
31-
]);
28+
verifySignature(
29+
xml,
30+
"./test/static/integration/expectedVerify.xml",
31+
["//*[local-name(.)='x']", "//*[local-name(.)='y']", "//*[local-name(.)='w']"],
32+
"http://www.w3.org/2001/10/xml-exc-c14n#",
33+
);
3234
});
3335

3436
it("verify signature of complex element", function () {
@@ -43,9 +45,12 @@ describe("Signature integration tests", function () {
4345
"</book>" +
4446
"</library>";
4547

46-
verifySignature(xml, "./test/static/integration/expectedVerifyComplex.xml", [
47-
"//*[local-name(.)='book']",
48-
]);
48+
verifySignature(
49+
xml,
50+
"./test/static/integration/expectedVerifyComplex.xml",
51+
["//*[local-name(.)='book']"],
52+
"http://www.w3.org/2001/10/xml-exc-c14n#",
53+
);
4954
});
5055

5156
it("empty URI reference should consider the whole document", function () {
@@ -168,6 +173,7 @@ describe("Signature integration tests", function () {
168173
const sig = new SignedXml();
169174
sig.addReference({ xpath: "//*[local-name(.)='book']" });
170175
sig.privateKey = fs.readFileSync("./test/static/client.pem");
176+
sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
171177
sig.computeSignature(xml);
172178

173179
const signed = sig.getSignedXml();

0 commit comments

Comments
 (0)