馃 distributed transcription service thistle.dunkirk.sh
1/** 2 * Pure JavaScript crypto implementations for non-secure contexts. 3 * Only used when crypto.subtle is unavailable (HTTP non-localhost). 4 */ 5 6/** 7 * Pure JS SHA-256 implementation. 8 */ 9export 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, 22 ]); 23 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) => (x & y) ^ (x & z) ^ (y & z); 27 const s0 = (x: number) => rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); 28 const s1 = (x: number) => rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); 29 const g0 = (x: number) => rotr(x, 7) ^ rotr(x, 18) ^ (x >>> 3); 30 const g1 = (x: number) => rotr(x, 17) ^ rotr(x, 19) ^ (x >>> 10); 31 32 // Pad message 33 const msgLen = data.length; 34 const bitLen = msgLen * 8; 35 const padLen = msgLen + 1 + ((119 - msgLen) % 64); 36 const padded = new Uint8Array(padLen + 8); 37 padded.set(data); 38 padded[msgLen] = 0x80; 39 new DataView(padded.buffer).setUint32(padLen + 4, bitLen, false); 40 41 // Initialize hash 42 let h0 = 0x6a09e667; 43 let h1 = 0xbb67ae85; 44 let h2 = 0x3c6ef372; 45 let h3 = 0xa54ff53a; 46 let h4 = 0x510e527f; 47 let h5 = 0x9b05688c; 48 let h6 = 0x1f83d9ab; 49 let h7 = 0x5be0cd19; 50 51 // Process blocks 52 const w = new Uint32Array(64); 53 for (let i = 0; i < padded.length; i += 64) { 54 const view = new DataView(padded.buffer, i, 64); 55 for (let j = 0; j < 16; j++) w[j] = view.getUint32(j * 4, false); 56 for (let j = 16; j < 64; j++) 57 w[j] = (g1(w[j - 2]) + w[j - 7] + g0(w[j - 15]) + w[j - 16]) | 0; 58 59 let a = h0, 60 b = h1, 61 c = h2, 62 d = h3, 63 e = h4, 64 f = h5, 65 g = h6, 66 h = h7; 67 68 for (let j = 0; j < 64; j++) { 69 const t1 = (h + s1(e) + ch(e, f, g) + K[j] + w[j]) | 0; 70 const t2 = (s0(a) + maj(a, b, c)) | 0; 71 h = g; 72 g = f; 73 f = e; 74 e = (d + t1) | 0; 75 d = c; 76 c = b; 77 b = a; 78 a = (t1 + t2) | 0; 79 } 80 81 h0 = (h0 + a) | 0; 82 h1 = (h1 + b) | 0; 83 h2 = (h2 + c) | 0; 84 h3 = (h3 + d) | 0; 85 h4 = (h4 + e) | 0; 86 h5 = (h5 + f) | 0; 87 h6 = (h6 + g) | 0; 88 h7 = (h7 + h) | 0; 89 } 90 91 const result = new Uint8Array(32); 92 const view = new DataView(result.buffer); 93 view.setUint32(0, h0, false); 94 view.setUint32(4, h1, false); 95 view.setUint32(8, h2, false); 96 view.setUint32(12, h3, false); 97 view.setUint32(16, h4, false); 98 view.setUint32(20, h5, false); 99 view.setUint32(24, h6, false); 100 view.setUint32(28, h7, false); 101 102 return result; 103} 104 105/** 106 * HMAC-SHA256 using pure JS SHA-256. 107 */ 108async function hmac(key: Uint8Array, data: Uint8Array): Promise<Uint8Array> { 109 const blockSize = 64; 110 const opad = new Uint8Array(blockSize).fill(0x5c); 111 const ipad = new Uint8Array(blockSize).fill(0x36); 112 113 if (key.length > blockSize) { 114 key = await sha256(key); 115 } 116 117 const keyPadded = new Uint8Array(blockSize); 118 keyPadded.set(key); 119 120 for (let i = 0; i < blockSize; i++) { 121 opad[i] ^= keyPadded[i]; 122 ipad[i] ^= keyPadded[i]; 123 } 124 125 const inner = new Uint8Array(blockSize + data.length); 126 inner.set(ipad); 127 inner.set(data, blockSize); 128 129 const innerHash = await sha256(inner); 130 131 const outer = new Uint8Array(blockSize + 32); 132 outer.set(opad); 133 outer.set(innerHash, blockSize); 134 135 return sha256(outer); 136} 137 138/** 139 * Pure JS PBKDF2-HMAC-SHA256 implementation. 140 */ 141export async function pbkdf2Fallback( 142 password: Uint8Array, 143 salt: Uint8Array, 144 iterations: number, 145): Promise<Uint8Array> { 146 const dkLen = 32; // 256 bits 147 const hLen = 32; // SHA-256 output length 148 const l = Math.ceil(dkLen / hLen); 149 const r = dkLen - (l - 1) * hLen; 150 151 const dk = new Uint8Array(dkLen); 152 153 for (let i = 1; i <= l; i++) { 154 const saltInt = new Uint8Array(salt.length + 4); 155 saltInt.set(salt); 156 new DataView(saltInt.buffer).setUint32(salt.length, i, false); 157 158 let u = await hmac(password, saltInt); 159 const t = new Uint8Array(u); 160 161 for (let j = 1; j < iterations; j++) { 162 u = await hmac(password, u); 163 for (let k = 0; k < hLen; k++) { 164 t[k] ^= u[k]; 165 } 166 } 167 168 const offset = (i - 1) * hLen; 169 const len = i === l ? r : hLen; 170 dk.set(t.subarray(0, len), offset); 171 } 172 173 return dk; 174}