Skip to content

Commit 6d0aede

Browse files
authored
Merge pull request #15 from jeskew/feature/crypto-ie11-detection
Add IE 11 detection for crypto components
2 parents d907ef6 + f4f51b7 commit 6d0aede

File tree

10 files changed

+252
-0
lines changed

10 files changed

+252
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules
2+
*.js
3+
*.js.map
4+
*.d.ts
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import {isMsWindow, MsWindow} from "../lib/MsWindow";
2+
3+
const fakeMsWindow: MsWindow = {
4+
MSInputMethodContext: {},
5+
msCrypto: {
6+
getRandomValues: () => {},
7+
subtle: {
8+
decrypt(alg: any, key: any) { return {} as any; },
9+
digest(alg: any) { return {} as any; },
10+
encrypt(alg: any, key: any) { return {} as any; },
11+
exportKey(format: any, key: any) { return {} as any; },
12+
generateKey(alg: any) { return {} as any; },
13+
importKey(format: any, keyData: any, alg: any) { return {} as any; },
14+
sign(alg: any, key: any) { return {} as any; },
15+
verify(alg: any, key: any, signature: any) { return {} as any; },
16+
},
17+
},
18+
} as any;
19+
20+
describe('isMsWindow', () => {
21+
it(
22+
'should return false if an object does not fulfill the MsWindow interface',
23+
() => {
24+
expect(isMsWindow({} as any)).toBe(false);
25+
}
26+
);
27+
28+
it('should return true if an object fulfills the MsWindow interface', () => {
29+
expect(isMsWindow(fakeMsWindow)).toBe(true);
30+
});
31+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export * from './lib/CryptoOperation';
2+
export * from './lib/Key';
3+
export * from './lib/KeyOperation';
4+
export * from './lib/MsSubtleCrypto';
5+
export * from './lib/MsWindow';
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {Key} from "./Key";
2+
3+
/**
4+
* Represents a cryptographic operation that has been instantiated but not
5+
* necessarily fed all data or finalized.
6+
*
7+
* @see https://msdn.microsoft.com/en-us/library/dn280996(v=vs.85).aspx
8+
*/
9+
export interface CryptoOperation {
10+
readonly algorithm: string;
11+
readonly key: Key;
12+
onabort: (event: Event) => void;
13+
oncomplete: (event: Event) => void;
14+
onerror: (event: Event) => void;
15+
onprogress: (event: Event) => void;
16+
readonly result: ArrayBuffer|undefined;
17+
18+
abort(): void;
19+
finish(): void;
20+
process(buffer: ArrayBufferView): void;
21+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* The result of a successful KeyOperation.
3+
*
4+
* @see {KeyOperation}
5+
* @see https://msdn.microsoft.com/en-us/library/dn302313(v=vs.85).aspx
6+
*/
7+
export interface Key {
8+
readonly algorithm: string;
9+
readonly extractable: boolean;
10+
readonly keyUsage: Array<string>;
11+
readonly type: string;
12+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import {Key} from "./Key";
2+
3+
/**
4+
* Represents the return of a key-related operation that may or may not have
5+
* been completed.
6+
*
7+
* @see https://msdn.microsoft.com/en-us/library/dn302314(v=vs.85).aspx
8+
*/
9+
export interface KeyOperation {
10+
oncomplete: (event: Event) => void;
11+
onerror: (event: Event) => void;
12+
readonly result: Key|undefined;
13+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import {CryptoOperation} from './CryptoOperation';
2+
import {Key} from './Key';
3+
import {KeyOperation} from './KeyOperation';
4+
5+
export type KeyUsage = 'encrypt'|'decrypt'|'sign'|'verify'|'derive'|'wrap'|'unwrap';
6+
7+
export type EncryptionOrVerificationAlgorithm = 'RSAES-PKCS1-v1_5';
8+
export type Ie11EncryptionAlgorithm = 'AES-CBC'|'AES-GCM'|'RSA-OAEP'|EncryptionOrVerificationAlgorithm;
9+
export type Ie11DigestAlgorithm = 'SHA-1'|'SHA-256'|'SHA-384';
10+
11+
export interface HashAlgorithm {
12+
name: Ie11DigestAlgorithm;
13+
}
14+
15+
export interface HmacAlgorithm {
16+
name: 'HMAC';
17+
hash: HashAlgorithm;
18+
}
19+
20+
export type SigningAlgorithm = HmacAlgorithm;
21+
22+
/**
23+
* Represent ths SubtleCrypto interface as implemented in Internet Explorer 11.
24+
* This implementation was based on an earlier version of the WebCrypto API and
25+
* differs from the `window.crypto.subtle` object exposed in Chrome, Safari,
26+
* Firefox, and MS Edge.
27+
*
28+
* @see https://msdn.microsoft.com/en-us/library/dn302325(v=vs.85).aspx
29+
*/
30+
export interface MsSubtleCrypto {
31+
decrypt(
32+
algorithm: Ie11EncryptionAlgorithm,
33+
key: Key,
34+
buffer?: ArrayBufferView
35+
): CryptoOperation;
36+
37+
digest(
38+
algorithm: Ie11DigestAlgorithm,
39+
buffer?: ArrayBufferView
40+
): CryptoOperation;
41+
42+
encrypt(
43+
algorithm: Ie11EncryptionAlgorithm,
44+
key: Key,
45+
buffer?: ArrayBufferView
46+
): CryptoOperation;
47+
48+
exportKey(
49+
format: string,
50+
key: Key
51+
): KeyOperation;
52+
53+
generateKey(
54+
algorithm: SigningAlgorithm|Ie11EncryptionAlgorithm,
55+
extractable?: boolean,
56+
keyUsages?: Array<KeyUsage>
57+
): KeyOperation;
58+
59+
importKey(
60+
format: string,
61+
keyData: ArrayBufferView,
62+
algorithm: any,
63+
extractable?: boolean,
64+
keyUsages?: Array<KeyUsage>
65+
): KeyOperation;
66+
67+
sign(
68+
algorithm: SigningAlgorithm,
69+
key: Key,
70+
buffer?: ArrayBufferView,
71+
): CryptoOperation;
72+
73+
verify(
74+
algorithm: SigningAlgorithm|EncryptionOrVerificationAlgorithm,
75+
key: Key,
76+
signature: ArrayBufferView,
77+
buffer?: ArrayBufferView
78+
): CryptoOperation;
79+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import {MsSubtleCrypto} from "./MsSubtleCrypto";
2+
3+
type SubtleCryptoMethod = 'decrypt'|'digest'|'encrypt'|'exportKey'|'generateKey'|'importKey'|'sign'|'verify';
4+
5+
const msSubtleCryptoMethods: Array<SubtleCryptoMethod> = [
6+
'decrypt',
7+
'digest',
8+
'encrypt',
9+
'exportKey',
10+
'generateKey',
11+
'importKey',
12+
'sign',
13+
'verify',
14+
];
15+
16+
/**
17+
* The value accessible as `window.msCrypto` in Internet Explorer 11.
18+
*/
19+
export interface MsCrypto {
20+
getRandomValues: (toFill: Uint8Array) => void;
21+
subtle: MsSubtleCrypto;
22+
}
23+
24+
/**
25+
* The `window` object in Internet Explorer 11. This interface does not
26+
* exhaustively document the prefixed features of `window` in IE11.
27+
*/
28+
export interface MsWindow extends Window {
29+
MSInputMethodContext: any;
30+
msCrypto: MsCrypto;
31+
}
32+
33+
function quacksLikeAnMsWindow(window: Window): window is MsWindow {
34+
return 'MSInputMethodContext' in window &&
35+
'msCrypto' in window;
36+
}
37+
38+
/**
39+
* Determines if the provided window is (or is like) the window object one would
40+
* expect to encounter in Internet Explorer 11.
41+
*/
42+
export function isMsWindow(window: Window): window is MsWindow {
43+
if (quacksLikeAnMsWindow(window) && window.msCrypto.subtle !== undefined) {
44+
const {getRandomValues, subtle} = window.msCrypto;
45+
const methodsToTest = msSubtleCryptoMethods
46+
.map<Function>(methodName => subtle[methodName])
47+
.concat(getRandomValues);
48+
49+
for (let method of methodsToTest) {
50+
if (typeof method !== 'function') {
51+
return false;
52+
}
53+
}
54+
55+
return true;
56+
}
57+
58+
return false;
59+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "@aws/crypto-ie11-detection",
3+
"private": true,
4+
"version": "0.0.1",
5+
"description": "Provides functions and types for detecting if the host environment is IE11",
6+
"scripts": {
7+
"pretest": "tsc",
8+
"test": "jest"
9+
},
10+
"author": "[email protected]",
11+
"license": "UNLICENSED",
12+
"main": "index.js",
13+
"devDependencies": {
14+
"@types/jest": "^19.2.2",
15+
"jest": "^19.0.2",
16+
"typescript": "^2.3"
17+
}
18+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"compilerOptions": {
3+
"module": "commonjs",
4+
"target": "es5",
5+
"strict": true,
6+
"sourceMap": true,
7+
"declaration": true,
8+
"stripInternal": true
9+
}
10+
}

0 commit comments

Comments
 (0)