Skip to content

Commit 1ea275c

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 858cefa commit 1ea275c

Some content is hidden

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

77 files changed

+153
-2619
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: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ describe('randomValues', () => {
2525
}
2626
};
2727

28-
await expect(randomValues(12)).rejects;
28+
await expect(randomValues(12)).rejects
29+
.toMatchObject(new Error('PANIC PANIC'));
2930
}
3031
);
3132
});

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

Lines changed: 22 additions & 28 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(
@@ -61,20 +55,20 @@ describe('implementation selection', () => {
6155

6256
expect((webCryptoRandomValues as any).mock.calls.length).toBe(1);
6357
expect((ie11RandomValues as any).mock.calls.length).toBe(0);
64-
expect((jsRandomValues as any).mock.calls.length).toBe(0);
6558
}
6659
);
6760

68-
it('should fall back on the SJCL', async () => {
69-
(supportsWebCrypto as any).mockImplementation(() => false);
70-
(isMsWindow as any).mockImplementation(() => false);
71-
72-
await randomValues(1);
61+
it(
62+
'should throw if neither WebCrypto nor IE 11 Crypto is available',
63+
async () => {
64+
await expect(randomValues(1)).rejects.toMatchObject(
65+
new Error('Unable to locate secure random source.')
66+
);
7367

74-
expect((webCryptoRandomValues as any).mock.calls.length).toBe(0);
75-
expect((ie11RandomValues as any).mock.calls.length).toBe(0);
76-
expect((jsRandomValues as any).mock.calls.length).toBe(1);
77-
});
68+
expect((webCryptoRandomValues as any).mock.calls.length).toBe(0);
69+
expect((ie11RandomValues as any).mock.calls.length).toBe(0);
70+
}
71+
);
7872
});
7973

8074
describe('global detection', () => {
@@ -91,21 +85,21 @@ describe('global detection', () => {
9185
(global as any).self = _self;
9286
});
9387

94-
it(
95-
'should fall back to the SJCL if neither window nor self is defined',
96-
async () => {
97-
await randomValues(1);
88+
it('should throw if neither window nor self is defined', async () => {
89+
await expect(randomValues(1)).rejects.toMatchObject(
90+
new Error('Unable to locate secure random source.')
91+
);
9892

99-
expect((webCryptoRandomValues as any).mock.calls.length).toBe(0);
100-
expect((ie11RandomValues as any).mock.calls.length).toBe(0);
101-
expect((jsRandomValues as any).mock.calls.length).toBe(1);
102-
}
103-
);
93+
expect((webCryptoRandomValues as any).mock.calls.length).toBe(0);
94+
expect((ie11RandomValues as any).mock.calls.length).toBe(0);
95+
});
10496

10597
it('should use `self` if window is not defined', async () => {
10698
(global as any).self = _self;
10799

108-
await randomValues(1);
100+
try {
101+
await randomValues(1);
102+
} catch {}
109103

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

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

Lines changed: 4 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,7 @@ export function randomValues(byteLength: number): Promise<Uint8Array> {
1716
return ie11RandomValues(byteLength);
1817
}
1918

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

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

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

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

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

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ describe('randomValues', () => {
2525
}
2626
};
2727

28-
await expect(randomValues(12)).rejects;
28+
await expect(randomValues(12)).rejects
29+
.toMatchObject(new Error('PANIC PANIC'));
2930
}
3031
);
3132
});

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: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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(
23+
'should use the browser implementation when the crypto module is not defined',
24+
async () => {
25+
await randomValues(1);
26+
27+
expect((nodeRandomValues as any).mock.calls.length).toBe(0);
28+
expect((browserRandomValues as any).mock.calls.length).toBe(1);
29+
}
30+
);
31+
});

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

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

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

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 {
32
randomValues as browserRandomValues
43
} from '@aws/crypto-random-source-browser';
@@ -11,9 +10,24 @@ import {randomValues as IRandomValues} from '@aws/types';
1110
* @implements {IRandomValues}
1211
*/
1312
export function randomValues(byteLength: number): Promise<Uint8Array> {
14-
if (isNode()) {
13+
if (supportsCryptoModule) {
1514
return nodeRandomValues(byteLength);
1615
}
1716

1817
return browserRandomValues(byteLength);
1918
}
19+
20+
/**
21+
* Try to require Node's crypto module and record whether the operation
22+
* succeeded.
23+
*
24+
* @internal
25+
*/
26+
const supportsCryptoModule: boolean = (() => {
27+
try {
28+
require('crypto');
29+
return true;
30+
} catch {
31+
return false;
32+
}
33+
})();

0 commit comments

Comments
 (0)