@queue-it/fastly 2.0.2 → 2.0.3-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +134 -134
- package/package.json +6 -11
- package/src/contextProvider.ts +134 -126
- package/src/fastlyCryptoProvider.ts +8 -0
- package/src/helper.ts +1 -8
- package/src/{sdk/helpers → helpers}/crypto.ts +338 -338
- package/src/index.ts +3 -3
- package/src/integrationConfigProvider.ts +1 -0
- package/src/requestResponseHandler.ts +129 -131
- package/LICENSE +0 -21
- package/src/sdk/HttpContextProvider.ts +0 -23
- package/src/sdk/IntegrationConfig/CustomerIntegrationDecodingHandler.ts +0 -57
- package/src/sdk/IntegrationConfig/IntegrationConfigHelpers.ts +0 -230
- package/src/sdk/IntegrationConfig/IntegrationConfigModel.ts +0 -93
- package/src/sdk/KnownUser.ts +0 -393
- package/src/sdk/Models.ts +0 -105
- package/src/sdk/QueueITHelpers.ts +0 -267
- package/src/sdk/UserInQueueService.ts +0 -245
- package/src/sdk/UserInQueueStateCookieRepository.ts +0 -188
- package/src/sdk/helpers/Uri.ts +0 -4
|
@@ -1,338 +1,338 @@
|
|
|
1
|
-
// Hash implements SHA256 hash algorithm.
|
|
2
|
-
export class Hash {
|
|
3
|
-
blockSize: number;
|
|
4
|
-
digestLength: number;
|
|
5
|
-
private readonly state: Int32Array;
|
|
6
|
-
private readonly temp: Int32Array;
|
|
7
|
-
private readonly buffer: Uint8Array;
|
|
8
|
-
private bufferLength: number;
|
|
9
|
-
private bytesHashed: number;
|
|
10
|
-
finished: boolean = false
|
|
11
|
-
|
|
12
|
-
// SHA-256 constants
|
|
13
|
-
static K: number[] = [
|
|
14
|
-
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
|
|
15
|
-
0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
|
|
16
|
-
0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
|
|
17
|
-
0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
|
18
|
-
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
|
|
19
|
-
0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
|
|
20
|
-
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
|
|
21
|
-
0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
22
|
-
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
|
|
23
|
-
0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
|
|
24
|
-
0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
|
|
25
|
-
0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
|
26
|
-
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];
|
|
27
|
-
|
|
28
|
-
constructor() {
|
|
29
|
-
this.digestLength = 32;
|
|
30
|
-
this.blockSize = 64;
|
|
31
|
-
// Note: Int32Array is used instead of Uint32Array for performance reasons.
|
|
32
|
-
this.state = new Int32Array(8); // hash state
|
|
33
|
-
this.temp = new Int32Array(64); // temporary state
|
|
34
|
-
this.buffer = new Uint8Array(128); // buffer for data to hash
|
|
35
|
-
this.bufferLength = 0; // number of bytes in buffer
|
|
36
|
-
this.bytesHashed = 0; // number of total bytes hashed
|
|
37
|
-
this.finished = false; // indicates whether the hash was finalized
|
|
38
|
-
this.reset();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Resets hash state making it possible
|
|
42
|
-
// to re-use this instance to hash other data.
|
|
43
|
-
reset(): Hash {
|
|
44
|
-
this.state[0] = 0x6a09e667;
|
|
45
|
-
this.state[1] = 0xbb67ae85;
|
|
46
|
-
this.state[2] = 0x3c6ef372;
|
|
47
|
-
this.state[3] = 0xa54ff53a;
|
|
48
|
-
this.state[4] = 0x510e527f;
|
|
49
|
-
this.state[5] = 0x9b05688c;
|
|
50
|
-
this.state[6] = 0x1f83d9ab;
|
|
51
|
-
this.state[7] = 0x5be0cd19;
|
|
52
|
-
this.bufferLength = 0;
|
|
53
|
-
this.bytesHashed = 0;
|
|
54
|
-
this.finished = false;
|
|
55
|
-
return this;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// Cleans internal buffers and re-initializes hash state.
|
|
59
|
-
clean(): void {
|
|
60
|
-
for (let i = 0; i < this.buffer.length; i++) {
|
|
61
|
-
this.buffer[i] = 0;
|
|
62
|
-
}
|
|
63
|
-
for (let i = 0; i < this.temp.length; i++) {
|
|
64
|
-
this.temp[i] = 0;
|
|
65
|
-
}
|
|
66
|
-
this.reset();
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
// Updates hash state with the given data.
|
|
70
|
-
//
|
|
71
|
-
// Optionally, length of the data can be specified to hash
|
|
72
|
-
// fewer bytes than data.length.
|
|
73
|
-
|
|
74
|
-
// Throws error when trying to update already finalized hash:
|
|
75
|
-
// instance must be reset to use it again.
|
|
76
|
-
update(data: Uint8Array, dataLength: number = 0): Hash {
|
|
77
|
-
if (dataLength == 0) {
|
|
78
|
-
dataLength = data.length;
|
|
79
|
-
}
|
|
80
|
-
if (this.finished) {
|
|
81
|
-
throw new Error("SHA256: can't update because hash was finished.");
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
let dataPos: number = 0;
|
|
85
|
-
this.bytesHashed += dataLength;
|
|
86
|
-
if (this.bufferLength > 0) {
|
|
87
|
-
while (this.bufferLength < 64 && dataLength > 0) {
|
|
88
|
-
this.buffer[this.bufferLength++] = data[dataPos++];
|
|
89
|
-
dataLength--;
|
|
90
|
-
}
|
|
91
|
-
if (this.bufferLength == 64) {
|
|
92
|
-
Hash.hashBlocks(this.temp, this.state, this.buffer, 0, 64);
|
|
93
|
-
this.bufferLength = 0;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
if (dataLength >= 64) {
|
|
97
|
-
dataPos = Hash.hashBlocks(this.temp, this.state, data, dataPos, dataLength);
|
|
98
|
-
dataLength %= 64;
|
|
99
|
-
}
|
|
100
|
-
while (dataLength > 0) {
|
|
101
|
-
this.buffer[this.bufferLength++] = data[dataPos++];
|
|
102
|
-
dataLength--;
|
|
103
|
-
}
|
|
104
|
-
return this;
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
// Finalizes hash state and puts hash into out.
|
|
108
|
-
//
|
|
109
|
-
// If hash was already finalized, puts the same value.
|
|
110
|
-
finish(out: Uint8Array): Hash {
|
|
111
|
-
if (!this.finished) {
|
|
112
|
-
let bytesHashed: number = this.bytesHashed;
|
|
113
|
-
let left: number = this.bufferLength;
|
|
114
|
-
let bitLenHi: number = (bytesHashed / 0x20000000) | 0;
|
|
115
|
-
let bitLenLo: number = bytesHashed << 3;
|
|
116
|
-
let padLength: number = (bytesHashed % 64 < 56) ? 64 : 128;
|
|
117
|
-
this.buffer[left] = 0x80;
|
|
118
|
-
for (let i = left + 1; i < padLength - 8; i++) {
|
|
119
|
-
this.buffer[i] = 0;
|
|
120
|
-
}
|
|
121
|
-
this.buffer[padLength - 8] = (bitLenHi >>> 24) & 0xff;
|
|
122
|
-
this.buffer[padLength - 7] = (bitLenHi >>> 16) & 0xff;
|
|
123
|
-
this.buffer[padLength - 6] = (bitLenHi >>> 8) & 0xff;
|
|
124
|
-
this.buffer[padLength - 5] = (bitLenHi >>> 0) & 0xff;
|
|
125
|
-
this.buffer[padLength - 4] = (bitLenLo >>> 24) & 0xff;
|
|
126
|
-
this.buffer[padLength - 3] = (bitLenLo >>> 16) & 0xff;
|
|
127
|
-
this.buffer[padLength - 2] = (bitLenLo >>> 8) & 0xff;
|
|
128
|
-
this.buffer[padLength - 1] = (bitLenLo >>> 0) & 0xff;
|
|
129
|
-
|
|
130
|
-
Hash.hashBlocks(this.temp, this.state, this.buffer, 0, padLength);
|
|
131
|
-
this.finished = true;
|
|
132
|
-
}
|
|
133
|
-
for (let i = 0; i < 8; i++) {
|
|
134
|
-
out[i * 4] = (this.state[i] >>> 24) & 0xff;
|
|
135
|
-
out[i * 4 + 1] = (this.state[i] >>> 16) & 0xff;
|
|
136
|
-
out[i * 4 + 2] = (this.state[i] >>> 8) & 0xff;
|
|
137
|
-
out[i * 4 + 3] = (this.state[i] >>> 0) & 0xff;
|
|
138
|
-
}
|
|
139
|
-
return this;
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
// Returns the final hash digest.
|
|
143
|
-
digest(): Uint8Array {
|
|
144
|
-
let out = new Uint8Array(this.digestLength);
|
|
145
|
-
this.finish(out);
|
|
146
|
-
return out;
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
// Internal function for use in HMAC for optimization.
|
|
150
|
-
_saveState(out: Uint32Array): void {
|
|
151
|
-
for (let i = 0; i < this.state.length; i++) {
|
|
152
|
-
out[i] = this.state[i];
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
// Internal function for use in HMAC for optimization.
|
|
157
|
-
_restoreState(from: Uint32Array, bytesHashed: number): void {
|
|
158
|
-
for (let i = 0; i < this.state.length; i++) {
|
|
159
|
-
this.state[i] = from[i];
|
|
160
|
-
}
|
|
161
|
-
this.bytesHashed = bytesHashed;
|
|
162
|
-
this.finished = false;
|
|
163
|
-
this.bufferLength = 0;
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
static hashBlocks(w: Int32Array, v: Int32Array, p: Uint8Array, pos: number, len: number): number {
|
|
167
|
-
let a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, u: number, i: number, j: number, t1: number, t2: number;
|
|
168
|
-
while (len >= 64) {
|
|
169
|
-
a = v[0];
|
|
170
|
-
b = v[1];
|
|
171
|
-
c = v[2];
|
|
172
|
-
d = v[3];
|
|
173
|
-
e = v[4];
|
|
174
|
-
f = v[5];
|
|
175
|
-
g = v[6];
|
|
176
|
-
h = v[7];
|
|
177
|
-
for (i = 0; i < 16; i++) {
|
|
178
|
-
j = pos + i * 4;
|
|
179
|
-
let p1 = ((p[j] & 0xff) << 24);
|
|
180
|
-
let p2 = ((p[j + 1] & 0xff) << 16);
|
|
181
|
-
let p3 = ((p[j + 2] & 0xff) << 8);
|
|
182
|
-
let p4 = (p[j + 3] & 0xff);
|
|
183
|
-
w[i] = p1 | p2 | p3 | p4;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
for (i = 16; i < 64; i++) {
|
|
187
|
-
u = w[i - 2];
|
|
188
|
-
t1 = (u >>> 17 | u << (32 - 17)) ^ (u >>> 19 | u << (32 - 19)) ^ (u >>> 10);
|
|
189
|
-
u = w[i - 15];
|
|
190
|
-
t2 = (u >>> 7 | u << (32 - 7)) ^ (u >>> 18 | u << (32 - 18)) ^ (u >>> 3);
|
|
191
|
-
w[i] = (t1 + w[i - 7] | 0) + (t2 + w[i - 16] | 0);
|
|
192
|
-
}
|
|
193
|
-
for (i = 0; i < 64; i++) {
|
|
194
|
-
t1 = (((((e >>> 6 | e << (32 - 6)) ^ (e >>> 11 | e << (32 - 11)) ^
|
|
195
|
-
(e >>> 25 | e << (32 - 25))) + ((e & f) ^ (~e & g))) | 0) +
|
|
196
|
-
((h + ((Hash.K[i] + w[i]) | 0)) | 0)) | 0;
|
|
197
|
-
t2 = (((a >>> 2 | a << (32 - 2)) ^ (a >>> 13 | a << (32 - 13)) ^
|
|
198
|
-
(a >>> 22 | a << (32 - 22))) + ((a & b) ^ (a & c) ^ (b & c))) | 0;
|
|
199
|
-
h = g;
|
|
200
|
-
g = f;
|
|
201
|
-
f = e;
|
|
202
|
-
e = (d + t1) | 0;
|
|
203
|
-
d = c;
|
|
204
|
-
c = b;
|
|
205
|
-
b = a;
|
|
206
|
-
a = (t1 + t2) | 0;
|
|
207
|
-
}
|
|
208
|
-
v[0] += a;
|
|
209
|
-
v[1] += b;
|
|
210
|
-
v[2] += c;
|
|
211
|
-
v[3] += d;
|
|
212
|
-
v[4] += e;
|
|
213
|
-
v[5] += f;
|
|
214
|
-
v[6] += g;
|
|
215
|
-
v[7] += h;
|
|
216
|
-
pos += 64;
|
|
217
|
-
len -= 64;
|
|
218
|
-
}
|
|
219
|
-
return pos;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// HMAC implements HMAC-SHA256 message authentication algorithm.
|
|
224
|
-
export class HMAC {
|
|
225
|
-
private inner: Hash
|
|
226
|
-
private outer: Hash
|
|
227
|
-
blockSize: number
|
|
228
|
-
digestLength: number
|
|
229
|
-
private readonly istate: Uint32Array
|
|
230
|
-
private readonly ostate: Uint32Array
|
|
231
|
-
|
|
232
|
-
constructor(key: Uint8Array) {
|
|
233
|
-
this.inner = new Hash();
|
|
234
|
-
this.outer = new Hash();
|
|
235
|
-
this.blockSize = this.inner.blockSize;
|
|
236
|
-
this.digestLength = this.inner.digestLength;
|
|
237
|
-
const pad = new Uint8Array(this.blockSize);
|
|
238
|
-
if (key.length > this.blockSize) {
|
|
239
|
-
(new Hash()).update(key).finish(pad).clean();
|
|
240
|
-
} else {
|
|
241
|
-
for (let i = 0; i < key.length; i++) {
|
|
242
|
-
pad[i] = key[i];
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
for (let i = 0; i < pad.length; i++) {
|
|
246
|
-
pad[i] ^= 0x36;
|
|
247
|
-
}
|
|
248
|
-
this.inner.update(pad);
|
|
249
|
-
for (let i = 0; i < pad.length; i++) {
|
|
250
|
-
pad[i] ^= 0x36 ^ 0x5c;
|
|
251
|
-
}
|
|
252
|
-
this.outer.update(pad);
|
|
253
|
-
this.istate = new Uint32Array(8);
|
|
254
|
-
this.ostate = new Uint32Array(8);
|
|
255
|
-
this.inner._saveState(this.istate);
|
|
256
|
-
this.outer._saveState(this.ostate);
|
|
257
|
-
for (let i = 0; i < pad.length; i++) {
|
|
258
|
-
pad[i] = 0;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Returns HMAC state to the state initialized with key
|
|
263
|
-
// to make it possible to run HMAC over the other data with the same
|
|
264
|
-
// key without creating a new instance.
|
|
265
|
-
reset(): HMAC {
|
|
266
|
-
this.inner._restoreState(this.istate, this.inner.blockSize);
|
|
267
|
-
this.outer._restoreState(this.ostate, this.outer.blockSize);
|
|
268
|
-
return this;
|
|
269
|
-
};
|
|
270
|
-
|
|
271
|
-
// Cleans HMAC state.
|
|
272
|
-
clean(): void {
|
|
273
|
-
for (let i = 0; i < this.istate.length; i++) {
|
|
274
|
-
this.ostate[i] = this.istate[i] = 0;
|
|
275
|
-
}
|
|
276
|
-
this.inner.clean();
|
|
277
|
-
this.outer.clean();
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
// Updates state with provided data.
|
|
281
|
-
update(data: Uint8Array): HMAC {
|
|
282
|
-
this.inner.update(data);
|
|
283
|
-
return this;
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
// Finalizes HMAC and puts the result in out.
|
|
287
|
-
finish(out: Uint8Array): HMAC {
|
|
288
|
-
if (this.outer.finished) {
|
|
289
|
-
this.outer.finish(out);
|
|
290
|
-
} else {
|
|
291
|
-
this.inner.finish(out);
|
|
292
|
-
this.outer.update(out, this.digestLength).finish(out);
|
|
293
|
-
}
|
|
294
|
-
return this;
|
|
295
|
-
};
|
|
296
|
-
|
|
297
|
-
// Returns message authentication code.
|
|
298
|
-
digest(): Uint8Array {
|
|
299
|
-
let out = new Uint8Array(this.digestLength);
|
|
300
|
-
this.finish(out);
|
|
301
|
-
return out;
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// Returns SHA256 hash of data.
|
|
306
|
-
export function hash(data: Uint8Array): Uint8Array {
|
|
307
|
-
const h = (new Hash()).update(data);
|
|
308
|
-
const digest = h.digest();
|
|
309
|
-
h.clean();
|
|
310
|
-
return digest;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
export function hashString(data: string): string {
|
|
314
|
-
return toHex(hash(new TextEncoder().encode(data)));
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// Returns HMAC-SHA256 of data under the key.
|
|
318
|
-
export function hmac(key: Uint8Array, data: Uint8Array): Uint8Array {
|
|
319
|
-
const h = (new HMAC(key)).update(data);
|
|
320
|
-
const digest = h.digest();
|
|
321
|
-
h.clean();
|
|
322
|
-
return digest;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
export function toHex(byteArray: Uint8Array): string {
|
|
326
|
-
let acc = '';
|
|
327
|
-
for (let i = 0; i < byteArray.length; i++) {
|
|
328
|
-
let val = byteArray[i];
|
|
329
|
-
acc += ('0' + val.toString(16)).slice(-2);
|
|
330
|
-
}
|
|
331
|
-
return acc;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
export function hmacString(key: string, data: string): string {
|
|
335
|
-
const encoder = new TextEncoder();
|
|
336
|
-
const result = hmac(encoder.encode(key), encoder.encode(data));
|
|
337
|
-
return toHex(result);
|
|
338
|
-
}
|
|
1
|
+
// Hash implements SHA256 hash algorithm.
|
|
2
|
+
export class Hash {
|
|
3
|
+
blockSize: number;
|
|
4
|
+
digestLength: number;
|
|
5
|
+
private readonly state: Int32Array;
|
|
6
|
+
private readonly temp: Int32Array;
|
|
7
|
+
private readonly buffer: Uint8Array;
|
|
8
|
+
private bufferLength: number;
|
|
9
|
+
private bytesHashed: number;
|
|
10
|
+
finished: boolean = false
|
|
11
|
+
|
|
12
|
+
// SHA-256 constants
|
|
13
|
+
static K: number[] = [
|
|
14
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
|
|
15
|
+
0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
|
|
16
|
+
0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
|
|
17
|
+
0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
|
18
|
+
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
|
|
19
|
+
0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
|
|
20
|
+
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
|
|
21
|
+
0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
22
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
|
|
23
|
+
0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
|
|
24
|
+
0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
|
|
25
|
+
0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
|
26
|
+
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];
|
|
27
|
+
|
|
28
|
+
constructor() {
|
|
29
|
+
this.digestLength = 32;
|
|
30
|
+
this.blockSize = 64;
|
|
31
|
+
// Note: Int32Array is used instead of Uint32Array for performance reasons.
|
|
32
|
+
this.state = new Int32Array(8); // hash state
|
|
33
|
+
this.temp = new Int32Array(64); // temporary state
|
|
34
|
+
this.buffer = new Uint8Array(128); // buffer for data to hash
|
|
35
|
+
this.bufferLength = 0; // number of bytes in buffer
|
|
36
|
+
this.bytesHashed = 0; // number of total bytes hashed
|
|
37
|
+
this.finished = false; // indicates whether the hash was finalized
|
|
38
|
+
this.reset();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Resets hash state making it possible
|
|
42
|
+
// to re-use this instance to hash other data.
|
|
43
|
+
reset(): Hash {
|
|
44
|
+
this.state[0] = 0x6a09e667;
|
|
45
|
+
this.state[1] = 0xbb67ae85;
|
|
46
|
+
this.state[2] = 0x3c6ef372;
|
|
47
|
+
this.state[3] = 0xa54ff53a;
|
|
48
|
+
this.state[4] = 0x510e527f;
|
|
49
|
+
this.state[5] = 0x9b05688c;
|
|
50
|
+
this.state[6] = 0x1f83d9ab;
|
|
51
|
+
this.state[7] = 0x5be0cd19;
|
|
52
|
+
this.bufferLength = 0;
|
|
53
|
+
this.bytesHashed = 0;
|
|
54
|
+
this.finished = false;
|
|
55
|
+
return this;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Cleans internal buffers and re-initializes hash state.
|
|
59
|
+
clean(): void {
|
|
60
|
+
for (let i = 0; i < this.buffer.length; i++) {
|
|
61
|
+
this.buffer[i] = 0;
|
|
62
|
+
}
|
|
63
|
+
for (let i = 0; i < this.temp.length; i++) {
|
|
64
|
+
this.temp[i] = 0;
|
|
65
|
+
}
|
|
66
|
+
this.reset();
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Updates hash state with the given data.
|
|
70
|
+
//
|
|
71
|
+
// Optionally, length of the data can be specified to hash
|
|
72
|
+
// fewer bytes than data.length.
|
|
73
|
+
|
|
74
|
+
// Throws error when trying to update already finalized hash:
|
|
75
|
+
// instance must be reset to use it again.
|
|
76
|
+
update(data: Uint8Array, dataLength: number = 0): Hash {
|
|
77
|
+
if (dataLength == 0) {
|
|
78
|
+
dataLength = data.length;
|
|
79
|
+
}
|
|
80
|
+
if (this.finished) {
|
|
81
|
+
throw new Error("SHA256: can't update because hash was finished.");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
let dataPos: number = 0;
|
|
85
|
+
this.bytesHashed += dataLength;
|
|
86
|
+
if (this.bufferLength > 0) {
|
|
87
|
+
while (this.bufferLength < 64 && dataLength > 0) {
|
|
88
|
+
this.buffer[this.bufferLength++] = data[dataPos++];
|
|
89
|
+
dataLength--;
|
|
90
|
+
}
|
|
91
|
+
if (this.bufferLength == 64) {
|
|
92
|
+
Hash.hashBlocks(this.temp, this.state, this.buffer, 0, 64);
|
|
93
|
+
this.bufferLength = 0;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (dataLength >= 64) {
|
|
97
|
+
dataPos = Hash.hashBlocks(this.temp, this.state, data, dataPos, dataLength);
|
|
98
|
+
dataLength %= 64;
|
|
99
|
+
}
|
|
100
|
+
while (dataLength > 0) {
|
|
101
|
+
this.buffer[this.bufferLength++] = data[dataPos++];
|
|
102
|
+
dataLength--;
|
|
103
|
+
}
|
|
104
|
+
return this;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// Finalizes hash state and puts hash into out.
|
|
108
|
+
//
|
|
109
|
+
// If hash was already finalized, puts the same value.
|
|
110
|
+
finish(out: Uint8Array): Hash {
|
|
111
|
+
if (!this.finished) {
|
|
112
|
+
let bytesHashed: number = this.bytesHashed;
|
|
113
|
+
let left: number = this.bufferLength;
|
|
114
|
+
let bitLenHi: number = (bytesHashed / 0x20000000) | 0;
|
|
115
|
+
let bitLenLo: number = bytesHashed << 3;
|
|
116
|
+
let padLength: number = (bytesHashed % 64 < 56) ? 64 : 128;
|
|
117
|
+
this.buffer[left] = 0x80;
|
|
118
|
+
for (let i = left + 1; i < padLength - 8; i++) {
|
|
119
|
+
this.buffer[i] = 0;
|
|
120
|
+
}
|
|
121
|
+
this.buffer[padLength - 8] = (bitLenHi >>> 24) & 0xff;
|
|
122
|
+
this.buffer[padLength - 7] = (bitLenHi >>> 16) & 0xff;
|
|
123
|
+
this.buffer[padLength - 6] = (bitLenHi >>> 8) & 0xff;
|
|
124
|
+
this.buffer[padLength - 5] = (bitLenHi >>> 0) & 0xff;
|
|
125
|
+
this.buffer[padLength - 4] = (bitLenLo >>> 24) & 0xff;
|
|
126
|
+
this.buffer[padLength - 3] = (bitLenLo >>> 16) & 0xff;
|
|
127
|
+
this.buffer[padLength - 2] = (bitLenLo >>> 8) & 0xff;
|
|
128
|
+
this.buffer[padLength - 1] = (bitLenLo >>> 0) & 0xff;
|
|
129
|
+
|
|
130
|
+
Hash.hashBlocks(this.temp, this.state, this.buffer, 0, padLength);
|
|
131
|
+
this.finished = true;
|
|
132
|
+
}
|
|
133
|
+
for (let i = 0; i < 8; i++) {
|
|
134
|
+
out[i * 4] = (this.state[i] >>> 24) & 0xff;
|
|
135
|
+
out[i * 4 + 1] = (this.state[i] >>> 16) & 0xff;
|
|
136
|
+
out[i * 4 + 2] = (this.state[i] >>> 8) & 0xff;
|
|
137
|
+
out[i * 4 + 3] = (this.state[i] >>> 0) & 0xff;
|
|
138
|
+
}
|
|
139
|
+
return this;
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// Returns the final hash digest.
|
|
143
|
+
digest(): Uint8Array {
|
|
144
|
+
let out = new Uint8Array(this.digestLength);
|
|
145
|
+
this.finish(out);
|
|
146
|
+
return out;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// Internal function for use in HMAC for optimization.
|
|
150
|
+
_saveState(out: Uint32Array): void {
|
|
151
|
+
for (let i = 0; i < this.state.length; i++) {
|
|
152
|
+
out[i] = this.state[i];
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// Internal function for use in HMAC for optimization.
|
|
157
|
+
_restoreState(from: Uint32Array, bytesHashed: number): void {
|
|
158
|
+
for (let i = 0; i < this.state.length; i++) {
|
|
159
|
+
this.state[i] = from[i];
|
|
160
|
+
}
|
|
161
|
+
this.bytesHashed = bytesHashed;
|
|
162
|
+
this.finished = false;
|
|
163
|
+
this.bufferLength = 0;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
static hashBlocks(w: Int32Array, v: Int32Array, p: Uint8Array, pos: number, len: number): number {
|
|
167
|
+
let a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, u: number, i: number, j: number, t1: number, t2: number;
|
|
168
|
+
while (len >= 64) {
|
|
169
|
+
a = v[0];
|
|
170
|
+
b = v[1];
|
|
171
|
+
c = v[2];
|
|
172
|
+
d = v[3];
|
|
173
|
+
e = v[4];
|
|
174
|
+
f = v[5];
|
|
175
|
+
g = v[6];
|
|
176
|
+
h = v[7];
|
|
177
|
+
for (i = 0; i < 16; i++) {
|
|
178
|
+
j = pos + i * 4;
|
|
179
|
+
let p1 = ((p[j] & 0xff) << 24);
|
|
180
|
+
let p2 = ((p[j + 1] & 0xff) << 16);
|
|
181
|
+
let p3 = ((p[j + 2] & 0xff) << 8);
|
|
182
|
+
let p4 = (p[j + 3] & 0xff);
|
|
183
|
+
w[i] = p1 | p2 | p3 | p4;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
for (i = 16; i < 64; i++) {
|
|
187
|
+
u = w[i - 2];
|
|
188
|
+
t1 = (u >>> 17 | u << (32 - 17)) ^ (u >>> 19 | u << (32 - 19)) ^ (u >>> 10);
|
|
189
|
+
u = w[i - 15];
|
|
190
|
+
t2 = (u >>> 7 | u << (32 - 7)) ^ (u >>> 18 | u << (32 - 18)) ^ (u >>> 3);
|
|
191
|
+
w[i] = (t1 + w[i - 7] | 0) + (t2 + w[i - 16] | 0);
|
|
192
|
+
}
|
|
193
|
+
for (i = 0; i < 64; i++) {
|
|
194
|
+
t1 = (((((e >>> 6 | e << (32 - 6)) ^ (e >>> 11 | e << (32 - 11)) ^
|
|
195
|
+
(e >>> 25 | e << (32 - 25))) + ((e & f) ^ (~e & g))) | 0) +
|
|
196
|
+
((h + ((Hash.K[i] + w[i]) | 0)) | 0)) | 0;
|
|
197
|
+
t2 = (((a >>> 2 | a << (32 - 2)) ^ (a >>> 13 | a << (32 - 13)) ^
|
|
198
|
+
(a >>> 22 | a << (32 - 22))) + ((a & b) ^ (a & c) ^ (b & c))) | 0;
|
|
199
|
+
h = g;
|
|
200
|
+
g = f;
|
|
201
|
+
f = e;
|
|
202
|
+
e = (d + t1) | 0;
|
|
203
|
+
d = c;
|
|
204
|
+
c = b;
|
|
205
|
+
b = a;
|
|
206
|
+
a = (t1 + t2) | 0;
|
|
207
|
+
}
|
|
208
|
+
v[0] += a;
|
|
209
|
+
v[1] += b;
|
|
210
|
+
v[2] += c;
|
|
211
|
+
v[3] += d;
|
|
212
|
+
v[4] += e;
|
|
213
|
+
v[5] += f;
|
|
214
|
+
v[6] += g;
|
|
215
|
+
v[7] += h;
|
|
216
|
+
pos += 64;
|
|
217
|
+
len -= 64;
|
|
218
|
+
}
|
|
219
|
+
return pos;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// HMAC implements HMAC-SHA256 message authentication algorithm.
|
|
224
|
+
export class HMAC {
|
|
225
|
+
private inner: Hash
|
|
226
|
+
private outer: Hash
|
|
227
|
+
blockSize: number
|
|
228
|
+
digestLength: number
|
|
229
|
+
private readonly istate: Uint32Array
|
|
230
|
+
private readonly ostate: Uint32Array
|
|
231
|
+
|
|
232
|
+
constructor(key: Uint8Array) {
|
|
233
|
+
this.inner = new Hash();
|
|
234
|
+
this.outer = new Hash();
|
|
235
|
+
this.blockSize = this.inner.blockSize;
|
|
236
|
+
this.digestLength = this.inner.digestLength;
|
|
237
|
+
const pad = new Uint8Array(this.blockSize);
|
|
238
|
+
if (key.length > this.blockSize) {
|
|
239
|
+
(new Hash()).update(key).finish(pad).clean();
|
|
240
|
+
} else {
|
|
241
|
+
for (let i = 0; i < key.length; i++) {
|
|
242
|
+
pad[i] = key[i];
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
for (let i = 0; i < pad.length; i++) {
|
|
246
|
+
pad[i] ^= 0x36;
|
|
247
|
+
}
|
|
248
|
+
this.inner.update(pad);
|
|
249
|
+
for (let i = 0; i < pad.length; i++) {
|
|
250
|
+
pad[i] ^= 0x36 ^ 0x5c;
|
|
251
|
+
}
|
|
252
|
+
this.outer.update(pad);
|
|
253
|
+
this.istate = new Uint32Array(8);
|
|
254
|
+
this.ostate = new Uint32Array(8);
|
|
255
|
+
this.inner._saveState(this.istate);
|
|
256
|
+
this.outer._saveState(this.ostate);
|
|
257
|
+
for (let i = 0; i < pad.length; i++) {
|
|
258
|
+
pad[i] = 0;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Returns HMAC state to the state initialized with key
|
|
263
|
+
// to make it possible to run HMAC over the other data with the same
|
|
264
|
+
// key without creating a new instance.
|
|
265
|
+
reset(): HMAC {
|
|
266
|
+
this.inner._restoreState(this.istate, this.inner.blockSize);
|
|
267
|
+
this.outer._restoreState(this.ostate, this.outer.blockSize);
|
|
268
|
+
return this;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
// Cleans HMAC state.
|
|
272
|
+
clean(): void {
|
|
273
|
+
for (let i = 0; i < this.istate.length; i++) {
|
|
274
|
+
this.ostate[i] = this.istate[i] = 0;
|
|
275
|
+
}
|
|
276
|
+
this.inner.clean();
|
|
277
|
+
this.outer.clean();
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
// Updates state with provided data.
|
|
281
|
+
update(data: Uint8Array): HMAC {
|
|
282
|
+
this.inner.update(data);
|
|
283
|
+
return this;
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
// Finalizes HMAC and puts the result in out.
|
|
287
|
+
finish(out: Uint8Array): HMAC {
|
|
288
|
+
if (this.outer.finished) {
|
|
289
|
+
this.outer.finish(out);
|
|
290
|
+
} else {
|
|
291
|
+
this.inner.finish(out);
|
|
292
|
+
this.outer.update(out, this.digestLength).finish(out);
|
|
293
|
+
}
|
|
294
|
+
return this;
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
// Returns message authentication code.
|
|
298
|
+
digest(): Uint8Array {
|
|
299
|
+
let out = new Uint8Array(this.digestLength);
|
|
300
|
+
this.finish(out);
|
|
301
|
+
return out;
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Returns SHA256 hash of data.
|
|
306
|
+
export function hash(data: Uint8Array): Uint8Array {
|
|
307
|
+
const h = (new Hash()).update(data);
|
|
308
|
+
const digest = h.digest();
|
|
309
|
+
h.clean();
|
|
310
|
+
return digest;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
export function hashString(data: string): string {
|
|
314
|
+
return toHex(hash(new TextEncoder().encode(data)));
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Returns HMAC-SHA256 of data under the key.
|
|
318
|
+
export function hmac(key: Uint8Array, data: Uint8Array): Uint8Array {
|
|
319
|
+
const h = (new HMAC(key)).update(data);
|
|
320
|
+
const digest = h.digest();
|
|
321
|
+
h.clean();
|
|
322
|
+
return digest;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
export function toHex(byteArray: Uint8Array): string {
|
|
326
|
+
let acc = '';
|
|
327
|
+
for (let i = 0; i < byteArray.length; i++) {
|
|
328
|
+
let val = byteArray[i];
|
|
329
|
+
acc += ('0' + val.toString(16)).slice(-2);
|
|
330
|
+
}
|
|
331
|
+
return acc;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export function hmacString(key: string, data: string): string {
|
|
335
|
+
const encoder = new TextEncoder();
|
|
336
|
+
const result = hmac(encoder.encode(key), encoder.encode(data));
|
|
337
|
+
return toHex(result);
|
|
338
|
+
}
|