Skip to content

Commit 91db7be

Browse files
authored
Purge SJCL (#73)
* Remove SJCL from browser random source * Use crypto feature detection rather than generic runtime detection * Remove packages vendoring portions of the SJCL * Fix flaky signature tests
1 parent 8b88c79 commit 91db7be

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+109
-2573
lines changed

packages/crypto-random-source-browser/package.json

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,10 @@
77
"pretest": "tsc -p tsconfig.test.json",
88
"test": "jest"
99
},
10-
"author": "aws-javascript-sdk-team@amazon.com",
11-
"license": "UNLICENSED",
10+
"author": "aws-sdk-js@amazon.com",
11+
"license": "Apache-2.0",
1212
"dependencies": {
1313
"@aws/crypto-ie11-detection": "^0.0.1",
14-
"@aws/crypto-sjcl-random": "^0.0.1",
15-
"@aws/crypto-sjcl-codecArrayBuffer": "^0.0.1",
1614
"@aws/crypto-supports-webCrypto": "^0.0.1",
1715
"@aws/types": "^0.0.1",
1816
"@aws/util-locate-window": "^0.0.1"
@@ -25,4 +23,4 @@
2523
},
2624
"main": "./build/index.js",
2725
"types": "./build/index.d.ts"
28-
}
26+
}

packages/crypto-random-source-browser/src/ie11RandomValues.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ describe("randomValues", () => {
2222
}
2323
};
2424

25-
await expect(randomValues(12)).rejects;
25+
await expect(randomValues(12)).rejects.toMatchObject(
26+
new Error("PANIC PANIC")
27+
);
2628
});
2729
});

packages/crypto-random-source-browser/src/index.spec.ts

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,6 @@ jest.mock("./ie11RandomValues", () => {
1414
});
1515
import { randomValues as ie11RandomValues } from "./ie11RandomValues";
1616

17-
jest.mock("./jsRandomValues", () => {
18-
return { randomValues: jest.fn() };
19-
});
20-
import { randomValues as jsRandomValues } from "./jsRandomValues";
21-
2217
jest.mock("./webCryptoRandomValues", () => {
2318
return { randomValues: jest.fn() };
2419
});
@@ -28,7 +23,6 @@ beforeEach(() => {
2823
(isMsWindow as any).mockReset();
2924
(supportsWebCrypto as any).mockReset();
3025
(ie11RandomValues as any).mockReset();
31-
(jsRandomValues as any).mockReset();
3226
(webCryptoRandomValues as any).mockReset();
3327
});
3428

@@ -39,7 +33,7 @@ describe("implementation selection", () => {
3933
await randomValues(1);
4034

4135
expect((webCryptoRandomValues as any).mock.calls.length).toBe(1);
42-
expect((jsRandomValues as any).mock.calls.length).toBe(0);
36+
expect((ie11RandomValues as any).mock.calls.length).toBe(0);
4337
});
4438

