···
2
+
* Pure JavaScript crypto implementations for non-secure contexts.
3
+
* Only used when crypto.subtle is unavailable (HTTP non-localhost).
7
+
* Pure JS SHA-256 implementation.
9
+
export async function sha256(data: Uint8Array): Promise<Uint8Array> {
10
+
const K = new Uint32Array([
11
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
12
+
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
13
+
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
14
+
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
15
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
16
+
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
17
+
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
18
+
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
19
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
20
+
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
21
+
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
24
+
const rotr = (x: number, n: number) => (x >>> n) | (x << (32 - n));
25
+
const ch = (x: number, y: number, z: number) => (x & y) ^ (~x & z);
26
+
const maj = (x: number, y: number, z: number) =>
27
+
(x & y) ^ (x & z) ^ (y & z);
28
+
const s0 = (x: number) => rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22);
29
+
const s1 = (x: number) => rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25);
30
+
const g0 = (x: number) => rotr(x, 7) ^ rotr(x, 18) ^ (x >>> 3);
31
+
const g1 = (x: number) => rotr(x, 17) ^ rotr(x, 19) ^ (x >>> 10);
34
+
const msgLen = data.length;
35
+
const bitLen = msgLen * 8;
36
+
const padLen = msgLen + 1 + ((119 - msgLen) % 64);
37
+
const padded = new Uint8Array(padLen + 8);
39
+
padded[msgLen] = 0x80;
40
+
new DataView(padded.buffer).setUint32(padLen + 4, bitLen, false);
43
+
let h0 = 0x6a09e667;
44
+
let h1 = 0xbb67ae85;
45
+
let h2 = 0x3c6ef372;
46
+
let h3 = 0xa54ff53a;
47
+
let h4 = 0x510e527f;
48
+
let h5 = 0x9b05688c;
49
+
let h6 = 0x1f83d9ab;
50
+
let h7 = 0x5be0cd19;
53
+
const w = new Uint32Array(64);
54
+
for (let i = 0; i < padded.length; i += 64) {
55
+
const view = new DataView(padded.buffer, i, 64);
56
+
for (let j = 0; j < 16; j++) w[j] = view.getUint32(j * 4, false);
57
+
for (let j = 16; j < 64; j++)
58
+
w[j] = (g1(w[j - 2]) + w[j - 7] + g0(w[j - 15]) + w[j - 16]) | 0;
69
+
for (let j = 0; j < 64; j++) {
70
+
const t1 = (h + s1(e) + ch(e, f, g) + K[j] + w[j]) | 0;
71
+
const t2 = (s0(a) + maj(a, b, c)) | 0;
92
+
const result = new Uint8Array(32);
93
+
const view = new DataView(result.buffer);
94
+
view.setUint32(0, h0, false);
95
+
view.setUint32(4, h1, false);
96
+
view.setUint32(8, h2, false);
97
+
view.setUint32(12, h3, false);
98
+
view.setUint32(16, h4, false);
99
+
view.setUint32(20, h5, false);
100
+
view.setUint32(24, h6, false);
101
+
view.setUint32(28, h7, false);
107
+
* HMAC-SHA256 using pure JS SHA-256.
109
+
async function hmac(key: Uint8Array, data: Uint8Array): Promise<Uint8Array> {
110
+
const blockSize = 64;
111
+
const opad = new Uint8Array(blockSize).fill(0x5c);
112
+
const ipad = new Uint8Array(blockSize).fill(0x36);
114
+
if (key.length > blockSize) {
115
+
key = await sha256(key);
118
+
const keyPadded = new Uint8Array(blockSize);
119
+
keyPadded.set(key);
121
+
for (let i = 0; i < blockSize; i++) {
122
+
opad[i] ^= keyPadded[i];
123
+
ipad[i] ^= keyPadded[i];
126
+
const inner = new Uint8Array(blockSize + data.length);
128
+
inner.set(data, blockSize);
130
+
const innerHash = await sha256(inner);
132
+
const outer = new Uint8Array(blockSize + 32);
134
+
outer.set(innerHash, blockSize);
136
+
return sha256(outer);
140
+
* Pure JS PBKDF2-HMAC-SHA256 implementation.
142
+
export async function pbkdf2Fallback(
143
+
password: Uint8Array,
145
+
iterations: number,
146
+
): Promise<Uint8Array> {
147
+
const dkLen = 32; // 256 bits
148
+
const hLen = 32; // SHA-256 output length
149
+
const l = Math.ceil(dkLen / hLen);
150
+
const r = dkLen - (l - 1) * hLen;
152
+
const dk = new Uint8Array(dkLen);
154
+
for (let i = 1; i <= l; i++) {
155
+
const saltInt = new Uint8Array(salt.length + 4);
157
+
new DataView(saltInt.buffer).setUint32(salt.length, i, false);
159
+
let u = await hmac(password, saltInt);
160
+
const t = new Uint8Array(u);
162
+
for (let j = 1; j < iterations; j++) {
163
+
u = await hmac(password, u);
164
+
for (let k = 0; k < hLen; k++) {
169
+
const offset = (i - 1) * hLen;
170
+
const len = i === l ? r : hLen;
171
+
dk.set(t.subarray(0, len), offset);