Skip to content

Commit

Permalink
Remove default canonicalization algorithm (#405)
Browse files Browse the repository at this point in the history
  • Loading branch information
cjbarth authored Oct 18, 2023
1 parent e044d7a commit 5629be4
Show file tree
Hide file tree
Showing 10 changed files with 313 additions and 256 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ by default the following algorithms are used:

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

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

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

Expand Down Expand Up @@ -244,7 +244,7 @@ The `SignedXml` constructor provides an abstraction for sign and verify xml docu
- `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
- `canonicalizationAlgorithm` - string - default `http://www.w3.org/TR/2001/REC-xml-c14n-20010315` - the canonicalization 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
- `keyInfoAttributes` - object - default `{}` - a hash of attributes and values `attrName: value` to add to the KeyInfo node
Expand Down Expand Up @@ -313,7 +313,7 @@ function MyDigest() {
}
```

A custom signing algorithm. The default is RSA-SHA1.
A custom signing algorithm.

```javascript
function MySignatureAlgorithm() {
Expand All @@ -328,7 +328,7 @@ function MySignatureAlgorithm() {
}
```

Custom transformation algorithm. The default is exclusive canonicalization.
Custom transformation algorithm.

```javascript
function MyTransformation() {
Expand Down
6 changes: 5 additions & 1 deletion src/c14n-canonicalization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import * as utils from "./utils";
import * as isDomNode from "@xmldom/is-dom-node";

export class C14nCanonicalization implements CanonicalizationOrTransformationAlgorithm {
includeComments = false;
protected includeComments = false;

constructor() {
this.includeComments = false;
}

attrCompare(a, b) {
if (!a.namespaceURI && b.namespaceURI) {
Expand Down
7 changes: 6 additions & 1 deletion src/enveloped-signature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ import type {
} from "./types";

export class EnvelopedSignature implements CanonicalizationOrTransformationAlgorithm {
includeComments = false;
protected includeComments = false;

constructor() {
this.includeComments = false;
}

process(node: Node, options: CanonicalizationOrTransformationAlgorithmProcessOptions): Node {
if (null == options.signatureNode) {
const signature = xpath.select1(
Expand Down
6 changes: 5 additions & 1 deletion src/exclusive-canonicalization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ function isPrefixInScope(prefixesInScope, prefix, namespaceURI) {
}

export class ExclusiveCanonicalization implements CanonicalizationOrTransformationAlgorithm {
includeComments = false;
protected includeComments = false;

constructor() {
this.includeComments = false;
}

attrCompare(a, b) {
if (!a.namespaceURI && b.namespaceURI) {
Expand Down
26 changes: 18 additions & 8 deletions src/signed-xml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ export class SignedXml {
/**
* Rules used to convert an XML document into its canonical form.
*/
canonicalizationAlgorithm: CanonicalizationAlgorithmType =
"http://www.w3.org/2001/10/xml-exc-c14n#";
canonicalizationAlgorithm?: CanonicalizationAlgorithmType = undefined;
/**
* It specifies a list of namespace prefixes that should be considered "inclusive" during the canonicalization process.
*/
Expand Down Expand Up @@ -140,7 +139,7 @@ export class SignedXml {
this.privateKey = privateKey;
this.publicCert = publicCert;
this.signatureAlgorithm = signatureAlgorithm ?? this.signatureAlgorithm;
this.canonicalizationAlgorithm = canonicalizationAlgorithm ?? this.canonicalizationAlgorithm;
this.canonicalizationAlgorithm = canonicalizationAlgorithm;
if (typeof inclusiveNamespacesPrefixList === "string") {
this.inclusiveNamespacesPrefixList = inclusiveNamespacesPrefixList.split(" ");
} else if (utils.isArrayHasLength(inclusiveNamespacesPrefixList)) {
Expand Down Expand Up @@ -286,6 +285,9 @@ export class SignedXml {
if (this.signatureNode == null) {
throw new Error("No signature found.");
}
if (typeof this.canonicalizationAlgorithm !== "string") {
throw new Error("Missing canonicalizationAlgorithm when trying to get signed info for XML");
}

const signedInfo = utils.findChildren(this.signatureNode, "SignedInfo");
if (signedInfo.length === 0) {
Expand All @@ -312,6 +314,7 @@ export class SignedXml {
const c14nOptions = {
ancestorNamespaces: ancestorNamespaces,
};

return this.getCanonXml([this.canonicalizationAlgorithm], signedInfo[0], c14nOptions);
}

Expand Down Expand Up @@ -354,12 +357,14 @@ export class SignedXml {
}

private findCanonicalizationAlgorithm(name: CanonicalizationOrTransformAlgorithmType) {
const algo = this.CanonicalizationAlgorithms[name];
if (algo) {
return new algo();
} else {
throw new Error(`canonicalization algorithm '${name}' is not supported`);
if (name != null) {
const algo = this.CanonicalizationAlgorithms[name];
if (algo) {
return new algo();
}
}

throw new Error(`canonicalization algorithm '${name}' is not supported`);
}

private findHashAlgorithm(name: HashAlgorithmType) {
Expand Down Expand Up @@ -1024,6 +1029,11 @@ export class SignedXml {
*
*/
private createSignedInfo(doc, prefix) {
if (typeof this.canonicalizationAlgorithm !== "string") {
throw new Error(
"Missing canonicalizationAlgorithm when trying to create signed info for XML",
);
}
const transform = this.findCanonicalizationAlgorithm(this.canonicalizationAlgorithm);
const algo = this.findSignatureAlgorithm(this.signatureAlgorithm);
let currentPrefix;
Expand Down
2 changes: 0 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,6 @@ export interface CanonicalizationOrTransformationAlgorithm {
): Node | string;

getAlgorithmName(): CanonicalizationOrTransformAlgorithmType;

includeComments: boolean;
}

/** Implement this to create a new HashAlgorithm */
Expand Down
1 change: 1 addition & 0 deletions test/hmac-tests.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ describe("HMAC tests", function () {
sig.privateKey = fs.readFileSync("./test/static/hmac.key");
sig.signatureAlgorithm = "http://www.w3.org/2000/09/xmldsig#hmac-sha1";
sig.addReference({ xpath: "//*[local-name(.)='book']" });
sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
sig.computeSignature(xml);

const doc = new xmldom.DOMParser().parseFromString(sig.getSignedXml());
Expand Down
2 changes: 2 additions & 0 deletions test/key-info-tests.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ describe("KeyInfo tests", function () {
const sig = new SignedXml();
sig.privateKey = fs.readFileSync("./test/static/client.pem");
sig.publicCert = fs.readFileSync("./test/static/client_public.pem");
sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
sig.computeSignature(xml);
const signedXml = sig.getSignedXml();
const doc = new xmldom.DOMParser().parseFromString(signedXml);
Expand All @@ -28,6 +29,7 @@ describe("KeyInfo tests", function () {
sig.signatureAlgorithm = "http://www.w3.org/2000/09/xmldsig#hmac-sha1";
sig.enableHMAC();
sig.addReference({ xpath: "//*[local-name(.)='book']" });
sig.canonicalizationAlgorithm = "http://www.w3.org/2001/10/xml-exc-c14n#";
sig.computeSignature(xml);

const doc = new xmldom.DOMParser().parseFromString(sig.getSignedXml());
Expand Down
24 changes: 15 additions & 9 deletions test/signature-integration-tests.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import { expect } from "chai";
import * as isDomNode from "@xmldom/is-dom-node";

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

xpath.map(function (n) {
sig.addReference({ xpath: n });
});

sig.canonicalizationAlgorithm = canonicalizationAlgorithm;
sig.computeSignature(xml);
const signed = sig.getSignedXml();

Expand All @@ -24,11 +25,12 @@ describe("Signature integration tests", function () {
it("verify signature", function () {
const xml =
'<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>';
verifySignature(xml, "./test/static/integration/expectedVerify.xml", [
"//*[local-name(.)='x']",
"//*[local-name(.)='y']",
"//*[local-name(.)='w']",
]);
verifySignature(
xml,
"./test/static/integration/expectedVerify.xml",
["//*[local-name(.)='x']", "//*[local-name(.)='y']", "//*[local-name(.)='w']"],
"http://www.w3.org/2001/10/xml-exc-c14n#",
);
});

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

verifySignature(xml, "./test/static/integration/expectedVerifyComplex.xml", [
"//*[local-name(.)='book']",
]);
verifySignature(
xml,
"./test/static/integration/expectedVerifyComplex.xml",
["//*[local-name(.)='book']"],
"http://www.w3.org/2001/10/xml-exc-c14n#",
);
});

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

const signed = sig.getSignedXml();
Expand Down
Loading

0 comments on commit 5629be4

Please sign in to comment.