|
const encoder = new TextEncoder(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
export function sha256(data) { |
|
if (!key[0]) precompute(); |
|
|
|
const out = init.slice(0); |
|
const array = encode(data); |
|
|
|
for (let i = 0; i < array.length; i += 16) { |
|
const w = array.subarray(i, i + 16); |
|
|
|
let tmp; |
|
let a; |
|
let b; |
|
|
|
let out0 = out[0]; |
|
let out1 = out[1]; |
|
let out2 = out[2]; |
|
let out3 = out[3]; |
|
let out4 = out[4]; |
|
let out5 = out[5]; |
|
let out6 = out[6]; |
|
let out7 = out[7]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < 64; i++) { |
|
|
|
|
|
if (i < 16) { |
|
tmp = w[i]; |
|
} else { |
|
a = w[(i + 1) & 15]; |
|
|
|
b = w[(i + 14) & 15]; |
|
|
|
tmp = w[i & 15] = |
|
(((a >>> 7) ^ (a >>> 18) ^ (a >>> 3) ^ (a << 25) ^ (a << 14)) + |
|
((b >>> 17) ^ (b >>> 19) ^ (b >>> 10) ^ (b << 15) ^ (b << 13)) + |
|
w[i & 15] + |
|
w[(i + 9) & 15]) | |
|
0; |
|
} |
|
|
|
tmp = |
|
tmp + |
|
out7 + |
|
((out4 >>> 6) ^ (out4 >>> 11) ^ (out4 >>> 25) ^ (out4 << 26) ^ (out4 << 21) ^ (out4 << 7)) + |
|
(out6 ^ (out4 & (out5 ^ out6))) + |
|
key[i]; |
|
|
|
|
|
out7 = out6; |
|
out6 = out5; |
|
out5 = out4; |
|
|
|
out4 = (out3 + tmp) | 0; |
|
|
|
out3 = out2; |
|
out2 = out1; |
|
out1 = out0; |
|
|
|
out0 = |
|
(tmp + |
|
((out1 & out2) ^ (out3 & (out1 ^ out2))) + |
|
((out1 >>> 2) ^ |
|
(out1 >>> 13) ^ |
|
(out1 >>> 22) ^ |
|
(out1 << 30) ^ |
|
(out1 << 19) ^ |
|
(out1 << 10))) | |
|
0; |
|
} |
|
|
|
out[0] = (out[0] + out0) | 0; |
|
out[1] = (out[1] + out1) | 0; |
|
out[2] = (out[2] + out2) | 0; |
|
out[3] = (out[3] + out3) | 0; |
|
out[4] = (out[4] + out4) | 0; |
|
out[5] = (out[5] + out5) | 0; |
|
out[6] = (out[6] + out6) | 0; |
|
out[7] = (out[7] + out7) | 0; |
|
} |
|
|
|
const bytes = new Uint8Array(out.buffer); |
|
reverse_endianness(bytes); |
|
|
|
return base64(bytes); |
|
} |
|
|
|
|
|
const init = new Uint32Array(8); |
|
|
|
|
|
const key = new Uint32Array(64); |
|
|
|
|
|
function precompute() { |
|
|
|
function frac(x) { |
|
return (x - Math.floor(x)) * 0x100000000; |
|
} |
|
|
|
let prime = 2; |
|
|
|
for (let i = 0; i < 64; prime++) { |
|
let is_prime = true; |
|
|
|
for (let factor = 2; factor * factor <= prime; factor++) { |
|
if (prime % factor === 0) { |
|
is_prime = false; |
|
|
|
break; |
|
} |
|
} |
|
|
|
if (is_prime) { |
|
if (i < 8) { |
|
init[i] = frac(prime ** (1 / 2)); |
|
} |
|
|
|
key[i] = frac(prime ** (1 / 3)); |
|
|
|
i++; |
|
} |
|
} |
|
} |
|
|
|
|
|
function reverse_endianness(bytes) { |
|
for (let i = 0; i < bytes.length; i += 4) { |
|
const a = bytes[i + 0]; |
|
const b = bytes[i + 1]; |
|
const c = bytes[i + 2]; |
|
const d = bytes[i + 3]; |
|
|
|
bytes[i + 0] = d; |
|
bytes[i + 1] = c; |
|
bytes[i + 2] = b; |
|
bytes[i + 3] = a; |
|
} |
|
} |
|
|
|
|
|
function encode(str) { |
|
const encoded = encoder.encode(str); |
|
const length = encoded.length * 8; |
|
|
|
|
|
|
|
|
|
const size = 512 * Math.ceil((length + 65) / 512); |
|
const bytes = new Uint8Array(size / 8); |
|
bytes.set(encoded); |
|
|
|
|
|
bytes[encoded.length] = 0b10000000; |
|
|
|
reverse_endianness(bytes); |
|
|
|
|
|
const words = new Uint32Array(bytes.buffer); |
|
words[words.length - 2] = Math.floor(length / 0x100000000); |
|
words[words.length - 1] = length; |
|
|
|
return words; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); |
|
|
|
|
|
export function base64(bytes) { |
|
const l = bytes.length; |
|
|
|
let result = ''; |
|
let i; |
|
|
|
for (i = 2; i < l; i += 3) { |
|
result += chars[bytes[i - 2] >> 2]; |
|
result += chars[((bytes[i - 2] & 0x03) << 4) | (bytes[i - 1] >> 4)]; |
|
result += chars[((bytes[i - 1] & 0x0f) << 2) | (bytes[i] >> 6)]; |
|
result += chars[bytes[i] & 0x3f]; |
|
} |
|
|
|
if (i === l + 1) { |
|
|
|
result += chars[bytes[i - 2] >> 2]; |
|
result += chars[(bytes[i - 2] & 0x03) << 4]; |
|
result += '=='; |
|
} |
|
|
|
if (i === l) { |
|
|
|
result += chars[bytes[i - 2] >> 2]; |
|
result += chars[((bytes[i - 2] & 0x03) << 4) | (bytes[i - 1] >> 4)]; |
|
result += chars[(bytes[i - 1] & 0x0f) << 2]; |
|
result += '='; |
|
} |
|
|
|
return result; |
|
} |
|
|