UNPKG

2.74 kBPlain TextView Raw
1import { isEmptyData } from "./isEmptyData";
2import { SHA_256_HMAC_ALGO } from "./constants";
3import { Hash, SourceData } from "@aws-sdk/types";
4import { fromUtf8 } from "@aws-sdk/util-utf8-browser";
5import { CryptoOperation, Key, MsWindow } from "@aws-crypto/ie11-detection";
6import { locateWindow } from "@aws-sdk/util-locate-window";
7
8export class Sha256 implements Hash {
9 private operation: Promise<CryptoOperation>;
10
11 constructor(secret?: SourceData) {
12 if (secret) {
13 this.operation = getKeyPromise(secret).then(keyData =>
14 (locateWindow() as MsWindow).msCrypto.subtle.sign(
15 SHA_256_HMAC_ALGO,
16 keyData
17 )
18 );
19 this.operation.catch(() => {});
20 } else {
21 this.operation = Promise.resolve(
22 (locateWindow() as MsWindow).msCrypto.subtle.digest("SHA-256")
23 );
24 }
25 }
26
27 update(toHash: SourceData): void {
28 if (isEmptyData(toHash)) {
29 return;
30 }
31
32 this.operation = this.operation.then(operation => {
33 operation.onerror = () => {
34 this.operation = Promise.reject(
35 new Error("Error encountered updating hash")
36 );
37 };
38 operation.process(toArrayBufferView(toHash));
39
40 return operation;
41 });
42 this.operation.catch(() => {});
43 }
44
45 digest(): Promise<Uint8Array> {
46 return this.operation.then<Uint8Array>(
47 operation =>
48 new Promise((resolve, reject) => {
49 operation.onerror = () => {
50 reject(new Error("Error encountered finalizing hash"));
51 };
52 operation.oncomplete = () => {
53 if (operation.result) {
54 resolve(new Uint8Array(operation.result));
55 }
56 reject(new Error("Error encountered finalizing hash"));
57 };
58
59 operation.finish();
60 })
61 );
62 }
63}
64
65function getKeyPromise(secret: SourceData): Promise<Key> {
66 return new Promise((resolve, reject) => {
67 const keyOperation = (locateWindow() as MsWindow).msCrypto.subtle.importKey(
68 "raw",
69 toArrayBufferView(secret),
70 SHA_256_HMAC_ALGO,
71 false,
72 ["sign"]
73 );
74
75 keyOperation.oncomplete = () => {
76 if (keyOperation.result) {
77 resolve(keyOperation.result);
78 }
79
80 reject(new Error("ImportKey completed without importing key."));
81 };
82 keyOperation.onerror = () => {
83 reject(new Error("ImportKey failed to import key."));
84 };
85 });
86}
87
88function toArrayBufferView(data: SourceData): Uint8Array {
89 if (typeof data === "string") {
90 return fromUtf8(data);
91 }
92
93 if (ArrayBuffer.isView(data)) {
94 return new Uint8Array(
95 data.buffer,
96 data.byteOffset,
97 data.byteLength / Uint8Array.BYTES_PER_ELEMENT
98 );
99 }
100
101 return new Uint8Array(data);
102}