4539
it("should use IE 11 WebCrypto when available", async () => {
@@ -48,7 +42,7 @@ describe("implementation selection", () => {
4842
await randomValues(1);
4943

5044
expect((ie11RandomValues as any).mock.calls.length).toBe(1);
51-
expect((jsRandomValues as any).mock.calls.length).toBe(0);
45+
expect((webCryptoRandomValues as any).mock.calls.length).toBe(0);
5246
});
5347

5448
it("should prefer standards-compliant WebCrypto over IE 11 WebCrypto", async () => {
@@ -59,18 +53,15 @@ describe("implementation selection", () => {
5953

6054
expect((webCryptoRandomValues as any).mock.calls.length).toBe(1);
6155
expect((ie11RandomValues as any).mock.calls.length).toBe(0);
62-
expect((jsRandomValues as any).mock.calls.length).toBe(0);
6356
});
6457

65-
it("should fall back on the SJCL", async () => {
66-
(supportsWebCrypto as any).mockImplementation(() => false);
67-
(isMsWindow as any).mockImplementation(() => false);
68-
69-
await randomValues(1);
58+
it("should throw if neither WebCrypto nor IE 11 Crypto is available", async () => {
59+
await expect(randomValues(1)).rejects.toMatchObject(
60+
new Error("Unable to locate secure random source.")
61+
);
7062

7163
expect((webCryptoRandomValues as any).mock.calls.length).toBe(0);
7264
expect((ie11RandomValues as any).mock.calls.length).toBe(0);
73-
expect((jsRandomValues as any).mock.calls.length).toBe(1);
7465
});
7566
});
7667

@@ -88,18 +79,21 @@ describe("global detection", () => {
8879
(global as any).self = _self;
8980
});
9081

91-
it("should fall back to the SJCL if neither window nor self is defined", async () => {
92-
await randomValues(1);
82+
it("should throw if neither window nor self is defined", async () => {
83+
await expect(randomValues(1)).rejects.toMatchObject(
84+
new Error("Unable to locate secure random source.")
85+
);
9386

9487
expect((webCryptoRandomValues as any).mock.calls.length).toBe(0);
9588
expect((ie11RandomValues as any).mock.calls.length).toBe(0);
96-
expect((jsRandomValues as any).mock.calls.length).toBe(1);
9789
});
9890

9991
it("should use `self` if window is not defined", async () => {
10092
(global as any).self = _self;
10193

102-
await randomValues(1);
94+
try {
95+
await randomValues(1);
96+
} catch {}
10397

10498
expect((supportsWebCrypto as any).mock.calls.length).toBe(1);
10599
expect((supportsWebCrypto as any).mock.calls[0][0]).toBe(_self);

packages/crypto-random-source-browser/src/index.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { randomValues as ie11RandomValues } from "./ie11RandomValues";
22
import { randomValues as webCryptoRandomValues } from "./webCryptoRandomValues";
3-
import { randomValues as sjclRandomValues } from "./jsRandomValues";
43
import { isMsWindow } from "@aws/crypto-ie11-detection";
54
import { supportsWebCrypto } from "@aws/crypto-supports-webCrypto";
65
import { locateWindow } from "@aws/util-locate-window";
76

8-
export { ie11RandomValues, webCryptoRandomValues, sjclRandomValues };
7+
export { ie11RandomValues, webCryptoRandomValues };
98

109
export function randomValues(byteLength: number): Promise<Uint8Array> {
1110
// Find the global scope for this runtime
@@ -17,5 +16,5 @@ export function randomValues(byteLength: number): Promise<Uint8Array> {
1716
return ie11RandomValues(byteLength);
1817
}
1918

20-
return sjclRandomValues(byteLength);
19+
return Promise.reject(new Error(`Unable to locate a secure random source.`));
2120
}

packages/crypto-random-source-browser/src/jsRandomValues.spec.ts

Lines changed: 0 additions & 66 deletions
This file was deleted.

packages/crypto-random-source-browser/src/jsRandomValues.ts

Lines changed: 0 additions & 28 deletions
This file was deleted.

packages/crypto-random-source-browser/src/webCryptoRandomValues.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ describe("randomValues", () => {
2222
}
2323
};
2424

25-
await expect(randomValues(12)).rejects;
25+
await expect(randomValues(12)).rejects.toMatchObject(
26+
new Error("PANIC PANIC")
27+
);
2628
});
2729
});

packages/crypto-random-source-universal/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
"dependencies": {
1313
"@aws/crypto-random-source-browser": "^0.0.1",
1414
"@aws/crypto-random-source-node": "^0.0.1",
15-
"@aws/is-node": "^0.0.1",
1615
"@aws/types": "^0.0.1"
1716
},
1817
"devDependencies": {
@@ -26,4 +25,4 @@
2625
},
2726
"main": "./build/index.js",
2827
"types": "./build/index.d.ts"
29-
}
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { randomValues } from "./";
2+
3+
jest.mock("crypto", () => {
4+
throw new Error("Crypto module is not defined");
5+
});
6+
7+
jest.mock("@aws/crypto-random-source-browser", () => {
8+
return { randomValues: jest.fn() };
9+
});
10+
import { randomValues as browserRandomValues } from "@aws/crypto-random-source-browser";
11+
jest.mock("@aws/crypto-random-source-node", () => {
12+
return { randomValues: jest.fn() };
13+
});
14+
import { randomValues as nodeRandomValues } from "@aws/crypto-random-source-node";
15+
16+
beforeEach(() => {
17+
(browserRandomValues as any).mockReset();
18+
(nodeRandomValues as any).mockReset();
19+
});
20+
21+
describe("implementation selection", () => {
22+
it("should use the browser implementation when the crypto module is not defined", async () => {
23+
await randomValues(1);
24+
25+
expect((nodeRandomValues as any).mock.calls.length).toBe(0);
26+
expect((browserRandomValues as any).mock.calls.length).toBe(1);
27+
});
28+
});
Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { isNode } from "@aws/is-node";
21
import { randomValues as browserRandomValues } from "@aws/crypto-random-source-browser";
32
import { randomValues as nodeRandomValues } from "@aws/crypto-random-source-node";
43
import { randomValues as IRandomValues } from "@aws/types";
@@ -7,9 +6,24 @@ import { randomValues as IRandomValues } from "@aws/types";
76
* @implements {IRandomValues}
87
*/
98
export function randomValues(byteLength: number): Promise<Uint8Array> {
10-
if (isNode()) {
9+
if (supportsCryptoModule) {
1110
return nodeRandomValues(byteLength);
1211
}
1312

1413
return browserRandomValues(byteLength);
1514
}
15+
16+
/**
17+
* Try to require Node's crypto module and record whether the operation
18+
* succeeded.
19+
*
20+
* @internal
21+
*/
22+
const supportsCryptoModule: boolean = (() => {
23+
try {
24+
require("crypto");
25+
return true;
26+
} catch {
27+
return false;
28+
}
29+
})();
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import { randomValues } from "./";
22

3+
jest.mock("crypto", () => {
4+
return {};
5+
});
6+
37
jest.mock("@aws/crypto-random-source-browser", () => {
48
return { randomValues: jest.fn() };
59
});
@@ -8,33 +12,21 @@ jest.mock("@aws/crypto-random-source-node", () => {
812
return { randomValues: jest.fn() };
913
});
1014
import { randomValues as nodeRandomValues } from "@aws/crypto-random-source-node";
11-
jest.mock("@aws/is-node", () => {
12-
return { isNode: jest.fn() };
13-
});
14-
import { isNode } from "@aws/is-node";
1515

1616
beforeEach(() => {
1717
(browserRandomValues as any).mockReset();
1818
(nodeRandomValues as any).mockReset();
19-
(isNode as any).mockReset();
2019
});
2120

2221
describe("implementation selection", () => {
23-
it("should use the node implementation in node", async () => {
24-
(isNode as any).mockImplementation(() => true);
22+
it("should use the node implementation when the crypto module is defined", async () => {
23+
jest.mock("crypto", () => {
24+
return {};
25+
});
2526

2627
await randomValues(1);
2728

2829
expect((nodeRandomValues as any).mock.calls.length).toBe(1);
2930
expect((browserRandomValues as any).mock.calls.length).toBe(0);
3031
});
31-
32-
it("should use the browser implementation elsewhere", async () => {
33-
(isNode as any).mockImplementation(() => false);
34-
35-
await randomValues(1);
36-
37-
expect((nodeRandomValues as any).mock.calls.length).toBe(0);
38-
expect((browserRandomValues as any).mock.calls.length).toBe(1);
39-
});
4032
});

packages/crypto-sjcl-aes/.gitignore

Lines changed: 0 additions & 4 deletions
This file was deleted.

packages/crypto-sjcl-aes/.npmignore

Lines changed: 0 additions & 3 deletions
This file was deleted.

packages/crypto-sjcl-aes/__tests__/index.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)