Last active
December 28, 2023 12:06
-
-
Save mlanza/b557d3e0bac4d8efdc88a21cdfd2fd9a to your computer and use it in GitHub Desktop.
Verify Supabase User in Cloudflare Worker
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const base64abc = [ | |
"A", | |
"B", | |
"C", | |
"D", | |
"E", | |
"F", | |
"G", | |
"H", | |
"I", | |
"J", | |
"K", | |
"L", | |
"M", | |
"N", | |
"O", | |
"P", | |
"Q", | |
"R", | |
"S", | |
"T", | |
"U", | |
"V", | |
"W", | |
"X", | |
"Y", | |
"Z", | |
"a", | |
"b", | |
"c", | |
"d", | |
"e", | |
"f", | |
"g", | |
"h", | |
"i", | |
"j", | |
"k", | |
"l", | |
"m", | |
"n", | |
"o", | |
"p", | |
"q", | |
"r", | |
"s", | |
"t", | |
"u", | |
"v", | |
"w", | |
"x", | |
"y", | |
"z", | |
"0", | |
"1", | |
"2", | |
"3", | |
"4", | |
"5", | |
"6", | |
"7", | |
"8", | |
"9", | |
"+", | |
"/" | |
]; | |
function encode(data) { | |
const uint8 = typeof data === "string" ? new TextEncoder().encode(data) : data instanceof Uint8Array ? data : new Uint8Array(data); | |
let result = "", i2; | |
const l2 = uint8.length; | |
for(i2 = 2; i2 < l2; i2 += 3){ | |
result += base64abc[uint8[i2 - 2] >> 2]; | |
result += base64abc[(uint8[i2 - 2] & 0x03) << 4 | uint8[i2 - 1] >> 4]; | |
result += base64abc[(uint8[i2 - 1] & 0x0f) << 2 | uint8[i2] >> 6]; | |
result += base64abc[uint8[i2] & 0x3f]; | |
} | |
if (i2 === l2 + 1) { | |
result += base64abc[uint8[i2 - 2] >> 2]; | |
result += base64abc[(uint8[i2 - 2] & 0x03) << 4]; | |
result += "=="; | |
} | |
if (i2 === l2) { | |
result += base64abc[uint8[i2 - 2] >> 2]; | |
result += base64abc[(uint8[i2 - 2] & 0x03) << 4 | uint8[i2 - 1] >> 4]; | |
result += base64abc[(uint8[i2 - 1] & 0x0f) << 2]; | |
result += "="; | |
} | |
return result; | |
} | |
function decode(b64) { | |
const binString = atob(b64); | |
const size = binString.length; | |
const bytes = new Uint8Array(size); | |
for(let i3 = 0; i3 < size; i3++){ | |
bytes[i3] = binString.charCodeAt(i3); | |
} | |
return bytes; | |
} | |
function addPaddingToBase64url(base64url) { | |
if (base64url.length % 4 === 2) return base64url + "=="; | |
if (base64url.length % 4 === 3) return base64url + "="; | |
if (base64url.length % 4 === 1) { | |
throw new TypeError("Illegal base64url string!"); | |
} | |
return base64url; | |
} | |
function convertBase64urlToBase64(b64url) { | |
return addPaddingToBase64url(b64url).replace(/\-/g, "+").replace(/_/g, "/"); | |
} | |
function convertBase64ToBase64url(b64) { | |
return b64.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_"); | |
} | |
function encode1(uint8) { | |
return convertBase64ToBase64url(encode(uint8)); | |
} | |
function decode1(b64url) { | |
return decode(convertBase64urlToBase64(b64url)); | |
} | |
const mod = { | |
addPaddingToBase64url: addPaddingToBase64url, | |
encode: encode1, | |
decode: decode1 | |
}; | |
const hexTable = new TextEncoder().encode("0123456789abcdef"); | |
function errInvalidByte(__byte) { | |
return new Error("encoding/hex: invalid byte: " + new TextDecoder().decode(new Uint8Array([ | |
__byte | |
]))); | |
} | |
function errLength() { | |
return new Error("encoding/hex: odd length hex string"); | |
} | |
function fromHexChar(__byte) { | |
if (48 <= __byte && __byte <= 57) return __byte - 48; | |
if (97 <= __byte && __byte <= 102) return __byte - 97 + 10; | |
if (65 <= __byte && __byte <= 70) return __byte - 65 + 10; | |
throw errInvalidByte(__byte); | |
} | |
function encodedLen(n) { | |
return n * 2; | |
} | |
function encode2(src) { | |
const dst = new Uint8Array(encodedLen(src.length)); | |
for(let i4 = 0; i4 < dst.length; i4++){ | |
const v = src[i4]; | |
dst[i4 * 2] = hexTable[v >> 4]; | |
dst[i4 * 2 + 1] = hexTable[v & 0x0f]; | |
} | |
return dst; | |
} | |
function encodeToString(src) { | |
return new TextDecoder().decode(encode2(src)); | |
} | |
function decode2(src) { | |
const dst = new Uint8Array(decodedLen(src.length)); | |
for(let i5 = 0; i5 < dst.length; i5++){ | |
const a = fromHexChar(src[i5 * 2]); | |
const b = fromHexChar(src[i5 * 2 + 1]); | |
dst[i5] = a << 4 | b; | |
} | |
if (src.length % 2 == 1) { | |
fromHexChar(src[dst.length * 2]); | |
throw errLength(); | |
} | |
return dst; | |
} | |
function decodedLen(x) { | |
return x >>> 1; | |
} | |
function decodeString(s) { | |
return decode2(new TextEncoder().encode(s)); | |
} | |
const HEX_CHARS = "0123456789abcdef".split(""); | |
const EXTRA = [ | |
-2147483648, | |
8388608, | |
32768, | |
128 | |
]; | |
const SHIFT = [ | |
24, | |
16, | |
8, | |
0 | |
]; | |
const K = [ | |
0x428a2f98, | |
0x71374491, | |
0xb5c0fbcf, | |
0xe9b5dba5, | |
0x3956c25b, | |
0x59f111f1, | |
0x923f82a4, | |
0xab1c5ed5, | |
0xd807aa98, | |
0x12835b01, | |
0x243185be, | |
0x550c7dc3, | |
0x72be5d74, | |
0x80deb1fe, | |
0x9bdc06a7, | |
0xc19bf174, | |
0xe49b69c1, | |
0xefbe4786, | |
0x0fc19dc6, | |
0x240ca1cc, | |
0x2de92c6f, | |
0x4a7484aa, | |
0x5cb0a9dc, | |
0x76f988da, | |
0x983e5152, | |
0xa831c66d, | |
0xb00327c8, | |
0xbf597fc7, | |
0xc6e00bf3, | |
0xd5a79147, | |
0x06ca6351, | |
0x14292967, | |
0x27b70a85, | |
0x2e1b2138, | |
0x4d2c6dfc, | |
0x53380d13, | |
0x650a7354, | |
0x766a0abb, | |
0x81c2c92e, | |
0x92722c85, | |
0xa2bfe8a1, | |
0xa81a664b, | |
0xc24b8b70, | |
0xc76c51a3, | |
0xd192e819, | |
0xd6990624, | |
0xf40e3585, | |
0x106aa070, | |
0x19a4c116, | |
0x1e376c08, | |
0x2748774c, | |
0x34b0bcb5, | |
0x391c0cb3, | |
0x4ed8aa4a, | |
0x5b9cca4f, | |
0x682e6ff3, | |
0x748f82ee, | |
0x78a5636f, | |
0x84c87814, | |
0x8cc70208, | |
0x90befffa, | |
0xa4506ceb, | |
0xbef9a3f7, | |
0xc67178f2, | |
]; | |
const blocks = []; | |
class Sha256 { | |
#block; | |
#blocks; | |
#bytes; | |
#finalized; | |
#first; | |
#h0; | |
#h1; | |
#h2; | |
#h3; | |
#h4; | |
#h5; | |
#h6; | |
#h7; | |
#hashed; | |
#hBytes; | |
#is224; | |
#lastByteIndex = 0; | |
#start; | |
constructor(is224 = false, sharedMemory = false){ | |
this.init(is224, sharedMemory); | |
} | |
init(is224, sharedMemory) { | |
if (sharedMemory) { | |
blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] = blocks[4] = blocks[5] = blocks[6] = blocks[7] = blocks[8] = blocks[9] = blocks[10] = blocks[11] = blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0; | |
this.#blocks = blocks; | |
} else { | |
this.#blocks = [ | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0 | |
]; | |
} | |
if (is224) { | |
this.#h0 = 0xc1059ed8; | |
this.#h1 = 0x367cd507; | |
this.#h2 = 0x3070dd17; | |
this.#h3 = 0xf70e5939; | |
this.#h4 = 0xffc00b31; | |
this.#h5 = 0x68581511; | |
this.#h6 = 0x64f98fa7; | |
this.#h7 = 0xbefa4fa4; | |
} else { | |
this.#h0 = 0x6a09e667; | |
this.#h1 = 0xbb67ae85; | |
this.#h2 = 0x3c6ef372; | |
this.#h3 = 0xa54ff53a; | |
this.#h4 = 0x510e527f; | |
this.#h5 = 0x9b05688c; | |
this.#h6 = 0x1f83d9ab; | |
this.#h7 = 0x5be0cd19; | |
} | |
this.#block = this.#start = this.#bytes = this.#hBytes = 0; | |
this.#finalized = this.#hashed = false; | |
this.#first = true; | |
this.#is224 = is224; | |
} | |
update(message) { | |
if (this.#finalized) { | |
return this; | |
} | |
let msg; | |
if (message instanceof ArrayBuffer) { | |
msg = new Uint8Array(message); | |
} else { | |
msg = message; | |
} | |
let index = 0; | |
const length = msg.length; | |
const blocks1 = this.#blocks; | |
while(index < length){ | |
let i6; | |
if (this.#hashed) { | |
this.#hashed = false; | |
blocks1[0] = this.#block; | |
blocks1[16] = blocks1[1] = blocks1[2] = blocks1[3] = blocks1[4] = blocks1[5] = blocks1[6] = blocks1[7] = blocks1[8] = blocks1[9] = blocks1[10] = blocks1[11] = blocks1[12] = blocks1[13] = blocks1[14] = blocks1[15] = 0; | |
} | |
if (typeof msg !== "string") { | |
for(i6 = this.#start; index < length && i6 < 64; ++index){ | |
blocks1[i6 >> 2] |= msg[index] << SHIFT[(i6++) & 3]; | |
} | |
} else { | |
for(i6 = this.#start; index < length && i6 < 64; ++index){ | |
let code2 = msg.charCodeAt(index); | |
if (code2 < 0x80) { | |
blocks1[i6 >> 2] |= code2 << SHIFT[(i6++) & 3]; | |
} else if (code2 < 0x800) { | |
blocks1[i6 >> 2] |= (0xc0 | code2 >> 6) << SHIFT[(i6++) & 3]; | |
blocks1[i6 >> 2] |= (0x80 | code2 & 0x3f) << SHIFT[(i6++) & 3]; | |
} else if (code2 < 0xd800 || code2 >= 0xe000) { | |
blocks1[i6 >> 2] |= (0xe0 | code2 >> 12) << SHIFT[(i6++) & 3]; | |
blocks1[i6 >> 2] |= (0x80 | code2 >> 6 & 0x3f) << SHIFT[(i6++) & 3]; | |
blocks1[i6 >> 2] |= (0x80 | code2 & 0x3f) << SHIFT[(i6++) & 3]; | |
} else { | |
code2 = 0x10000 + ((code2 & 0x3ff) << 10 | msg.charCodeAt(++index) & 0x3ff); | |
blocks1[i6 >> 2] |= (0xf0 | code2 >> 18) << SHIFT[(i6++) & 3]; | |
blocks1[i6 >> 2] |= (0x80 | code2 >> 12 & 0x3f) << SHIFT[(i6++) & 3]; | |
blocks1[i6 >> 2] |= (0x80 | code2 >> 6 & 0x3f) << SHIFT[(i6++) & 3]; | |
blocks1[i6 >> 2] |= (0x80 | code2 & 0x3f) << SHIFT[(i6++) & 3]; | |
} | |
} | |
} | |
this.#lastByteIndex = i6; | |
this.#bytes += i6 - this.#start; | |
if (i6 >= 64) { | |
this.#block = blocks1[16]; | |
this.#start = i6 - 64; | |
this.hash(); | |
this.#hashed = true; | |
} else { | |
this.#start = i6; | |
} | |
} | |
if (this.#bytes > 4294967295) { | |
this.#hBytes += this.#bytes / 4294967296 << 0; | |
this.#bytes = this.#bytes % 4294967296; | |
} | |
return this; | |
} | |
finalize() { | |
if (this.#finalized) { | |
return; | |
} | |
this.#finalized = true; | |
const blocks2 = this.#blocks; | |
const i7 = this.#lastByteIndex; | |
blocks2[16] = this.#block; | |
blocks2[i7 >> 2] |= EXTRA[i7 & 3]; | |
this.#block = blocks2[16]; | |
if (i7 >= 56) { | |
if (!this.#hashed) { | |
this.hash(); | |
} | |
blocks2[0] = this.#block; | |
blocks2[16] = blocks2[1] = blocks2[2] = blocks2[3] = blocks2[4] = blocks2[5] = blocks2[6] = blocks2[7] = blocks2[8] = blocks2[9] = blocks2[10] = blocks2[11] = blocks2[12] = blocks2[13] = blocks2[14] = blocks2[15] = 0; | |
} | |
blocks2[14] = this.#hBytes << 3 | this.#bytes >>> 29; | |
blocks2[15] = this.#bytes << 3; | |
this.hash(); | |
} | |
hash() { | |
let a = this.#h0; | |
let b = this.#h1; | |
let c = this.#h2; | |
let d = this.#h3; | |
let e = this.#h4; | |
let f = this.#h5; | |
let g = this.#h6; | |
let h = this.#h7; | |
const blocks3 = this.#blocks; | |
let s0; | |
let s1; | |
let maj; | |
let t1; | |
let t2; | |
let ch; | |
let ab; | |
let da; | |
let cd; | |
let bc; | |
for(let j = 16; j < 64; ++j){ | |
t1 = blocks3[j - 15]; | |
s0 = (t1 >>> 7 | t1 << 25) ^ (t1 >>> 18 | t1 << 14) ^ t1 >>> 3; | |
t1 = blocks3[j - 2]; | |
s1 = (t1 >>> 17 | t1 << 15) ^ (t1 >>> 19 | t1 << 13) ^ t1 >>> 10; | |
blocks3[j] = blocks3[j - 16] + s0 + blocks3[j - 7] + s1 << 0; | |
} | |
bc = b & c; | |
for(let j1 = 0; j1 < 64; j1 += 4){ | |
if (this.#first) { | |
if (this.#is224) { | |
ab = 300032; | |
t1 = blocks3[0] - 1413257819; | |
h = t1 - 150054599 << 0; | |
d = t1 + 24177077 << 0; | |
} else { | |
ab = 704751109; | |
t1 = blocks3[0] - 210244248; | |
h = t1 - 1521486534 << 0; | |
d = t1 + 143694565 << 0; | |
} | |
this.#first = false; | |
} else { | |
s0 = (a >>> 2 | a << 30) ^ (a >>> 13 | a << 19) ^ (a >>> 22 | a << 10); | |
s1 = (e >>> 6 | e << 26) ^ (e >>> 11 | e << 21) ^ (e >>> 25 | e << 7); | |
ab = a & b; | |
maj = ab ^ a & c ^ bc; | |
ch = e & f ^ ~e & g; | |
t1 = h + s1 + ch + K[j1] + blocks3[j1]; | |
t2 = s0 + maj; | |
h = d + t1 << 0; | |
d = t1 + t2 << 0; | |
} | |
s0 = (d >>> 2 | d << 30) ^ (d >>> 13 | d << 19) ^ (d >>> 22 | d << 10); | |
s1 = (h >>> 6 | h << 26) ^ (h >>> 11 | h << 21) ^ (h >>> 25 | h << 7); | |
da = d & a; | |
maj = da ^ d & b ^ ab; | |
ch = h & e ^ ~h & f; | |
t1 = g + s1 + ch + K[j1 + 1] + blocks3[j1 + 1]; | |
t2 = s0 + maj; | |
g = c + t1 << 0; | |
c = t1 + t2 << 0; | |
s0 = (c >>> 2 | c << 30) ^ (c >>> 13 | c << 19) ^ (c >>> 22 | c << 10); | |
s1 = (g >>> 6 | g << 26) ^ (g >>> 11 | g << 21) ^ (g >>> 25 | g << 7); | |
cd = c & d; | |
maj = cd ^ c & a ^ da; | |
ch = g & h ^ ~g & e; | |
t1 = f + s1 + ch + K[j1 + 2] + blocks3[j1 + 2]; | |
t2 = s0 + maj; | |
f = b + t1 << 0; | |
b = t1 + t2 << 0; | |
s0 = (b >>> 2 | b << 30) ^ (b >>> 13 | b << 19) ^ (b >>> 22 | b << 10); | |
s1 = (f >>> 6 | f << 26) ^ (f >>> 11 | f << 21) ^ (f >>> 25 | f << 7); | |
bc = b & c; | |
maj = bc ^ b & d ^ cd; | |
ch = f & g ^ ~f & h; | |
t1 = e + s1 + ch + K[j1 + 3] + blocks3[j1 + 3]; | |
t2 = s0 + maj; | |
e = a + t1 << 0; | |
a = t1 + t2 << 0; | |
} | |
this.#h0 = this.#h0 + a << 0; | |
this.#h1 = this.#h1 + b << 0; | |
this.#h2 = this.#h2 + c << 0; | |
this.#h3 = this.#h3 + d << 0; | |
this.#h4 = this.#h4 + e << 0; | |
this.#h5 = this.#h5 + f << 0; | |
this.#h6 = this.#h6 + g << 0; | |
this.#h7 = this.#h7 + h << 0; | |
} | |
hex() { | |
this.finalize(); | |
const h0 = this.#h0; | |
const h1 = this.#h1; | |
const h2 = this.#h2; | |
const h3 = this.#h3; | |
const h4 = this.#h4; | |
const h5 = this.#h5; | |
const h6 = this.#h6; | |
const h7 = this.#h7; | |
let hex = HEX_CHARS[h0 >> 28 & 0x0f] + HEX_CHARS[h0 >> 24 & 0x0f] + HEX_CHARS[h0 >> 20 & 0x0f] + HEX_CHARS[h0 >> 16 & 0x0f] + HEX_CHARS[h0 >> 12 & 0x0f] + HEX_CHARS[h0 >> 8 & 0x0f] + HEX_CHARS[h0 >> 4 & 0x0f] + HEX_CHARS[h0 & 0x0f] + HEX_CHARS[h1 >> 28 & 0x0f] + HEX_CHARS[h1 >> 24 & 0x0f] + HEX_CHARS[h1 >> 20 & 0x0f] + HEX_CHARS[h1 >> 16 & 0x0f] + HEX_CHARS[h1 >> 12 & 0x0f] + HEX_CHARS[h1 >> 8 & 0x0f] + HEX_CHARS[h1 >> 4 & 0x0f] + HEX_CHARS[h1 & 0x0f] + HEX_CHARS[h2 >> 28 & 0x0f] + HEX_CHARS[h2 >> 24 & 0x0f] + HEX_CHARS[h2 >> 20 & 0x0f] + HEX_CHARS[h2 >> 16 & 0x0f] + HEX_CHARS[h2 >> 12 & 0x0f] + HEX_CHARS[h2 >> 8 & 0x0f] + HEX_CHARS[h2 >> 4 & 0x0f] + HEX_CHARS[h2 & 0x0f] + HEX_CHARS[h3 >> 28 & 0x0f] + HEX_CHARS[h3 >> 24 & 0x0f] + HEX_CHARS[h3 >> 20 & 0x0f] + HEX_CHARS[h3 >> 16 & 0x0f] + HEX_CHARS[h3 >> 12 & 0x0f] + HEX_CHARS[h3 >> 8 & 0x0f] + HEX_CHARS[h3 >> 4 & 0x0f] + HEX_CHARS[h3 & 0x0f] + HEX_CHARS[h4 >> 28 & 0x0f] + HEX_CHARS[h4 >> 24 & 0x0f] + HEX_CHARS[h4 >> 20 & 0x0f] + HEX_CHARS[h4 >> 16 & 0x0f] + HEX_CHARS[h4 >> 12 & 0x0f] + HEX_CHARS[h4 >> 8 & 0x0f] + HEX_CHARS[h4 >> 4 & 0x0f] + HEX_CHARS[h4 & 0x0f] + HEX_CHARS[h5 >> 28 & 0x0f] + HEX_CHARS[h5 >> 24 & 0x0f] + HEX_CHARS[h5 >> 20 & 0x0f] + HEX_CHARS[h5 >> 16 & 0x0f] + HEX_CHARS[h5 >> 12 & 0x0f] + HEX_CHARS[h5 >> 8 & 0x0f] + HEX_CHARS[h5 >> 4 & 0x0f] + HEX_CHARS[h5 & 0x0f] + HEX_CHARS[h6 >> 28 & 0x0f] + HEX_CHARS[h6 >> 24 & 0x0f] + HEX_CHARS[h6 >> 20 & 0x0f] + HEX_CHARS[h6 >> 16 & 0x0f] + HEX_CHARS[h6 >> 12 & 0x0f] + HEX_CHARS[h6 >> 8 & 0x0f] + HEX_CHARS[h6 >> 4 & 0x0f] + HEX_CHARS[h6 & 0x0f]; | |
if (!this.#is224) { | |
hex += HEX_CHARS[h7 >> 28 & 0x0f] + HEX_CHARS[h7 >> 24 & 0x0f] + HEX_CHARS[h7 >> 20 & 0x0f] + HEX_CHARS[h7 >> 16 & 0x0f] + HEX_CHARS[h7 >> 12 & 0x0f] + HEX_CHARS[h7 >> 8 & 0x0f] + HEX_CHARS[h7 >> 4 & 0x0f] + HEX_CHARS[h7 & 0x0f]; | |
} | |
return hex; | |
} | |
toString() { | |
return this.hex(); | |
} | |
digest() { | |
this.finalize(); | |
const h0 = this.#h0; | |
const h1 = this.#h1; | |
const h2 = this.#h2; | |
const h3 = this.#h3; | |
const h4 = this.#h4; | |
const h5 = this.#h5; | |
const h6 = this.#h6; | |
const h7 = this.#h7; | |
const arr = [ | |
h0 >> 24 & 0xff, | |
h0 >> 16 & 0xff, | |
h0 >> 8 & 0xff, | |
h0 & 0xff, | |
h1 >> 24 & 0xff, | |
h1 >> 16 & 0xff, | |
h1 >> 8 & 0xff, | |
h1 & 0xff, | |
h2 >> 24 & 0xff, | |
h2 >> 16 & 0xff, | |
h2 >> 8 & 0xff, | |
h2 & 0xff, | |
h3 >> 24 & 0xff, | |
h3 >> 16 & 0xff, | |
h3 >> 8 & 0xff, | |
h3 & 0xff, | |
h4 >> 24 & 0xff, | |
h4 >> 16 & 0xff, | |
h4 >> 8 & 0xff, | |
h4 & 0xff, | |
h5 >> 24 & 0xff, | |
h5 >> 16 & 0xff, | |
h5 >> 8 & 0xff, | |
h5 & 0xff, | |
h6 >> 24 & 0xff, | |
h6 >> 16 & 0xff, | |
h6 >> 8 & 0xff, | |
h6 & 0xff, | |
]; | |
if (!this.#is224) { | |
arr.push(h7 >> 24 & 0xff, h7 >> 16 & 0xff, h7 >> 8 & 0xff, h7 & 0xff); | |
} | |
return arr; | |
} | |
array() { | |
return this.digest(); | |
} | |
arrayBuffer() { | |
this.finalize(); | |
const buffer = new ArrayBuffer(this.#is224 ? 28 : 32); | |
const dataView = new DataView(buffer); | |
dataView.setUint32(0, this.#h0); | |
dataView.setUint32(4, this.#h1); | |
dataView.setUint32(8, this.#h2); | |
dataView.setUint32(12, this.#h3); | |
dataView.setUint32(16, this.#h4); | |
dataView.setUint32(20, this.#h5); | |
dataView.setUint32(24, this.#h6); | |
if (!this.#is224) { | |
dataView.setUint32(28, this.#h7); | |
} | |
return buffer; | |
} | |
} | |
class HmacSha256 extends Sha256 { | |
#inner; | |
#is224; | |
#oKeyPad; | |
#sharedMemory; | |
constructor(secretKey, is224 = false, sharedMemory = false){ | |
super(is224, sharedMemory); | |
let key; | |
if (typeof secretKey === "string") { | |
const bytes = []; | |
const length = secretKey.length; | |
let index = 0; | |
for(let i8 = 0; i8 < length; ++i8){ | |
let code3 = secretKey.charCodeAt(i8); | |
if (code3 < 0x80) { | |
bytes[index++] = code3; | |
} else if (code3 < 0x800) { | |
bytes[index++] = 0xc0 | code3 >> 6; | |
bytes[index++] = 0x80 | code3 & 0x3f; | |
} else if (code3 < 0xd800 || code3 >= 0xe000) { | |
bytes[index++] = 0xe0 | code3 >> 12; | |
bytes[index++] = 0x80 | code3 >> 6 & 0x3f; | |
bytes[index++] = 0x80 | code3 & 0x3f; | |
} else { | |
code3 = 0x10000 + ((code3 & 0x3ff) << 10 | secretKey.charCodeAt(++i8) & 0x3ff); | |
bytes[index++] = 0xf0 | code3 >> 18; | |
bytes[index++] = 0x80 | code3 >> 12 & 0x3f; | |
bytes[index++] = 0x80 | code3 >> 6 & 0x3f; | |
bytes[index++] = 0x80 | code3 & 0x3f; | |
} | |
} | |
key = bytes; | |
} else { | |
if (secretKey instanceof ArrayBuffer) { | |
key = new Uint8Array(secretKey); | |
} else { | |
key = secretKey; | |
} | |
} | |
if (key.length > 64) { | |
key = new Sha256(is224, true).update(key).array(); | |
} | |
const oKeyPad = []; | |
const iKeyPad = []; | |
for(let i9 = 0; i9 < 64; ++i9){ | |
const b = key[i9] || 0; | |
oKeyPad[i9] = 0x5c ^ b; | |
iKeyPad[i9] = 0x36 ^ b; | |
} | |
this.update(iKeyPad); | |
this.#oKeyPad = oKeyPad; | |
this.#inner = true; | |
this.#is224 = is224; | |
this.#sharedMemory = sharedMemory; | |
} | |
finalize() { | |
super.finalize(); | |
if (this.#inner) { | |
this.#inner = false; | |
const innerHash = this.array(); | |
super.init(this.#is224, this.#sharedMemory); | |
this.update(this.#oKeyPad); | |
this.update(innerHash); | |
super.finalize(); | |
} | |
} | |
} | |
const HEX_CHARS1 = [ | |
"0", | |
"1", | |
"2", | |
"3", | |
"4", | |
"5", | |
"6", | |
"7", | |
"8", | |
"9", | |
"a", | |
"b", | |
"c", | |
"d", | |
"e", | |
"f" | |
]; | |
const EXTRA1 = [ | |
-2147483648, | |
8388608, | |
32768, | |
128 | |
]; | |
const SHIFT1 = [ | |
24, | |
16, | |
8, | |
0 | |
]; | |
const K1 = [ | |
0x428a2f98, | |
0xd728ae22, | |
0x71374491, | |
0x23ef65cd, | |
0xb5c0fbcf, | |
0xec4d3b2f, | |
0xe9b5dba5, | |
0x8189dbbc, | |
0x3956c25b, | |
0xf348b538, | |
0x59f111f1, | |
0xb605d019, | |
0x923f82a4, | |
0xaf194f9b, | |
0xab1c5ed5, | |
0xda6d8118, | |
0xd807aa98, | |
0xa3030242, | |
0x12835b01, | |
0x45706fbe, | |
0x243185be, | |
0x4ee4b28c, | |
0x550c7dc3, | |
0xd5ffb4e2, | |
0x72be5d74, | |
0xf27b896f, | |
0x80deb1fe, | |
0x3b1696b1, | |
0x9bdc06a7, | |
0x25c71235, | |
0xc19bf174, | |
0xcf692694, | |
0xe49b69c1, | |
0x9ef14ad2, | |
0xefbe4786, | |
0x384f25e3, | |
0x0fc19dc6, | |
0x8b8cd5b5, | |
0x240ca1cc, | |
0x77ac9c65, | |
0x2de92c6f, | |
0x592b0275, | |
0x4a7484aa, | |
0x6ea6e483, | |
0x5cb0a9dc, | |
0xbd41fbd4, | |
0x76f988da, | |
0x831153b5, | |
0x983e5152, | |
0xee66dfab, | |
0xa831c66d, | |
0x2db43210, | |
0xb00327c8, | |
0x98fb213f, | |
0xbf597fc7, | |
0xbeef0ee4, | |
0xc6e00bf3, | |
0x3da88fc2, | |
0xd5a79147, | |
0x930aa725, | |
0x06ca6351, | |
0xe003826f, | |
0x14292967, | |
0x0a0e6e70, | |
0x27b70a85, | |
0x46d22ffc, | |
0x2e1b2138, | |
0x5c26c926, | |
0x4d2c6dfc, | |
0x5ac42aed, | |
0x53380d13, | |
0x9d95b3df, | |
0x650a7354, | |
0x8baf63de, | |
0x766a0abb, | |
0x3c77b2a8, | |
0x81c2c92e, | |
0x47edaee6, | |
0x92722c85, | |
0x1482353b, | |
0xa2bfe8a1, | |
0x4cf10364, | |
0xa81a664b, | |
0xbc423001, | |
0xc24b8b70, | |
0xd0f89791, | |
0xc76c51a3, | |
0x0654be30, | |
0xd192e819, | |
0xd6ef5218, | |
0xd6990624, | |
0x5565a910, | |
0xf40e3585, | |
0x5771202a, | |
0x106aa070, | |
0x32bbd1b8, | |
0x19a4c116, | |
0xb8d2d0c8, | |
0x1e376c08, | |
0x5141ab53, | |
0x2748774c, | |
0xdf8eeb99, | |
0x34b0bcb5, | |
0xe19b48a8, | |
0x391c0cb3, | |
0xc5c95a63, | |
0x4ed8aa4a, | |
0xe3418acb, | |
0x5b9cca4f, | |
0x7763e373, | |
0x682e6ff3, | |
0xd6b2b8a3, | |
0x748f82ee, | |
0x5defb2fc, | |
0x78a5636f, | |
0x43172f60, | |
0x84c87814, | |
0xa1f0ab72, | |
0x8cc70208, | |
0x1a6439ec, | |
0x90befffa, | |
0x23631e28, | |
0xa4506ceb, | |
0xde82bde9, | |
0xbef9a3f7, | |
0xb2c67915, | |
0xc67178f2, | |
0xe372532b, | |
0xca273ece, | |
0xea26619c, | |
0xd186b8c7, | |
0x21c0c207, | |
0xeada7dd6, | |
0xcde0eb1e, | |
0xf57d4f7f, | |
0xee6ed178, | |
0x06f067aa, | |
0x72176fba, | |
0x0a637dc5, | |
0xa2c898a6, | |
0x113f9804, | |
0xbef90dae, | |
0x1b710b35, | |
0x131c471b, | |
0x28db77f5, | |
0x23047d84, | |
0x32caab7b, | |
0x40c72493, | |
0x3c9ebe0a, | |
0x15c9bebc, | |
0x431d67c4, | |
0x9c100d4c, | |
0x4cc5d4be, | |
0xcb3e42b6, | |
0x597f299c, | |
0xfc657e2a, | |
0x5fcb6fab, | |
0x3ad6faec, | |
0x6c44198c, | |
0x4a475817 | |
]; | |
const blocks1 = []; | |
class Sha512 { | |
#blocks; | |
#block; | |
#bits; | |
#start; | |
#bytes; | |
#hBytes; | |
#lastByteIndex = 0; | |
#finalized; | |
#hashed; | |
#h0h; | |
#h0l; | |
#h1h; | |
#h1l; | |
#h2h; | |
#h2l; | |
#h3h; | |
#h3l; | |
#h4h; | |
#h4l; | |
#h5h; | |
#h5l; | |
#h6h; | |
#h6l; | |
#h7h; | |
#h7l; | |
constructor(bits = 512, sharedMemory = false){ | |
this.init(bits, sharedMemory); | |
} | |
init(bits, sharedMemory) { | |
if (sharedMemory) { | |
blocks1[0] = blocks1[1] = blocks1[2] = blocks1[3] = blocks1[4] = blocks1[5] = blocks1[6] = blocks1[7] = blocks1[8] = blocks1[9] = blocks1[10] = blocks1[11] = blocks1[12] = blocks1[13] = blocks1[14] = blocks1[15] = blocks1[16] = blocks1[17] = blocks1[18] = blocks1[19] = blocks1[20] = blocks1[21] = blocks1[22] = blocks1[23] = blocks1[24] = blocks1[25] = blocks1[26] = blocks1[27] = blocks1[28] = blocks1[29] = blocks1[30] = blocks1[31] = blocks1[32] = 0; | |
this.#blocks = blocks1; | |
} else { | |
this.#blocks = [ | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0 | |
]; | |
} | |
if (bits === 224) { | |
this.#h0h = 0x8c3d37c8; | |
this.#h0l = 0x19544da2; | |
this.#h1h = 0x73e19966; | |
this.#h1l = 0x89dcd4d6; | |
this.#h2h = 0x1dfab7ae; | |
this.#h2l = 0x32ff9c82; | |
this.#h3h = 0x679dd514; | |
this.#h3l = 0x582f9fcf; | |
this.#h4h = 0x0f6d2b69; | |
this.#h4l = 0x7bd44da8; | |
this.#h5h = 0x77e36f73; | |
this.#h5l = 0x04c48942; | |
this.#h6h = 0x3f9d85a8; | |
this.#h6l = 0x6a1d36c8; | |
this.#h7h = 0x1112e6ad; | |
this.#h7l = 0x91d692a1; | |
} else if (bits === 256) { | |
this.#h0h = 0x22312194; | |
this.#h0l = 0xfc2bf72c; | |
this.#h1h = 0x9f555fa3; | |
this.#h1l = 0xc84c64c2; | |
this.#h2h = 0x2393b86b; | |
this.#h2l = 0x6f53b151; | |
this.#h3h = 0x96387719; | |
this.#h3l = 0x5940eabd; | |
this.#h4h = 0x96283ee2; | |
this.#h4l = 0xa88effe3; | |
this.#h5h = 0xbe5e1e25; | |
this.#h5l = 0x53863992; | |
this.#h6h = 0x2b0199fc; | |
this.#h6l = 0x2c85b8aa; | |
this.#h7h = 0x0eb72ddc; | |
this.#h7l = 0x81c52ca2; | |
} else if (bits === 384) { | |
this.#h0h = 0xcbbb9d5d; | |
this.#h0l = 0xc1059ed8; | |
this.#h1h = 0x629a292a; | |
this.#h1l = 0x367cd507; | |
this.#h2h = 0x9159015a; | |
this.#h2l = 0x3070dd17; | |
this.#h3h = 0x152fecd8; | |
this.#h3l = 0xf70e5939; | |
this.#h4h = 0x67332667; | |
this.#h4l = 0xffc00b31; | |
this.#h5h = 0x8eb44a87; | |
this.#h5l = 0x68581511; | |
this.#h6h = 0xdb0c2e0d; | |
this.#h6l = 0x64f98fa7; | |
this.#h7h = 0x47b5481d; | |
this.#h7l = 0xbefa4fa4; | |
} else { | |
this.#h0h = 0x6a09e667; | |
this.#h0l = 0xf3bcc908; | |
this.#h1h = 0xbb67ae85; | |
this.#h1l = 0x84caa73b; | |
this.#h2h = 0x3c6ef372; | |
this.#h2l = 0xfe94f82b; | |
this.#h3h = 0xa54ff53a; | |
this.#h3l = 0x5f1d36f1; | |
this.#h4h = 0x510e527f; | |
this.#h4l = 0xade682d1; | |
this.#h5h = 0x9b05688c; | |
this.#h5l = 0x2b3e6c1f; | |
this.#h6h = 0x1f83d9ab; | |
this.#h6l = 0xfb41bd6b; | |
this.#h7h = 0x5be0cd19; | |
this.#h7l = 0x137e2179; | |
} | |
this.#bits = bits; | |
this.#block = this.#start = this.#bytes = this.#hBytes = 0; | |
this.#finalized = this.#hashed = false; | |
} | |
update(message) { | |
if (this.#finalized) { | |
return this; | |
} | |
let msg; | |
if (message instanceof ArrayBuffer) { | |
msg = new Uint8Array(message); | |
} else { | |
msg = message; | |
} | |
const length = msg.length; | |
const blocks11 = this.#blocks; | |
let index = 0; | |
while(index < length){ | |
let i10; | |
if (this.#hashed) { | |
this.#hashed = false; | |
blocks11[0] = this.#block; | |
blocks11[1] = blocks11[2] = blocks11[3] = blocks11[4] = blocks11[5] = blocks11[6] = blocks11[7] = blocks11[8] = blocks11[9] = blocks11[10] = blocks11[11] = blocks11[12] = blocks11[13] = blocks11[14] = blocks11[15] = blocks11[16] = blocks11[17] = blocks11[18] = blocks11[19] = blocks11[20] = blocks11[21] = blocks11[22] = blocks11[23] = blocks11[24] = blocks11[25] = blocks11[26] = blocks11[27] = blocks11[28] = blocks11[29] = blocks11[30] = blocks11[31] = blocks11[32] = 0; | |
} | |
if (typeof msg !== "string") { | |
for(i10 = this.#start; index < length && i10 < 128; ++index){ | |
blocks11[i10 >> 2] |= msg[index] << SHIFT1[(i10++) & 3]; | |
} | |
} else { | |
for(i10 = this.#start; index < length && i10 < 128; ++index){ | |
let code4 = msg.charCodeAt(index); | |
if (code4 < 0x80) { | |
blocks11[i10 >> 2] |= code4 << SHIFT1[(i10++) & 3]; | |
} else if (code4 < 0x800) { | |
blocks11[i10 >> 2] |= (0xc0 | code4 >> 6) << SHIFT1[(i10++) & 3]; | |
blocks11[i10 >> 2] |= (0x80 | code4 & 0x3f) << SHIFT1[(i10++) & 3]; | |
} else if (code4 < 0xd800 || code4 >= 0xe000) { | |
blocks11[i10 >> 2] |= (0xe0 | code4 >> 12) << SHIFT1[(i10++) & 3]; | |
blocks11[i10 >> 2] |= (0x80 | code4 >> 6 & 0x3f) << SHIFT1[(i10++) & 3]; | |
blocks11[i10 >> 2] |= (0x80 | code4 & 0x3f) << SHIFT1[(i10++) & 3]; | |
} else { | |
code4 = 0x10000 + ((code4 & 0x3ff) << 10 | msg.charCodeAt(++index) & 0x3ff); | |
blocks11[i10 >> 2] |= (0xf0 | code4 >> 18) << SHIFT1[(i10++) & 3]; | |
blocks11[i10 >> 2] |= (0x80 | code4 >> 12 & 0x3f) << SHIFT1[(i10++) & 3]; | |
blocks11[i10 >> 2] |= (0x80 | code4 >> 6 & 0x3f) << SHIFT1[(i10++) & 3]; | |
blocks11[i10 >> 2] |= (0x80 | code4 & 0x3f) << SHIFT1[(i10++) & 3]; | |
} | |
} | |
} | |
this.#lastByteIndex = i10; | |
this.#bytes += i10 - this.#start; | |
if (i10 >= 128) { | |
this.#block = blocks11[32]; | |
this.#start = i10 - 128; | |
this.hash(); | |
this.#hashed = true; | |
} else { | |
this.#start = i10; | |
} | |
} | |
if (this.#bytes > 4294967295) { | |
this.#hBytes += this.#bytes / 4294967296 << 0; | |
this.#bytes = this.#bytes % 4294967296; | |
} | |
return this; | |
} | |
finalize() { | |
if (this.#finalized) { | |
return; | |
} | |
this.#finalized = true; | |
const blocks2 = this.#blocks; | |
const i11 = this.#lastByteIndex; | |
blocks2[32] = this.#block; | |
blocks2[i11 >> 2] |= EXTRA1[i11 & 3]; | |
this.#block = blocks2[32]; | |
if (i11 >= 112) { | |
if (!this.#hashed) { | |
this.hash(); | |
} | |
blocks2[0] = this.#block; | |
blocks2[1] = blocks2[2] = blocks2[3] = blocks2[4] = blocks2[5] = blocks2[6] = blocks2[7] = blocks2[8] = blocks2[9] = blocks2[10] = blocks2[11] = blocks2[12] = blocks2[13] = blocks2[14] = blocks2[15] = blocks2[16] = blocks2[17] = blocks2[18] = blocks2[19] = blocks2[20] = blocks2[21] = blocks2[22] = blocks2[23] = blocks2[24] = blocks2[25] = blocks2[26] = blocks2[27] = blocks2[28] = blocks2[29] = blocks2[30] = blocks2[31] = blocks2[32] = 0; | |
} | |
blocks2[30] = this.#hBytes << 3 | this.#bytes >>> 29; | |
blocks2[31] = this.#bytes << 3; | |
this.hash(); | |
} | |
hash() { | |
const h0h = this.#h0h, h0l = this.#h0l, h1h = this.#h1h, h1l = this.#h1l, h2h = this.#h2h, h2l = this.#h2l, h3h = this.#h3h, h3l = this.#h3l, h4h = this.#h4h, h4l = this.#h4l, h5h = this.#h5h, h5l = this.#h5l, h6h = this.#h6h, h6l = this.#h6l, h7h = this.#h7h, h7l = this.#h7l; | |
let s0h, s0l, s1h, s1l, c1, c2, c3, c4, abh, abl, dah, dal, cdh, cdl, bch, bcl, majh, majl, t1h, t1l, t2h, t2l, chh, chl; | |
const blocks3 = this.#blocks; | |
for(let j = 32; j < 160; j += 2){ | |
t1h = blocks3[j - 30]; | |
t1l = blocks3[j - 29]; | |
s0h = (t1h >>> 1 | t1l << 31) ^ (t1h >>> 8 | t1l << 24) ^ t1h >>> 7; | |
s0l = (t1l >>> 1 | t1h << 31) ^ (t1l >>> 8 | t1h << 24) ^ (t1l >>> 7 | t1h << 25); | |
t1h = blocks3[j - 4]; | |
t1l = blocks3[j - 3]; | |
s1h = (t1h >>> 19 | t1l << 13) ^ (t1l >>> 29 | t1h << 3) ^ t1h >>> 6; | |
s1l = (t1l >>> 19 | t1h << 13) ^ (t1h >>> 29 | t1l << 3) ^ (t1l >>> 6 | t1h << 26); | |
t1h = blocks3[j - 32]; | |
t1l = blocks3[j - 31]; | |
t2h = blocks3[j - 14]; | |
t2l = blocks3[j - 13]; | |
c1 = (t2l & 0xffff) + (t1l & 0xffff) + (s0l & 0xffff) + (s1l & 0xffff); | |
c2 = (t2l >>> 16) + (t1l >>> 16) + (s0l >>> 16) + (s1l >>> 16) + (c1 >>> 16); | |
c3 = (t2h & 0xffff) + (t1h & 0xffff) + (s0h & 0xffff) + (s1h & 0xffff) + (c2 >>> 16); | |
c4 = (t2h >>> 16) + (t1h >>> 16) + (s0h >>> 16) + (s1h >>> 16) + (c3 >>> 16); | |
blocks3[j] = c4 << 16 | c3 & 0xffff; | |
blocks3[j + 1] = c2 << 16 | c1 & 0xffff; | |
} | |
let ah = h0h, al = h0l, bh = h1h, bl = h1l, ch = h2h, cl = h2l, dh = h3h, dl = h3l, eh = h4h, el = h4l, fh = h5h, fl = h5l, gh = h6h, gl = h6l, hh = h7h, hl = h7l; | |
bch = bh & ch; | |
bcl = bl & cl; | |
for(let j1 = 0; j1 < 160; j1 += 8){ | |
s0h = (ah >>> 28 | al << 4) ^ (al >>> 2 | ah << 30) ^ (al >>> 7 | ah << 25); | |
s0l = (al >>> 28 | ah << 4) ^ (ah >>> 2 | al << 30) ^ (ah >>> 7 | al << 25); | |
s1h = (eh >>> 14 | el << 18) ^ (eh >>> 18 | el << 14) ^ (el >>> 9 | eh << 23); | |
s1l = (el >>> 14 | eh << 18) ^ (el >>> 18 | eh << 14) ^ (eh >>> 9 | el << 23); | |
abh = ah & bh; | |
abl = al & bl; | |
majh = abh ^ ah & ch ^ bch; | |
majl = abl ^ al & cl ^ bcl; | |
chh = eh & fh ^ ~eh & gh; | |
chl = el & fl ^ ~el & gl; | |
t1h = blocks3[j1]; | |
t1l = blocks3[j1 + 1]; | |
t2h = K1[j1]; | |
t2l = K1[j1 + 1]; | |
c1 = (t2l & 0xffff) + (t1l & 0xffff) + (chl & 0xffff) + (s1l & 0xffff) + (hl & 0xffff); | |
c2 = (t2l >>> 16) + (t1l >>> 16) + (chl >>> 16) + (s1l >>> 16) + (hl >>> 16) + (c1 >>> 16); | |
c3 = (t2h & 0xffff) + (t1h & 0xffff) + (chh & 0xffff) + (s1h & 0xffff) + (hh & 0xffff) + (c2 >>> 16); | |
c4 = (t2h >>> 16) + (t1h >>> 16) + (chh >>> 16) + (s1h >>> 16) + (hh >>> 16) + (c3 >>> 16); | |
t1h = c4 << 16 | c3 & 0xffff; | |
t1l = c2 << 16 | c1 & 0xffff; | |
c1 = (majl & 0xffff) + (s0l & 0xffff); | |
c2 = (majl >>> 16) + (s0l >>> 16) + (c1 >>> 16); | |
c3 = (majh & 0xffff) + (s0h & 0xffff) + (c2 >>> 16); | |
c4 = (majh >>> 16) + (s0h >>> 16) + (c3 >>> 16); | |
t2h = c4 << 16 | c3 & 0xffff; | |
t2l = c2 << 16 | c1 & 0xffff; | |
c1 = (dl & 0xffff) + (t1l & 0xffff); | |
c2 = (dl >>> 16) + (t1l >>> 16) + (c1 >>> 16); | |
c3 = (dh & 0xffff) + (t1h & 0xffff) + (c2 >>> 16); | |
c4 = (dh >>> 16) + (t1h >>> 16) + (c3 >>> 16); | |
hh = c4 << 16 | c3 & 0xffff; | |
hl = c2 << 16 | c1 & 0xffff; | |
c1 = (t2l & 0xffff) + (t1l & 0xffff); | |
c2 = (t2l >>> 16) + (t1l >>> 16) + (c1 >>> 16); | |
c3 = (t2h & 0xffff) + (t1h & 0xffff) + (c2 >>> 16); | |
c4 = (t2h >>> 16) + (t1h >>> 16) + (c3 >>> 16); | |
dh = c4 << 16 | c3 & 0xffff; | |
dl = c2 << 16 | c1 & 0xffff; | |
s0h = (dh >>> 28 | dl << 4) ^ (dl >>> 2 | dh << 30) ^ (dl >>> 7 | dh << 25); | |
s0l = (dl >>> 28 | dh << 4) ^ (dh >>> 2 | dl << 30) ^ (dh >>> 7 | dl << 25); | |
s1h = (hh >>> 14 | hl << 18) ^ (hh >>> 18 | hl << 14) ^ (hl >>> 9 | hh << 23); | |
s1l = (hl >>> 14 | hh << 18) ^ (hl >>> 18 | hh << 14) ^ (hh >>> 9 | hl << 23); | |
dah = dh & ah; | |
dal = dl & al; | |
majh = dah ^ dh & bh ^ abh; | |
majl = dal ^ dl & bl ^ abl; | |
chh = hh & eh ^ ~hh & fh; | |
chl = hl & el ^ ~hl & fl; | |
t1h = blocks3[j1 + 2]; | |
t1l = blocks3[j1 + 3]; | |
t2h = K1[j1 + 2]; | |
t2l = K1[j1 + 3]; | |
c1 = (t2l & 0xffff) + (t1l & 0xffff) + (chl & 0xffff) + (s1l & 0xffff) + (gl & 0xffff); | |
c2 = (t2l >>> 16) + (t1l >>> 16) + (chl >>> 16) + (s1l >>> 16) + (gl >>> 16) + (c1 >>> 16); | |
c3 = (t2h & 0xffff) + (t1h & 0xffff) + (chh & 0xffff) + (s1h & 0xffff) + (gh & 0xffff) + (c2 >>> 16); | |
c4 = (t2h >>> 16) + (t1h >>> 16) + (chh >>> 16) + (s1h >>> 16) + (gh >>> 16) + (c3 >>> 16); | |
t1h = c4 << 16 | c3 & 0xffff; | |
t1l = c2 << 16 | c1 & 0xffff; | |
c1 = (majl & 0xffff) + (s0l & 0xffff); | |
c2 = (majl >>> 16) + (s0l >>> 16) + (c1 >>> 16); | |
c3 = (majh & 0xffff) + (s0h & 0xffff) + (c2 >>> 16); | |
c4 = (majh >>> 16) + (s0h >>> 16) + (c3 >>> 16); | |
t2h = c4 << 16 | c3 & 0xffff; | |
t2l = c2 << 16 | c1 & 0xffff; | |
c1 = (cl & 0xffff) + (t1l & 0xffff); | |
c2 = (cl >>> 16) + (t1l >>> 16) + (c1 >>> 16); | |
c3 = (ch & 0xffff) + (t1h & 0xffff) + (c2 >>> 16); | |
c4 = (ch >>> 16) + (t1h >>> 16) + (c3 >>> 16); | |
gh = c4 << 16 | c3 & 0xffff; | |
gl = c2 << 16 | c1 & 0xffff; | |
c1 = (t2l & 0xffff) + (t1l & 0xffff); | |
c2 = (t2l >>> 16) + (t1l >>> 16) + (c1 >>> 16); | |
c3 = (t2h & 0xffff) + (t1h & 0xffff) + (c2 >>> 16); | |
c4 = (t2h >>> 16) + (t1h >>> 16) + (c3 >>> 16); | |
ch = c4 << 16 | c3 & 0xffff; | |
cl = c2 << 16 | c1 & 0xffff; | |
s0h = (ch >>> 28 | cl << 4) ^ (cl >>> 2 | ch << 30) ^ (cl >>> 7 | ch << 25); | |
s0l = (cl >>> 28 | ch << 4) ^ (ch >>> 2 | cl << 30) ^ (ch >>> 7 | cl << 25); | |
s1h = (gh >>> 14 | gl << 18) ^ (gh >>> 18 | gl << 14) ^ (gl >>> 9 | gh << 23); | |
s1l = (gl >>> 14 | gh << 18) ^ (gl >>> 18 | gh << 14) ^ (gh >>> 9 | gl << 23); | |
cdh = ch & dh; | |
cdl = cl & dl; | |
majh = cdh ^ ch & ah ^ dah; | |
majl = cdl ^ cl & al ^ dal; | |
chh = gh & hh ^ ~gh & eh; | |
chl = gl & hl ^ ~gl & el; | |
t1h = blocks3[j1 + 4]; | |
t1l = blocks3[j1 + 5]; | |
t2h = K1[j1 + 4]; | |
t2l = K1[j1 + 5]; | |
c1 = (t2l & 0xffff) + (t1l & 0xffff) + (chl & 0xffff) + (s1l & 0xffff) + (fl & 0xffff); | |
c2 = (t2l >>> 16) + (t1l >>> 16) + (chl >>> 16) + (s1l >>> 16) + (fl >>> 16) + (c1 >>> 16); | |
c3 = (t2h & 0xffff) + (t1h & 0xffff) + (chh & 0xffff) + (s1h & 0xffff) + (fh & 0xffff) + (c2 >>> 16); | |
c4 = (t2h >>> 16) + (t1h >>> 16) + (chh >>> 16) + (s1h >>> 16) + (fh >>> 16) + (c3 >>> 16); | |
t1h = c4 << 16 | c3 & 0xffff; | |
t1l = c2 << 16 | c1 & 0xffff; | |
c1 = (majl & 0xffff) + (s0l & 0xffff); | |
c2 = (majl >>> 16) + (s0l >>> 16) + (c1 >>> 16); | |
c3 = (majh & 0xffff) + (s0h & 0xffff) + (c2 >>> 16); | |
c4 = (majh >>> 16) + (s0h >>> 16) + (c3 >>> 16); | |
t2h = c4 << 16 | c3 & 0xffff; | |
t2l = c2 << 16 | c1 & 0xffff; | |
c1 = (bl & 0xffff) + (t1l & 0xffff); | |
c2 = (bl >>> 16) + (t1l >>> 16) + (c1 >>> 16); | |
c3 = (bh & 0xffff) + (t1h & 0xffff) + (c2 >>> 16); | |
c4 = (bh >>> 16) + (t1h >>> 16) + (c3 >>> 16); | |
fh = c4 << 16 | c3 & 0xffff; | |
fl = c2 << 16 | c1 & 0xffff; | |
c1 = (t2l & 0xffff) + (t1l & 0xffff); | |
c2 = (t2l >>> 16) + (t1l >>> 16) + (c1 >>> 16); | |
c3 = (t2h & 0xffff) + (t1h & 0xffff) + (c2 >>> 16); | |
c4 = (t2h >>> 16) + (t1h >>> 16) + (c3 >>> 16); | |
bh = c4 << 16 | c3 & 0xffff; | |
bl = c2 << 16 | c1 & 0xffff; | |
s0h = (bh >>> 28 | bl << 4) ^ (bl >>> 2 | bh << 30) ^ (bl >>> 7 | bh << 25); | |
s0l = (bl >>> 28 | bh << 4) ^ (bh >>> 2 | bl << 30) ^ (bh >>> 7 | bl << 25); | |
s1h = (fh >>> 14 | fl << 18) ^ (fh >>> 18 | fl << 14) ^ (fl >>> 9 | fh << 23); | |
s1l = (fl >>> 14 | fh << 18) ^ (fl >>> 18 | fh << 14) ^ (fh >>> 9 | fl << 23); | |
bch = bh & ch; | |
bcl = bl & cl; | |
majh = bch ^ bh & dh ^ cdh; | |
majl = bcl ^ bl & dl ^ cdl; | |
chh = fh & gh ^ ~fh & hh; | |
chl = fl & gl ^ ~fl & hl; | |
t1h = blocks3[j1 + 6]; | |
t1l = blocks3[j1 + 7]; | |
t2h = K1[j1 + 6]; | |
t2l = K1[j1 + 7]; | |
c1 = (t2l & 0xffff) + (t1l & 0xffff) + (chl & 0xffff) + (s1l & 0xffff) + (el & 0xffff); | |
c2 = (t2l >>> 16) + (t1l >>> 16) + (chl >>> 16) + (s1l >>> 16) + (el >>> 16) + (c1 >>> 16); | |
c3 = (t2h & 0xffff) + (t1h & 0xffff) + (chh & 0xffff) + (s1h & 0xffff) + (eh & 0xffff) + (c2 >>> 16); | |
c4 = (t2h >>> 16) + (t1h >>> 16) + (chh >>> 16) + (s1h >>> 16) + (eh >>> 16) + (c3 >>> 16); | |
t1h = c4 << 16 | c3 & 0xffff; | |
t1l = c2 << 16 | c1 & 0xffff; | |
c1 = (majl & 0xffff) + (s0l & 0xffff); | |
c2 = (majl >>> 16) + (s0l >>> 16) + (c1 >>> 16); | |
c3 = (majh & 0xffff) + (s0h & 0xffff) + (c2 >>> 16); | |
c4 = (majh >>> 16) + (s0h >>> 16) + (c3 >>> 16); | |
t2h = c4 << 16 | c3 & 0xffff; | |
t2l = c2 << 16 | c1 & 0xffff; | |
c1 = (al & 0xffff) + (t1l & 0xffff); | |
c2 = (al >>> 16) + (t1l >>> 16) + (c1 >>> 16); | |
c3 = (ah & 0xffff) + (t1h & 0xffff) + (c2 >>> 16); | |
c4 = (ah >>> 16) + (t1h >>> 16) + (c3 >>> 16); | |
eh = c4 << 16 | c3 & 0xffff; | |
el = c2 << 16 | c1 & 0xffff; | |
c1 = (t2l & 0xffff) + (t1l & 0xffff); | |
c2 = (t2l >>> 16) + (t1l >>> 16) + (c1 >>> 16); | |
c3 = (t2h & 0xffff) + (t1h & 0xffff) + (c2 >>> 16); | |
c4 = (t2h >>> 16) + (t1h >>> 16) + (c3 >>> 16); | |
ah = c4 << 16 | c3 & 0xffff; | |
al = c2 << 16 | c1 & 0xffff; | |
} | |
c1 = (h0l & 0xffff) + (al & 0xffff); | |
c2 = (h0l >>> 16) + (al >>> 16) + (c1 >>> 16); | |
c3 = (h0h & 0xffff) + (ah & 0xffff) + (c2 >>> 16); | |
c4 = (h0h >>> 16) + (ah >>> 16) + (c3 >>> 16); | |
this.#h0h = c4 << 16 | c3 & 0xffff; | |
this.#h0l = c2 << 16 | c1 & 0xffff; | |
c1 = (h1l & 0xffff) + (bl & 0xffff); | |
c2 = (h1l >>> 16) + (bl >>> 16) + (c1 >>> 16); | |
c3 = (h1h & 0xffff) + (bh & 0xffff) + (c2 >>> 16); | |
c4 = (h1h >>> 16) + (bh >>> 16) + (c3 >>> 16); | |
this.#h1h = c4 << 16 | c3 & 0xffff; | |
this.#h1l = c2 << 16 | c1 & 0xffff; | |
c1 = (h2l & 0xffff) + (cl & 0xffff); | |
c2 = (h2l >>> 16) + (cl >>> 16) + (c1 >>> 16); | |
c3 = (h2h & 0xffff) + (ch & 0xffff) + (c2 >>> 16); | |
c4 = (h2h >>> 16) + (ch >>> 16) + (c3 >>> 16); | |
this.#h2h = c4 << 16 | c3 & 0xffff; | |
this.#h2l = c2 << 16 | c1 & 0xffff; | |
c1 = (h3l & 0xffff) + (dl & 0xffff); | |
c2 = (h3l >>> 16) + (dl >>> 16) + (c1 >>> 16); | |
c3 = (h3h & 0xffff) + (dh & 0xffff) + (c2 >>> 16); | |
c4 = (h3h >>> 16) + (dh >>> 16) + (c3 >>> 16); | |
this.#h3h = c4 << 16 | c3 & 0xffff; | |
this.#h3l = c2 << 16 | c1 & 0xffff; | |
c1 = (h4l & 0xffff) + (el & 0xffff); | |
c2 = (h4l >>> 16) + (el >>> 16) + (c1 >>> 16); | |
c3 = (h4h & 0xffff) + (eh & 0xffff) + (c2 >>> 16); | |
c4 = (h4h >>> 16) + (eh >>> 16) + (c3 >>> 16); | |
this.#h4h = c4 << 16 | c3 & 0xffff; | |
this.#h4l = c2 << 16 | c1 & 0xffff; | |
c1 = (h5l & 0xffff) + (fl & 0xffff); | |
c2 = (h5l >>> 16) + (fl >>> 16) + (c1 >>> 16); | |
c3 = (h5h & 0xffff) + (fh & 0xffff) + (c2 >>> 16); | |
c4 = (h5h >>> 16) + (fh >>> 16) + (c3 >>> 16); | |
this.#h5h = c4 << 16 | c3 & 0xffff; | |
this.#h5l = c2 << 16 | c1 & 0xffff; | |
c1 = (h6l & 0xffff) + (gl & 0xffff); | |
c2 = (h6l >>> 16) + (gl >>> 16) + (c1 >>> 16); | |
c3 = (h6h & 0xffff) + (gh & 0xffff) + (c2 >>> 16); | |
c4 = (h6h >>> 16) + (gh >>> 16) + (c3 >>> 16); | |
this.#h6h = c4 << 16 | c3 & 0xffff; | |
this.#h6l = c2 << 16 | c1 & 0xffff; | |
c1 = (h7l & 0xffff) + (hl & 0xffff); | |
c2 = (h7l >>> 16) + (hl >>> 16) + (c1 >>> 16); | |
c3 = (h7h & 0xffff) + (hh & 0xffff) + (c2 >>> 16); | |
c4 = (h7h >>> 16) + (hh >>> 16) + (c3 >>> 16); | |
this.#h7h = c4 << 16 | c3 & 0xffff; | |
this.#h7l = c2 << 16 | c1 & 0xffff; | |
} | |
hex() { | |
this.finalize(); | |
const h0h = this.#h0h, h0l = this.#h0l, h1h = this.#h1h, h1l = this.#h1l, h2h = this.#h2h, h2l = this.#h2l, h3h = this.#h3h, h3l = this.#h3l, h4h = this.#h4h, h4l = this.#h4l, h5h = this.#h5h, h5l = this.#h5l, h6h = this.#h6h, h6l = this.#h6l, h7h = this.#h7h, h7l = this.#h7l, bits = this.#bits; | |
let hex = HEX_CHARS1[h0h >> 28 & 0x0f] + HEX_CHARS1[h0h >> 24 & 0x0f] + HEX_CHARS1[h0h >> 20 & 0x0f] + HEX_CHARS1[h0h >> 16 & 0x0f] + HEX_CHARS1[h0h >> 12 & 0x0f] + HEX_CHARS1[h0h >> 8 & 0x0f] + HEX_CHARS1[h0h >> 4 & 0x0f] + HEX_CHARS1[h0h & 0x0f] + HEX_CHARS1[h0l >> 28 & 0x0f] + HEX_CHARS1[h0l >> 24 & 0x0f] + HEX_CHARS1[h0l >> 20 & 0x0f] + HEX_CHARS1[h0l >> 16 & 0x0f] + HEX_CHARS1[h0l >> 12 & 0x0f] + HEX_CHARS1[h0l >> 8 & 0x0f] + HEX_CHARS1[h0l >> 4 & 0x0f] + HEX_CHARS1[h0l & 0x0f] + HEX_CHARS1[h1h >> 28 & 0x0f] + HEX_CHARS1[h1h >> 24 & 0x0f] + HEX_CHARS1[h1h >> 20 & 0x0f] + HEX_CHARS1[h1h >> 16 & 0x0f] + HEX_CHARS1[h1h >> 12 & 0x0f] + HEX_CHARS1[h1h >> 8 & 0x0f] + HEX_CHARS1[h1h >> 4 & 0x0f] + HEX_CHARS1[h1h & 0x0f] + HEX_CHARS1[h1l >> 28 & 0x0f] + HEX_CHARS1[h1l >> 24 & 0x0f] + HEX_CHARS1[h1l >> 20 & 0x0f] + HEX_CHARS1[h1l >> 16 & 0x0f] + HEX_CHARS1[h1l >> 12 & 0x0f] + HEX_CHARS1[h1l >> 8 & 0x0f] + HEX_CHARS1[h1l >> 4 & 0x0f] + HEX_CHARS1[h1l & 0x0f] + HEX_CHARS1[h2h >> 28 & 0x0f] + HEX_CHARS1[h2h >> 24 & 0x0f] + HEX_CHARS1[h2h >> 20 & 0x0f] + HEX_CHARS1[h2h >> 16 & 0x0f] + HEX_CHARS1[h2h >> 12 & 0x0f] + HEX_CHARS1[h2h >> 8 & 0x0f] + HEX_CHARS1[h2h >> 4 & 0x0f] + HEX_CHARS1[h2h & 0x0f] + HEX_CHARS1[h2l >> 28 & 0x0f] + HEX_CHARS1[h2l >> 24 & 0x0f] + HEX_CHARS1[h2l >> 20 & 0x0f] + HEX_CHARS1[h2l >> 16 & 0x0f] + HEX_CHARS1[h2l >> 12 & 0x0f] + HEX_CHARS1[h2l >> 8 & 0x0f] + HEX_CHARS1[h2l >> 4 & 0x0f] + HEX_CHARS1[h2l & 0x0f] + HEX_CHARS1[h3h >> 28 & 0x0f] + HEX_CHARS1[h3h >> 24 & 0x0f] + HEX_CHARS1[h3h >> 20 & 0x0f] + HEX_CHARS1[h3h >> 16 & 0x0f] + HEX_CHARS1[h3h >> 12 & 0x0f] + HEX_CHARS1[h3h >> 8 & 0x0f] + HEX_CHARS1[h3h >> 4 & 0x0f] + HEX_CHARS1[h3h & 0x0f]; | |
if (bits >= 256) { | |
hex += HEX_CHARS1[h3l >> 28 & 0x0f] + HEX_CHARS1[h3l >> 24 & 0x0f] + HEX_CHARS1[h3l >> 20 & 0x0f] + HEX_CHARS1[h3l >> 16 & 0x0f] + HEX_CHARS1[h3l >> 12 & 0x0f] + HEX_CHARS1[h3l >> 8 & 0x0f] + HEX_CHARS1[h3l >> 4 & 0x0f] + HEX_CHARS1[h3l & 0x0f]; | |
} | |
if (bits >= 384) { | |
hex += HEX_CHARS1[h4h >> 28 & 0x0f] + HEX_CHARS1[h4h >> 24 & 0x0f] + HEX_CHARS1[h4h >> 20 & 0x0f] + HEX_CHARS1[h4h >> 16 & 0x0f] + HEX_CHARS1[h4h >> 12 & 0x0f] + HEX_CHARS1[h4h >> 8 & 0x0f] + HEX_CHARS1[h4h >> 4 & 0x0f] + HEX_CHARS1[h4h & 0x0f] + HEX_CHARS1[h4l >> 28 & 0x0f] + HEX_CHARS1[h4l >> 24 & 0x0f] + HEX_CHARS1[h4l >> 20 & 0x0f] + HEX_CHARS1[h4l >> 16 & 0x0f] + HEX_CHARS1[h4l >> 12 & 0x0f] + HEX_CHARS1[h4l >> 8 & 0x0f] + HEX_CHARS1[h4l >> 4 & 0x0f] + HEX_CHARS1[h4l & 0x0f] + HEX_CHARS1[h5h >> 28 & 0x0f] + HEX_CHARS1[h5h >> 24 & 0x0f] + HEX_CHARS1[h5h >> 20 & 0x0f] + HEX_CHARS1[h5h >> 16 & 0x0f] + HEX_CHARS1[h5h >> 12 & 0x0f] + HEX_CHARS1[h5h >> 8 & 0x0f] + HEX_CHARS1[h5h >> 4 & 0x0f] + HEX_CHARS1[h5h & 0x0f] + HEX_CHARS1[h5l >> 28 & 0x0f] + HEX_CHARS1[h5l >> 24 & 0x0f] + HEX_CHARS1[h5l >> 20 & 0x0f] + HEX_CHARS1[h5l >> 16 & 0x0f] + HEX_CHARS1[h5l >> 12 & 0x0f] + HEX_CHARS1[h5l >> 8 & 0x0f] + HEX_CHARS1[h5l >> 4 & 0x0f] + HEX_CHARS1[h5l & 0x0f]; | |
} | |
if (bits === 512) { | |
hex += HEX_CHARS1[h6h >> 28 & 0x0f] + HEX_CHARS1[h6h >> 24 & 0x0f] + HEX_CHARS1[h6h >> 20 & 0x0f] + HEX_CHARS1[h6h >> 16 & 0x0f] + HEX_CHARS1[h6h >> 12 & 0x0f] + HEX_CHARS1[h6h >> 8 & 0x0f] + HEX_CHARS1[h6h >> 4 & 0x0f] + HEX_CHARS1[h6h & 0x0f] + HEX_CHARS1[h6l >> 28 & 0x0f] + HEX_CHARS1[h6l >> 24 & 0x0f] + HEX_CHARS1[h6l >> 20 & 0x0f] + HEX_CHARS1[h6l >> 16 & 0x0f] + HEX_CHARS1[h6l >> 12 & 0x0f] + HEX_CHARS1[h6l >> 8 & 0x0f] + HEX_CHARS1[h6l >> 4 & 0x0f] + HEX_CHARS1[h6l & 0x0f] + HEX_CHARS1[h7h >> 28 & 0x0f] + HEX_CHARS1[h7h >> 24 & 0x0f] + HEX_CHARS1[h7h >> 20 & 0x0f] + HEX_CHARS1[h7h >> 16 & 0x0f] + HEX_CHARS1[h7h >> 12 & 0x0f] + HEX_CHARS1[h7h >> 8 & 0x0f] + HEX_CHARS1[h7h >> 4 & 0x0f] + HEX_CHARS1[h7h & 0x0f] + HEX_CHARS1[h7l >> 28 & 0x0f] + HEX_CHARS1[h7l >> 24 & 0x0f] + HEX_CHARS1[h7l >> 20 & 0x0f] + HEX_CHARS1[h7l >> 16 & 0x0f] + HEX_CHARS1[h7l >> 12 & 0x0f] + HEX_CHARS1[h7l >> 8 & 0x0f] + HEX_CHARS1[h7l >> 4 & 0x0f] + HEX_CHARS1[h7l & 0x0f]; | |
} | |
return hex; | |
} | |
toString() { | |
return this.hex(); | |
} | |
digest() { | |
this.finalize(); | |
const h0h = this.#h0h, h0l = this.#h0l, h1h = this.#h1h, h1l = this.#h1l, h2h = this.#h2h, h2l = this.#h2l, h3h = this.#h3h, h3l = this.#h3l, h4h = this.#h4h, h4l = this.#h4l, h5h = this.#h5h, h5l = this.#h5l, h6h = this.#h6h, h6l = this.#h6l, h7h = this.#h7h, h7l = this.#h7l, bits = this.#bits; | |
const arr = [ | |
h0h >> 24 & 0xff, | |
h0h >> 16 & 0xff, | |
h0h >> 8 & 0xff, | |
h0h & 0xff, | |
h0l >> 24 & 0xff, | |
h0l >> 16 & 0xff, | |
h0l >> 8 & 0xff, | |
h0l & 0xff, | |
h1h >> 24 & 0xff, | |
h1h >> 16 & 0xff, | |
h1h >> 8 & 0xff, | |
h1h & 0xff, | |
h1l >> 24 & 0xff, | |
h1l >> 16 & 0xff, | |
h1l >> 8 & 0xff, | |
h1l & 0xff, | |
h2h >> 24 & 0xff, | |
h2h >> 16 & 0xff, | |
h2h >> 8 & 0xff, | |
h2h & 0xff, | |
h2l >> 24 & 0xff, | |
h2l >> 16 & 0xff, | |
h2l >> 8 & 0xff, | |
h2l & 0xff, | |
h3h >> 24 & 0xff, | |
h3h >> 16 & 0xff, | |
h3h >> 8 & 0xff, | |
h3h & 0xff | |
]; | |
if (bits >= 256) { | |
arr.push(h3l >> 24 & 0xff, h3l >> 16 & 0xff, h3l >> 8 & 0xff, h3l & 0xff); | |
} | |
if (bits >= 384) { | |
arr.push(h4h >> 24 & 0xff, h4h >> 16 & 0xff, h4h >> 8 & 0xff, h4h & 0xff, h4l >> 24 & 0xff, h4l >> 16 & 0xff, h4l >> 8 & 0xff, h4l & 0xff, h5h >> 24 & 0xff, h5h >> 16 & 0xff, h5h >> 8 & 0xff, h5h & 0xff, h5l >> 24 & 0xff, h5l >> 16 & 0xff, h5l >> 8 & 0xff, h5l & 0xff); | |
} | |
if (bits === 512) { | |
arr.push(h6h >> 24 & 0xff, h6h >> 16 & 0xff, h6h >> 8 & 0xff, h6h & 0xff, h6l >> 24 & 0xff, h6l >> 16 & 0xff, h6l >> 8 & 0xff, h6l & 0xff, h7h >> 24 & 0xff, h7h >> 16 & 0xff, h7h >> 8 & 0xff, h7h & 0xff, h7l >> 24 & 0xff, h7l >> 16 & 0xff, h7l >> 8 & 0xff, h7l & 0xff); | |
} | |
return arr; | |
} | |
array() { | |
return this.digest(); | |
} | |
arrayBuffer() { | |
this.finalize(); | |
const bits = this.#bits; | |
const buffer = new ArrayBuffer(bits / 8); | |
const dataView = new DataView(buffer); | |
dataView.setUint32(0, this.#h0h); | |
dataView.setUint32(4, this.#h0l); | |
dataView.setUint32(8, this.#h1h); | |
dataView.setUint32(12, this.#h1l); | |
dataView.setUint32(16, this.#h2h); | |
dataView.setUint32(20, this.#h2l); | |
dataView.setUint32(24, this.#h3h); | |
if (bits >= 256) { | |
dataView.setUint32(28, this.#h3l); | |
} | |
if (bits >= 384) { | |
dataView.setUint32(32, this.#h4h); | |
dataView.setUint32(36, this.#h4l); | |
dataView.setUint32(40, this.#h5h); | |
dataView.setUint32(44, this.#h5l); | |
} | |
if (bits === 512) { | |
dataView.setUint32(48, this.#h6h); | |
dataView.setUint32(52, this.#h6l); | |
dataView.setUint32(56, this.#h7h); | |
dataView.setUint32(60, this.#h7l); | |
} | |
return buffer; | |
} | |
} | |
class HmacSha512 extends Sha512 { | |
#inner; | |
#bits; | |
#oKeyPad; | |
#sharedMemory; | |
constructor(secretKey, bits = 512, sharedMemory = false){ | |
super(bits, sharedMemory); | |
let key; | |
if (secretKey instanceof ArrayBuffer) { | |
key = new Uint8Array(secretKey); | |
} else if (typeof secretKey === "string") { | |
const bytes = []; | |
const length = secretKey.length; | |
let index = 0; | |
let code5; | |
for(let i12 = 0; i12 < length; ++i12){ | |
code5 = secretKey.charCodeAt(i12); | |
if (code5 < 0x80) { | |
bytes[index++] = code5; | |
} else if (code5 < 0x800) { | |
bytes[index++] = 0xc0 | code5 >> 6; | |
bytes[index++] = 0x80 | code5 & 0x3f; | |
} else if (code5 < 0xd800 || code5 >= 0xe000) { | |
bytes[index++] = 0xe0 | code5 >> 12; | |
bytes[index++] = 0x80 | code5 >> 6 & 0x3f; | |
bytes[index++] = 0x80 | code5 & 0x3f; | |
} else { | |
code5 = 0x10000 + ((code5 & 0x3ff) << 10 | secretKey.charCodeAt(++i12) & 0x3ff); | |
bytes[index++] = 0xf0 | code5 >> 18; | |
bytes[index++] = 0x80 | code5 >> 12 & 0x3f; | |
bytes[index++] = 0x80 | code5 >> 6 & 0x3f; | |
bytes[index++] = 0x80 | code5 & 0x3f; | |
} | |
} | |
key = bytes; | |
} else { | |
key = secretKey; | |
} | |
if (key.length > 128) { | |
key = new Sha512(bits, true).update(key).array(); | |
} | |
const oKeyPad = []; | |
const iKeyPad = []; | |
for(let i13 = 0; i13 < 128; ++i13){ | |
const b = key[i13] || 0; | |
oKeyPad[i13] = 0x5c ^ b; | |
iKeyPad[i13] = 0x36 ^ b; | |
} | |
this.update(iKeyPad); | |
this.#inner = true; | |
this.#bits = bits; | |
this.#oKeyPad = oKeyPad; | |
this.#sharedMemory = sharedMemory; | |
} | |
finalize() { | |
super.finalize(); | |
if (this.#inner) { | |
this.#inner = false; | |
const innerHash = this.array(); | |
super.init(this.#bits, this.#sharedMemory); | |
this.update(this.#oKeyPad); | |
this.update(innerHash); | |
super.finalize(); | |
} | |
} | |
} | |
function big_base64(m) { | |
if (m === undefined) return undefined; | |
const bytes = []; | |
while(m > 0n){ | |
bytes.push(Number(m & 255n)); | |
m = m >> 8n; | |
} | |
bytes.reverse(); | |
let a = btoa(String.fromCharCode.apply(null, bytes)).replace(/=/g, ""); | |
a = a.replace(/\+/g, "-"); | |
a = a.replace(/\//g, "_"); | |
return a; | |
} | |
function getHashFunctionName(hash) { | |
if (hash === "sha1") return "SHA-1"; | |
if (hash === "sha256") return "SHA-256"; | |
return ""; | |
} | |
async function createWebCryptoKey(key, usage, options) { | |
let jwk = { | |
kty: "RSA", | |
n: big_base64(key.n), | |
ext: true | |
}; | |
if (usage === "encrypt") { | |
jwk = { | |
...jwk, | |
e: big_base64(key.e) | |
}; | |
} else if (usage === "decrypt") { | |
jwk = { | |
...jwk, | |
d: big_base64(key.d), | |
e: big_base64(key.e), | |
p: big_base64(key.p), | |
q: big_base64(key.q), | |
dp: big_base64(key.dp), | |
dq: big_base64(key.dq), | |
qi: big_base64(key.qi) | |
}; | |
} | |
return await crypto.subtle.importKey("jwk", jwk, { | |
name: "RSA-OAEP", | |
hash: { | |
name: getHashFunctionName(options.hash) | |
} | |
}, false, [ | |
usage | |
]); | |
} | |
class WebCryptoRSA { | |
key; | |
options; | |
encryptedKey = null; | |
decryptedKey = null; | |
constructor(key, options){ | |
this.key = key; | |
this.options = options; | |
} | |
static isSupported(options) { | |
if (!crypto.subtle) return false; | |
if (options.padding !== "oaep") return false; | |
return true; | |
} | |
static async encrypt(key, m, options) { | |
return await crypto.subtle.encrypt({ | |
name: "RSA-OAEP" | |
}, await createWebCryptoKey(key, "encrypt", options), m); | |
} | |
static async decrypt(key, m, options) { | |
return await crypto.subtle.decrypt({ | |
name: "RSA-OAEP" | |
}, await createWebCryptoKey(key, "decrypt", options), m); | |
} | |
} | |
function power_mod(n, p, m) { | |
if (p === 1n) return n; | |
if (p % 2n === 0n) { | |
const t = power_mod(n, p >> 1n, m); | |
return t * t % m; | |
} else { | |
const t = power_mod(n, p >> 1n, m); | |
return t * t * n % m; | |
} | |
} | |
function getLengths(b64) { | |
const len = b64.length; | |
let validLen = b64.indexOf("="); | |
if (validLen === -1) { | |
validLen = len; | |
} | |
const placeHoldersLen = validLen === len ? 0 : 4 - validLen % 4; | |
return [ | |
validLen, | |
placeHoldersLen | |
]; | |
} | |
function init(lookup2, revLookup2, urlsafe = false) { | |
function _byteLength(validLen, placeHoldersLen) { | |
return Math.floor((validLen + placeHoldersLen) * 3 / 4 - placeHoldersLen); | |
} | |
function tripletToBase64(num) { | |
return lookup2[num >> 18 & 0x3f] + lookup2[num >> 12 & 0x3f] + lookup2[num >> 6 & 0x3f] + lookup2[num & 0x3f]; | |
} | |
function encodeChunk(buf, start, end) { | |
const out = new Array((end - start) / 3); | |
for(let i14 = start, curTriplet = 0; i14 < end; i14 += 3){ | |
out[curTriplet++] = tripletToBase64((buf[i14] << 16) + (buf[i14 + 1] << 8) + buf[i14 + 2]); | |
} | |
return out.join(""); | |
} | |
return { | |
byteLength (b64) { | |
return _byteLength.apply(null, getLengths(b64)); | |
}, | |
toUint8Array (b64) { | |
const [validLen, placeHoldersLen] = getLengths(b64); | |
const buf = new Uint8Array(_byteLength(validLen, placeHoldersLen)); | |
const len = placeHoldersLen ? validLen - 4 : validLen; | |
let tmp; | |
let curByte = 0; | |
let i15; | |
for(i15 = 0; i15 < len; i15 += 4){ | |
tmp = revLookup2[b64.charCodeAt(i15)] << 18 | revLookup2[b64.charCodeAt(i15 + 1)] << 12 | revLookup2[b64.charCodeAt(i15 + 2)] << 6 | revLookup2[b64.charCodeAt(i15 + 3)]; | |
buf[curByte++] = tmp >> 16 & 0xff; | |
buf[curByte++] = tmp >> 8 & 0xff; | |
buf[curByte++] = tmp & 0xff; | |
} | |
if (placeHoldersLen === 2) { | |
tmp = revLookup2[b64.charCodeAt(i15)] << 2 | revLookup2[b64.charCodeAt(i15 + 1)] >> 4; | |
buf[curByte++] = tmp & 0xff; | |
} else if (placeHoldersLen === 1) { | |
tmp = revLookup2[b64.charCodeAt(i15)] << 10 | revLookup2[b64.charCodeAt(i15 + 1)] << 4 | revLookup2[b64.charCodeAt(i15 + 2)] >> 2; | |
buf[curByte++] = tmp >> 8 & 0xff; | |
buf[curByte++] = tmp & 0xff; | |
} | |
return buf; | |
}, | |
fromUint8Array (buf) { | |
const maxChunkLength = 16383; | |
const len = buf.length; | |
const extraBytes = len % 3; | |
const len2 = len - extraBytes; | |
const parts = new Array(Math.ceil(len2 / 16383) + (extraBytes ? 1 : 0)); | |
let curChunk = 0; | |
let chunkEnd; | |
for(let i16 = 0; i16 < len2; i16 += maxChunkLength){ | |
chunkEnd = i16 + maxChunkLength; | |
parts[curChunk++] = encodeChunk(buf, i16, chunkEnd > len2 ? len2 : chunkEnd); | |
} | |
let tmp; | |
if (extraBytes === 1) { | |
tmp = buf[len2]; | |
parts[curChunk] = lookup2[tmp >> 2] + lookup2[tmp << 4 & 0x3f]; | |
if (!urlsafe) parts[curChunk] += "=="; | |
} else if (extraBytes === 2) { | |
tmp = buf[len2] << 8 | buf[len2 + 1] & 0xff; | |
parts[curChunk] = lookup2[tmp >> 10] + lookup2[tmp >> 4 & 0x3f] + lookup2[tmp << 2 & 0x3f]; | |
if (!urlsafe) parts[curChunk] += "="; | |
} | |
return parts.join(""); | |
} | |
}; | |
} | |
const lookup = []; | |
const revLookup = []; | |
const code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; | |
for(let i = 0, l = code.length; i < l; ++i){ | |
lookup[i] = code[i]; | |
revLookup[code.charCodeAt(i)] = i; | |
} | |
const { byteLength , toUint8Array , fromUint8Array } = init(lookup, revLookup, true); | |
const decoder = new TextDecoder(); | |
const encoder = new TextEncoder(); | |
function toHexString(buf) { | |
return buf.reduce((hex, __byte)=>`${hex}${__byte < 16 ? "0" : ""}${__byte.toString(16)}` | |
, ""); | |
} | |
function fromHexString(hex) { | |
const len = hex.length; | |
if (len % 2 || !/^[0-9a-fA-F]+$/.test(hex)) { | |
throw new TypeError("Invalid hex string."); | |
} | |
hex = hex.toLowerCase(); | |
const buf = new Uint8Array(Math.floor(len / 2)); | |
const end = len / 2; | |
for(let i17 = 0; i17 < end; ++i17){ | |
buf[i17] = parseInt(hex.substr(i17 * 2, 2), 16); | |
} | |
return buf; | |
} | |
function decode3(buf, encoding = "utf8") { | |
if (/^utf-?8$/i.test(encoding)) { | |
return decoder.decode(buf); | |
} else if (/^base64$/i.test(encoding)) { | |
return fromUint8Array(buf); | |
} else if (/^hex(?:adecimal)?$/i.test(encoding)) { | |
return toHexString(buf); | |
} else { | |
throw new TypeError("Unsupported string encoding."); | |
} | |
} | |
function encode3(str, encoding = "utf8") { | |
if (/^utf-?8$/i.test(encoding)) { | |
return encoder.encode(str); | |
} else if (/^base64$/i.test(encoding)) { | |
return toUint8Array(str); | |
} else if (/^hex(?:adecimal)?$/i.test(encoding)) { | |
return fromHexString(str); | |
} else { | |
throw new TypeError("Unsupported string encoding."); | |
} | |
} | |
function rotl(x, n) { | |
return x << n | x >>> 32 - n; | |
} | |
class SHA1 { | |
hashSize = 20; | |
_buf = new Uint8Array(64); | |
_bufIdx; | |
_count; | |
_K = new Uint32Array([ | |
0x5a827999, | |
0x6ed9eba1, | |
0x8f1bbcdc, | |
0xca62c1d6 | |
]); | |
_H; | |
_finalized; | |
constructor(){ | |
this.init(); | |
} | |
static F(t, b, c, d) { | |
if (t <= 19) { | |
return b & c | ~b & d; | |
} else if (t <= 39) { | |
return b ^ c ^ d; | |
} else if (t <= 59) { | |
return b & c | b & d | c & d; | |
} else { | |
return b ^ c ^ d; | |
} | |
} | |
init() { | |
this._H = new Uint32Array([ | |
0x67452301, | |
0xEFCDAB89, | |
0x98BADCFE, | |
0x10325476, | |
0xC3D2E1F0 | |
]); | |
this._bufIdx = 0; | |
this._count = new Uint32Array(2); | |
this._buf.fill(0); | |
this._finalized = false; | |
return this; | |
} | |
update(msg, inputEncoding) { | |
if (msg === null) { | |
throw new TypeError("msg must be a string or Uint8Array."); | |
} else if (typeof msg === "string") { | |
msg = encode3(msg, inputEncoding); | |
} | |
for(let i18 = 0; i18 < msg.length; i18++){ | |
this._buf[this._bufIdx++] = msg[i18]; | |
if (this._bufIdx === 64) { | |
this.transform(); | |
this._bufIdx = 0; | |
} | |
} | |
const c = this._count; | |
if ((c[0] += msg.length << 3) < msg.length << 3) { | |
c[1]++; | |
} | |
c[1] += msg.length >>> 29; | |
return this; | |
} | |
digest(outputEncoding) { | |
if (this._finalized) { | |
throw new Error("digest has already been called."); | |
} | |
this._finalized = true; | |
const b = this._buf; | |
let idx = this._bufIdx; | |
b[idx++] = 0x80; | |
while(idx !== 56){ | |
if (idx === 64) { | |
this.transform(); | |
idx = 0; | |
} | |
b[idx++] = 0; | |
} | |
const c = this._count; | |
b[56] = c[1] >>> 24 & 0xff; | |
b[57] = c[1] >>> 16 & 0xff; | |
b[58] = c[1] >>> 8 & 0xff; | |
b[59] = c[1] >>> 0 & 0xff; | |
b[60] = c[0] >>> 24 & 0xff; | |
b[61] = c[0] >>> 16 & 0xff; | |
b[62] = c[0] >>> 8 & 0xff; | |
b[63] = c[0] >>> 0 & 0xff; | |
this.transform(); | |
const hash = new Uint8Array(20); | |
for(let i19 = 0; i19 < 5; i19++){ | |
hash[(i19 << 2) + 0] = this._H[i19] >>> 24 & 0xff; | |
hash[(i19 << 2) + 1] = this._H[i19] >>> 16 & 0xff; | |
hash[(i19 << 2) + 2] = this._H[i19] >>> 8 & 0xff; | |
hash[(i19 << 2) + 3] = this._H[i19] >>> 0 & 0xff; | |
} | |
this.init(); | |
return outputEncoding ? decode3(hash, outputEncoding) : hash; | |
} | |
transform() { | |
const h = this._H; | |
let a = h[0]; | |
let b = h[1]; | |
let c = h[2]; | |
let d = h[3]; | |
let e = h[4]; | |
const w = new Uint32Array(80); | |
for(let i20 = 0; i20 < 16; i20++){ | |
w[i20] = this._buf[(i20 << 2) + 3] | this._buf[(i20 << 2) + 2] << 8 | this._buf[(i20 << 2) + 1] << 16 | this._buf[i20 << 2] << 24; | |
} | |
for(let t = 0; t < 80; t++){ | |
if (t >= 16) { | |
w[t] = rotl(w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16], 1); | |
} | |
const tmp = rotl(a, 5) + SHA1.F(t, b, c, d) + e + w[t] + this._K[Math.floor(t / 20)] | 0; | |
e = d; | |
d = c; | |
c = rotl(b, 30); | |
b = a; | |
a = tmp; | |
} | |
h[0] = h[0] + a | 0; | |
h[1] = h[1] + b | 0; | |
h[2] = h[2] + c | 0; | |
h[3] = h[3] + d | 0; | |
h[4] = h[4] + e | 0; | |
} | |
} | |
function sha1(msg, inputEncoding, outputEncoding) { | |
return new SHA1().update(msg, inputEncoding).digest(outputEncoding); | |
} | |
class SHA256 { | |
hashSize = 32; | |
_buf; | |
_bufIdx; | |
_count; | |
_K; | |
_H; | |
_finalized; | |
constructor(){ | |
this._buf = new Uint8Array(64); | |
this._K = new Uint32Array([ | |
0x428a2f98, | |
0x71374491, | |
0xb5c0fbcf, | |
0xe9b5dba5, | |
0x3956c25b, | |
0x59f111f1, | |
0x923f82a4, | |
0xab1c5ed5, | |
0xd807aa98, | |
0x12835b01, | |
0x243185be, | |
0x550c7dc3, | |
0x72be5d74, | |
0x80deb1fe, | |
0x9bdc06a7, | |
0xc19bf174, | |
0xe49b69c1, | |
0xefbe4786, | |
0x0fc19dc6, | |
0x240ca1cc, | |
0x2de92c6f, | |
0x4a7484aa, | |
0x5cb0a9dc, | |
0x76f988da, | |
0x983e5152, | |
0xa831c66d, | |
0xb00327c8, | |
0xbf597fc7, | |
0xc6e00bf3, | |
0xd5a79147, | |
0x06ca6351, | |
0x14292967, | |
0x27b70a85, | |
0x2e1b2138, | |
0x4d2c6dfc, | |
0x53380d13, | |
0x650a7354, | |
0x766a0abb, | |
0x81c2c92e, | |
0x92722c85, | |
0xa2bfe8a1, | |
0xa81a664b, | |
0xc24b8b70, | |
0xc76c51a3, | |
0xd192e819, | |
0xd6990624, | |
0xf40e3585, | |
0x106aa070, | |
0x19a4c116, | |
0x1e376c08, | |
0x2748774c, | |
0x34b0bcb5, | |
0x391c0cb3, | |
0x4ed8aa4a, | |
0x5b9cca4f, | |
0x682e6ff3, | |
0x748f82ee, | |
0x78a5636f, | |
0x84c87814, | |
0x8cc70208, | |
0x90befffa, | |
0xa4506ceb, | |
0xbef9a3f7, | |
0xc67178f2 | |
]); | |
this.init(); | |
} | |
init() { | |
this._H = new Uint32Array([ | |
0x6a09e667, | |
0xbb67ae85, | |
0x3c6ef372, | |
0xa54ff53a, | |
0x510e527f, | |
0x9b05688c, | |
0x1f83d9ab, | |
0x5be0cd19 | |
]); | |
this._bufIdx = 0; | |
this._count = new Uint32Array(2); | |
this._buf.fill(0); | |
this._finalized = false; | |
return this; | |
} | |
update(msg, inputEncoding) { | |
if (msg === null) { | |
throw new TypeError("msg must be a string or Uint8Array."); | |
} else if (typeof msg === "string") { | |
msg = encode3(msg, inputEncoding); | |
} | |
for(let i21 = 0, len = msg.length; i21 < len; i21++){ | |
this._buf[this._bufIdx++] = msg[i21]; | |
if (this._bufIdx === 64) { | |
this._transform(); | |
this._bufIdx = 0; | |
} | |
} | |
const c = this._count; | |
if ((c[0] += msg.length << 3) < msg.length << 3) { | |
c[1]++; | |
} | |
c[1] += msg.length >>> 29; | |
return this; | |
} | |
digest(outputEncoding) { | |
if (this._finalized) { | |
throw new Error("digest has already been called."); | |
} | |
this._finalized = true; | |
const b = this._buf; | |
let idx = this._bufIdx; | |
b[idx++] = 0x80; | |
while(idx !== 56){ | |
if (idx === 64) { | |
this._transform(); | |
idx = 0; | |
} | |
b[idx++] = 0; | |
} | |
const c = this._count; | |
b[56] = c[1] >>> 24 & 0xff; | |
b[57] = c[1] >>> 16 & 0xff; | |
b[58] = c[1] >>> 8 & 0xff; | |
b[59] = c[1] >>> 0 & 0xff; | |
b[60] = c[0] >>> 24 & 0xff; | |
b[61] = c[0] >>> 16 & 0xff; | |
b[62] = c[0] >>> 8 & 0xff; | |
b[63] = c[0] >>> 0 & 0xff; | |
this._transform(); | |
const hash = new Uint8Array(32); | |
for(let i22 = 0; i22 < 8; i22++){ | |
hash[(i22 << 2) + 0] = this._H[i22] >>> 24 & 0xff; | |
hash[(i22 << 2) + 1] = this._H[i22] >>> 16 & 0xff; | |
hash[(i22 << 2) + 2] = this._H[i22] >>> 8 & 0xff; | |
hash[(i22 << 2) + 3] = this._H[i22] >>> 0 & 0xff; | |
} | |
this.init(); | |
return outputEncoding ? decode3(hash, outputEncoding) : hash; | |
} | |
_transform() { | |
const h = this._H; | |
let h0 = h[0]; | |
let h1 = h[1]; | |
let h2 = h[2]; | |
let h3 = h[3]; | |
let h4 = h[4]; | |
let h5 = h[5]; | |
let h6 = h[6]; | |
let h7 = h[7]; | |
const w = new Uint32Array(16); | |
let i23; | |
for(i23 = 0; i23 < 16; i23++){ | |
w[i23] = this._buf[(i23 << 2) + 3] | this._buf[(i23 << 2) + 2] << 8 | this._buf[(i23 << 2) + 1] << 16 | this._buf[i23 << 2] << 24; | |
} | |
for(i23 = 0; i23 < 64; i23++){ | |
let tmp; | |
if (i23 < 16) { | |
tmp = w[i23]; | |
} else { | |
let a = w[i23 + 1 & 15]; | |
let b = w[i23 + 14 & 15]; | |
tmp = w[i23 & 15] = (a >>> 7 ^ a >>> 18 ^ a >>> 3 ^ a << 25 ^ a << 14) + (b >>> 17 ^ b >>> 19 ^ b >>> 10 ^ b << 15 ^ b << 13) + w[i23 & 15] + w[i23 + 9 & 15] | 0; | |
} | |
tmp = tmp + h7 + (h4 >>> 6 ^ h4 >>> 11 ^ h4 >>> 25 ^ h4 << 26 ^ h4 << 21 ^ h4 << 7) + (h6 ^ h4 & (h5 ^ h6)) + this._K[i23] | 0; | |
h7 = h6; | |
h6 = h5; | |
h5 = h4; | |
h4 = h3 + tmp; | |
h3 = h2; | |
h2 = h1; | |
h1 = h0; | |
h0 = tmp + (h1 & h2 ^ h3 & (h1 ^ h2)) + (h1 >>> 2 ^ h1 >>> 13 ^ h1 >>> 22 ^ h1 << 30 ^ h1 << 19 ^ h1 << 10) | 0; | |
} | |
h[0] = h[0] + h0 | 0; | |
h[1] = h[1] + h1 | 0; | |
h[2] = h[2] + h2 | 0; | |
h[3] = h[3] + h3 | 0; | |
h[4] = h[4] + h4 | 0; | |
h[5] = h[5] + h5 | 0; | |
h[6] = h[6] + h6 | 0; | |
h[7] = h[7] + h7 | 0; | |
} | |
} | |
function sha256(msg, inputEncoding, outputEncoding) { | |
return new SHA256().update(msg, inputEncoding).digest(outputEncoding); | |
} | |
const lookup1 = []; | |
const revLookup1 = []; | |
const code1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
for(let i1 = 0, l1 = code1.length; i1 < l1; ++i1){ | |
lookup1[i1] = code1[i1]; | |
revLookup1[code1.charCodeAt(i1)] = i1; | |
} | |
revLookup1["-".charCodeAt(0)] = 62; | |
revLookup1["_".charCodeAt(0)] = 63; | |
const { byteLength: byteLength1 , toUint8Array: toUint8Array1 , fromUint8Array: fromUint8Array1 } = init(lookup1, revLookup1); | |
const decoder1 = new TextDecoder(); | |
const encoder1 = new TextEncoder(); | |
function toHexString1(buf) { | |
return buf.reduce((hex, __byte)=>`${hex}${__byte < 16 ? "0" : ""}${__byte.toString(16)}` | |
, ""); | |
} | |
function fromHexString1(hex) { | |
const len = hex.length; | |
if (len % 2 || !/^[0-9a-fA-F]+$/.test(hex)) { | |
throw new TypeError("Invalid hex string."); | |
} | |
hex = hex.toLowerCase(); | |
const buf = new Uint8Array(Math.floor(len / 2)); | |
const end = len / 2; | |
for(let i24 = 0; i24 < end; ++i24){ | |
buf[i24] = parseInt(hex.substr(i24 * 2, 2), 16); | |
} | |
return buf; | |
} | |
function decode4(buf, encoding = "utf8") { | |
if (/^utf-?8$/i.test(encoding)) { | |
return decoder1.decode(buf); | |
} else if (/^base64$/i.test(encoding)) { | |
return fromUint8Array1(buf); | |
} else if (/^base64url$/i.test(encoding)) { | |
return fromUint8Array(buf); | |
} else if (/^hex(?:adecimal)?$/i.test(encoding)) { | |
return toHexString1(buf); | |
} else { | |
throw new TypeError("Unsupported string encoding."); | |
} | |
} | |
function encode4(str, encoding = "utf8") { | |
if (/^utf-?8$/i.test(encoding)) { | |
return encoder1.encode(str); | |
} else if (/^base64(?:url)?$/i.test(encoding)) { | |
return toUint8Array1(str); | |
} else if (/^hex(?:adecimal)?$/i.test(encoding)) { | |
return fromHexString1(str); | |
} else { | |
throw new TypeError("Unsupported string encoding."); | |
} | |
} | |
class SHA512 { | |
hashSize = 64; | |
_buffer = new Uint8Array(128); | |
_bufferIndex; | |
_count; | |
_K; | |
_H; | |
_finalized; | |
constructor(){ | |
this._K = new Uint32Array([ | |
0x428a2f98, | |
0xd728ae22, | |
0x71374491, | |
0x23ef65cd, | |
0xb5c0fbcf, | |
0xec4d3b2f, | |
0xe9b5dba5, | |
0x8189dbbc, | |
0x3956c25b, | |
0xf348b538, | |
0x59f111f1, | |
0xb605d019, | |
0x923f82a4, | |
0xaf194f9b, | |
0xab1c5ed5, | |
0xda6d8118, | |
0xd807aa98, | |
0xa3030242, | |
0x12835b01, | |
0x45706fbe, | |
0x243185be, | |
0x4ee4b28c, | |
0x550c7dc3, | |
0xd5ffb4e2, | |
0x72be5d74, | |
0xf27b896f, | |
0x80deb1fe, | |
0x3b1696b1, | |
0x9bdc06a7, | |
0x25c71235, | |
0xc19bf174, | |
0xcf692694, | |
0xe49b69c1, | |
0x9ef14ad2, | |
0xefbe4786, | |
0x384f25e3, | |
0x0fc19dc6, | |
0x8b8cd5b5, | |
0x240ca1cc, | |
0x77ac9c65, | |
0x2de92c6f, | |
0x592b0275, | |
0x4a7484aa, | |
0x6ea6e483, | |
0x5cb0a9dc, | |
0xbd41fbd4, | |
0x76f988da, | |
0x831153b5, | |
0x983e5152, | |
0xee66dfab, | |
0xa831c66d, | |
0x2db43210, | |
0xb00327c8, | |
0x98fb213f, | |
0xbf597fc7, | |
0xbeef0ee4, | |
0xc6e00bf3, | |
0x3da88fc2, | |
0xd5a79147, | |
0x930aa725, | |
0x06ca6351, | |
0xe003826f, | |
0x14292967, | |
0x0a0e6e70, | |
0x27b70a85, | |
0x46d22ffc, | |
0x2e1b2138, | |
0x5c26c926, | |
0x4d2c6dfc, | |
0x5ac42aed, | |
0x53380d13, | |
0x9d95b3df, | |
0x650a7354, | |
0x8baf63de, | |
0x766a0abb, | |
0x3c77b2a8, | |
0x81c2c92e, | |
0x47edaee6, | |
0x92722c85, | |
0x1482353b, | |
0xa2bfe8a1, | |
0x4cf10364, | |
0xa81a664b, | |
0xbc423001, | |
0xc24b8b70, | |
0xd0f89791, | |
0xc76c51a3, | |
0x0654be30, | |
0xd192e819, | |
0xd6ef5218, | |
0xd6990624, | |
0x5565a910, | |
0xf40e3585, | |
0x5771202a, | |
0x106aa070, | |
0x32bbd1b8, | |
0x19a4c116, | |
0xb8d2d0c8, | |
0x1e376c08, | |
0x5141ab53, | |
0x2748774c, | |
0xdf8eeb99, | |
0x34b0bcb5, | |
0xe19b48a8, | |
0x391c0cb3, | |
0xc5c95a63, | |
0x4ed8aa4a, | |
0xe3418acb, | |
0x5b9cca4f, | |
0x7763e373, | |
0x682e6ff3, | |
0xd6b2b8a3, | |
0x748f82ee, | |
0x5defb2fc, | |
0x78a5636f, | |
0x43172f60, | |
0x84c87814, | |
0xa1f0ab72, | |
0x8cc70208, | |
0x1a6439ec, | |
0x90befffa, | |
0x23631e28, | |
0xa4506ceb, | |
0xde82bde9, | |
0xbef9a3f7, | |
0xb2c67915, | |
0xc67178f2, | |
0xe372532b, | |
0xca273ece, | |
0xea26619c, | |
0xd186b8c7, | |
0x21c0c207, | |
0xeada7dd6, | |
0xcde0eb1e, | |
0xf57d4f7f, | |
0xee6ed178, | |
0x06f067aa, | |
0x72176fba, | |
0x0a637dc5, | |
0xa2c898a6, | |
0x113f9804, | |
0xbef90dae, | |
0x1b710b35, | |
0x131c471b, | |
0x28db77f5, | |
0x23047d84, | |
0x32caab7b, | |
0x40c72493, | |
0x3c9ebe0a, | |
0x15c9bebc, | |
0x431d67c4, | |
0x9c100d4c, | |
0x4cc5d4be, | |
0xcb3e42b6, | |
0x597f299c, | |
0xfc657e2a, | |
0x5fcb6fab, | |
0x3ad6faec, | |
0x6c44198c, | |
0x4a475817 | |
]); | |
this.init(); | |
} | |
init() { | |
this._H = new Uint32Array([ | |
0x6a09e667, | |
0xf3bcc908, | |
0xbb67ae85, | |
0x84caa73b, | |
0x3c6ef372, | |
0xfe94f82b, | |
0xa54ff53a, | |
0x5f1d36f1, | |
0x510e527f, | |
0xade682d1, | |
0x9b05688c, | |
0x2b3e6c1f, | |
0x1f83d9ab, | |
0xfb41bd6b, | |
0x5be0cd19, | |
0x137e2179 | |
]); | |
this._bufferIndex = 0; | |
this._count = new Uint32Array(2); | |
this._buffer.fill(0); | |
this._finalized = false; | |
return this; | |
} | |
update(msg, inputEncoding) { | |
if (msg === null) { | |
throw new TypeError("msg must be a string or Uint8Array."); | |
} else if (typeof msg === "string") { | |
msg = encode4(msg, inputEncoding); | |
} | |
for(let i25 = 0; i25 < msg.length; i25++){ | |
this._buffer[this._bufferIndex++] = msg[i25]; | |
if (this._bufferIndex === 128) { | |
this.transform(); | |
this._bufferIndex = 0; | |
} | |
} | |
let c = this._count; | |
if ((c[0] += msg.length << 3) < msg.length << 3) { | |
c[1]++; | |
} | |
c[1] += msg.length >>> 29; | |
return this; | |
} | |
digest(outputEncoding) { | |
if (this._finalized) { | |
throw new Error("digest has already been called."); | |
} | |
this._finalized = true; | |
var b = this._buffer, idx = this._bufferIndex; | |
b[idx++] = 0x80; | |
while(idx !== 112){ | |
if (idx === 128) { | |
this.transform(); | |
idx = 0; | |
} | |
b[idx++] = 0; | |
} | |
let c = this._count; | |
b[112] = b[113] = b[114] = b[115] = b[116] = b[117] = b[118] = b[119] = 0; | |
b[120] = c[1] >>> 24 & 0xff; | |
b[121] = c[1] >>> 16 & 0xff; | |
b[122] = c[1] >>> 8 & 0xff; | |
b[123] = c[1] >>> 0 & 0xff; | |
b[124] = c[0] >>> 24 & 0xff; | |
b[125] = c[0] >>> 16 & 0xff; | |
b[126] = c[0] >>> 8 & 0xff; | |
b[127] = c[0] >>> 0 & 0xff; | |
this.transform(); | |
let i26, hash = new Uint8Array(64); | |
for(i26 = 0; i26 < 16; i26++){ | |
hash[(i26 << 2) + 0] = this._H[i26] >>> 24 & 0xff; | |
hash[(i26 << 2) + 1] = this._H[i26] >>> 16 & 0xff; | |
hash[(i26 << 2) + 2] = this._H[i26] >>> 8 & 0xff; | |
hash[(i26 << 2) + 3] = this._H[i26] & 0xff; | |
} | |
this.init(); | |
return outputEncoding ? decode4(hash, outputEncoding) : hash; | |
} | |
transform() { | |
let h = this._H, h0h = h[0], h0l = h[1], h1h = h[2], h1l = h[3], h2h = h[4], h2l = h[5], h3h = h[6], h3l = h[7], h4h = h[8], h4l = h[9], h5h = h[10], h5l = h[11], h6h = h[12], h6l = h[13], h7h = h[14], h7l = h[15]; | |
let ah = h0h, al = h0l, bh = h1h, bl = h1l, ch = h2h, cl = h2l, dh = h3h, dl = h3l, eh = h4h, el = h4l, fh = h5h, fl = h5l, gh = h6h, gl = h6l, hh = h7h, hl = h7l; | |
let i27, w = new Uint32Array(160); | |
for(i27 = 0; i27 < 32; i27++){ | |
w[i27] = this._buffer[(i27 << 2) + 3] | this._buffer[(i27 << 2) + 2] << 8 | this._buffer[(i27 << 2) + 1] << 16 | this._buffer[i27 << 2] << 24; | |
} | |
let gamma0xl, gamma0xh, gamma0l, gamma0h, gamma1xl, gamma1xh, gamma1l, gamma1h, wrl, wrh, wr7l, wr7h, wr16l, wr16h; | |
for(i27 = 16; i27 < 80; i27++){ | |
gamma0xh = w[(i27 - 15) * 2]; | |
gamma0xl = w[(i27 - 15) * 2 + 1]; | |
gamma0h = (gamma0xl << 31 | gamma0xh >>> 1) ^ (gamma0xl << 24 | gamma0xh >>> 8) ^ gamma0xh >>> 7; | |
gamma0l = (gamma0xh << 31 | gamma0xl >>> 1) ^ (gamma0xh << 24 | gamma0xl >>> 8) ^ (gamma0xh << 25 | gamma0xl >>> 7); | |
gamma1xh = w[(i27 - 2) * 2]; | |
gamma1xl = w[(i27 - 2) * 2 + 1]; | |
gamma1h = (gamma1xl << 13 | gamma1xh >>> 19) ^ (gamma1xh << 3 | gamma1xl >>> 29) ^ gamma1xh >>> 6; | |
gamma1l = (gamma1xh << 13 | gamma1xl >>> 19) ^ (gamma1xl << 3 | gamma1xh >>> 29) ^ (gamma1xh << 26 | gamma1xl >>> 6); | |
wr7h = w[(i27 - 7) * 2], wr7l = w[(i27 - 7) * 2 + 1], wr16h = w[(i27 - 16) * 2], wr16l = w[(i27 - 16) * 2 + 1]; | |
wrl = gamma0l + wr7l; | |
wrh = gamma0h + wr7h + (wrl >>> 0 < gamma0l >>> 0 ? 1 : 0); | |
wrl += gamma1l; | |
wrh += gamma1h + (wrl >>> 0 < gamma1l >>> 0 ? 1 : 0); | |
wrl += wr16l; | |
wrh += wr16h + (wrl >>> 0 < wr16l >>> 0 ? 1 : 0); | |
w[i27 * 2] = wrh; | |
w[i27 * 2 + 1] = wrl; | |
} | |
let chl, chh, majl, majh, sig0l, sig0h, sig1l, sig1h, krl, krh, t1l, t1h, t2l, t2h; | |
for(i27 = 0; i27 < 80; i27++){ | |
chh = eh & fh ^ ~eh & gh; | |
chl = el & fl ^ ~el & gl; | |
majh = ah & bh ^ ah & ch ^ bh & ch; | |
majl = al & bl ^ al & cl ^ bl & cl; | |
sig0h = (al << 4 | ah >>> 28) ^ (ah << 30 | al >>> 2) ^ (ah << 25 | al >>> 7); | |
sig0l = (ah << 4 | al >>> 28) ^ (al << 30 | ah >>> 2) ^ (al << 25 | ah >>> 7); | |
sig1h = (el << 18 | eh >>> 14) ^ (el << 14 | eh >>> 18) ^ (eh << 23 | el >>> 9); | |
sig1l = (eh << 18 | el >>> 14) ^ (eh << 14 | el >>> 18) ^ (el << 23 | eh >>> 9); | |
krh = this._K[i27 * 2]; | |
krl = this._K[i27 * 2 + 1]; | |
t1l = hl + sig1l; | |
t1h = hh + sig1h + (t1l >>> 0 < hl >>> 0 ? 1 : 0); | |
t1l += chl; | |
t1h += chh + (t1l >>> 0 < chl >>> 0 ? 1 : 0); | |
t1l += krl; | |
t1h += krh + (t1l >>> 0 < krl >>> 0 ? 1 : 0); | |
t1l = t1l + w[i27 * 2 + 1]; | |
t1h += w[i27 * 2] + (t1l >>> 0 < w[i27 * 2 + 1] >>> 0 ? 1 : 0); | |
t2l = sig0l + majl; | |
t2h = sig0h + majh + (t2l >>> 0 < sig0l >>> 0 ? 1 : 0); | |
hh = gh; | |
hl = gl; | |
gh = fh; | |
gl = fl; | |
fh = eh; | |
fl = el; | |
el = dl + t1l | 0; | |
eh = dh + t1h + (el >>> 0 < dl >>> 0 ? 1 : 0) | 0; | |
dh = ch; | |
dl = cl; | |
ch = bh; | |
cl = bl; | |
bh = ah; | |
bl = al; | |
al = t1l + t2l | 0; | |
ah = t1h + t2h + (al >>> 0 < t1l >>> 0 ? 1 : 0) | 0; | |
} | |
h0l = h[1] = h0l + al | 0; | |
h[0] = h0h + ah + (h0l >>> 0 < al >>> 0 ? 1 : 0) | 0; | |
h1l = h[3] = h1l + bl | 0; | |
h[2] = h1h + bh + (h1l >>> 0 < bl >>> 0 ? 1 : 0) | 0; | |
h2l = h[5] = h2l + cl | 0; | |
h[4] = h2h + ch + (h2l >>> 0 < cl >>> 0 ? 1 : 0) | 0; | |
h3l = h[7] = h3l + dl | 0; | |
h[6] = h3h + dh + (h3l >>> 0 < dl >>> 0 ? 1 : 0) | 0; | |
h4l = h[9] = h4l + el | 0; | |
h[8] = h4h + eh + (h4l >>> 0 < el >>> 0 ? 1 : 0) | 0; | |
h5l = h[11] = h5l + fl | 0; | |
h[10] = h5h + fh + (h5l >>> 0 < fl >>> 0 ? 1 : 0) | 0; | |
h6l = h[13] = h6l + gl | 0; | |
h[12] = h6h + gh + (h6l >>> 0 < gl >>> 0 ? 1 : 0) | 0; | |
h7l = h[15] = h7l + hl | 0; | |
h[14] = h7h + hh + (h7l >>> 0 < hl >>> 0 ? 1 : 0) | 0; | |
} | |
} | |
function sha512(msg, inputEncoding, outputEncoding) { | |
return new SHA512().init().update(msg, inputEncoding).digest(outputEncoding); | |
} | |
function digest(algorithm, m) { | |
if (algorithm === "sha1") { | |
return sha1(m); | |
} else if (algorithm === "sha256") { | |
return sha256(m); | |
} else if (algorithm === "sha512") { | |
return sha512(m); | |
} | |
throw "Unsupport hash algorithm"; | |
} | |
function digestLength(algorithm) { | |
if (algorithm === "sha512") return 64; | |
if (algorithm === "sha256") return 32; | |
return 20; | |
} | |
function i2osp(x, length) { | |
const t = new Uint8Array(length); | |
for(let i28 = length - 1; i28 >= 0; i28--){ | |
if (x === 0n) break; | |
t[i28] = Number(x & 255n); | |
x = x >> 8n; | |
} | |
return t; | |
} | |
function os2ip(m) { | |
let n = 0n; | |
for (const c of m)n = (n << 8n) + BigInt(c); | |
return n; | |
} | |
function mgf1(seed, length, hash) { | |
let counter = 0n; | |
let output = []; | |
while(output.length < length){ | |
const c = i2osp(counter, 4); | |
const h = new Uint8Array(digest(hash, new Uint8Array([ | |
...seed, | |
...c | |
]))); | |
output = [ | |
...output, | |
...h | |
]; | |
counter++; | |
} | |
return new Uint8Array(output.slice(0, length)); | |
} | |
function xor(a, b) { | |
const c = new Uint8Array(a.length); | |
for(let i29 = 0; i29 < c.length; i29++){ | |
c[i29] = a[i29] ^ b[i29 % b.length]; | |
} | |
return c; | |
} | |
function concat(...arg) { | |
const length = arg.reduce((a, b)=>a + b.length | |
, 0); | |
const c = new Uint8Array(length); | |
let ptr = 0; | |
for(let i30 = 0; i30 < arg.length; i30++){ | |
c.set(arg[i30], ptr); | |
ptr += arg[i30].length; | |
} | |
return c; | |
} | |
function random_bytes(length) { | |
const n = new Uint8Array(length); | |
for(let i31 = 0; i31 < length; i31++)n[i31] = (Math.random() * 254 | 0) + 1; | |
return n; | |
} | |
function get_key_size(n) { | |
const size_list = [ | |
64n, | |
128n, | |
256n, | |
512n, | |
1024n | |
]; | |
for (const size of size_list){ | |
if (n < 1n << size * 8n) return Number(size); | |
} | |
return 2048; | |
} | |
function base64_to_binary(b) { | |
let binaryString = window.atob(b); | |
let len = binaryString.length; | |
let bytes = new Uint8Array(len); | |
for(var i32 = 0; i32 < len; i32++){ | |
bytes[i32] = binaryString.charCodeAt(i32); | |
} | |
return bytes; | |
} | |
function eme_oaep_encode(label, m, k, algorithm) { | |
const labelHash = new Uint8Array(digest(algorithm, label)); | |
const ps = new Uint8Array(k - labelHash.length * 2 - 2 - m.length); | |
const db = concat(labelHash, ps, [ | |
0x01 | |
], m); | |
const seed = random_bytes(labelHash.length); | |
const dbMask = mgf1(seed, k - labelHash.length - 1, algorithm); | |
const maskedDb = xor(db, dbMask); | |
const seedMask = mgf1(maskedDb, labelHash.length, algorithm); | |
const maskedSeed = xor(seed, seedMask); | |
return concat([ | |
0x00 | |
], maskedSeed, maskedDb); | |
} | |
function eme_oaep_decode(label, c, k, algorithm) { | |
const labelHash = new Uint8Array(digest(algorithm, label)); | |
const maskedSeed = c.slice(1, 1 + labelHash.length); | |
const maskedDb = c.slice(1 + labelHash.length); | |
const seedMask = mgf1(maskedDb, labelHash.length, algorithm); | |
const seed = xor(maskedSeed, seedMask); | |
const dbMask = mgf1(seed, k - labelHash.length - 1, algorithm); | |
const db = xor(maskedDb, dbMask); | |
let ptr = labelHash.length; | |
while(ptr < db.length && db[ptr] === 0)ptr++; | |
return db.slice(ptr + 1); | |
} | |
function ber_decode(bytes, from, to) { | |
return ber_next(bytes); | |
} | |
function ber_sequence(bytes, from, length) { | |
const end = from + length; | |
let res = []; | |
let ptr = from; | |
while(ptr < end){ | |
const next = ber_next(bytes, ptr); | |
res.push(next); | |
ptr += next.totalLength; | |
} | |
return res; | |
} | |
function ber_integer(bytes, from, length) { | |
let n = 0n; | |
for (const b of bytes.slice(from, from + length)){ | |
n = (n << 8n) + BigInt(b); | |
} | |
return n; | |
} | |
function ber_oid(bytes, from, length) { | |
const id = [ | |
bytes[from] / 40 | 0, | |
bytes[from] % 40 | |
]; | |
let value = 0; | |
for (const b of bytes.slice(from + 1, from + length)){ | |
if (b > 128) value += value * 127 + (b - 128); | |
else { | |
value = value * 128 + b; | |
id.push(value); | |
value = 0; | |
} | |
} | |
return id.join("."); | |
} | |
function ber_unknown(bytes, from, length) { | |
return bytes.slice(from, from + length); | |
} | |
function ber_simple(n) { | |
if (Array.isArray(n.value)) return n.value.map((x)=>ber_simple(x) | |
); | |
return n.value; | |
} | |
function ber_next(bytes, from, to) { | |
if (!from) from = 0; | |
if (!to) to = bytes.length; | |
let ptr = from; | |
const type = bytes[ptr++]; | |
let size = bytes[ptr++]; | |
if ((size & 0x80) > 0) { | |
let ext = size - 0x80; | |
size = 0; | |
while(--ext >= 0){ | |
size = (size << 8) + bytes[ptr++]; | |
} | |
} | |
let value = null; | |
if (type === 0x30) { | |
value = ber_sequence(bytes, ptr, size); | |
} else if (type === 0x2) { | |
value = ber_integer(bytes, ptr, size); | |
} else if (type === 0x3) { | |
value = ber_sequence(bytes, ptr + 1, size - 1); | |
} else if (type === 0x5) { | |
value = null; | |
} else if (type === 0x6) { | |
value = ber_oid(bytes, ptr, size); | |
} else { | |
value = ber_unknown(bytes, ptr, size); | |
} | |
return { | |
totalLength: ptr - from + size, | |
type, | |
length: size, | |
value | |
}; | |
} | |
class RawBinary extends Uint8Array { | |
hex() { | |
return [ | |
...this | |
].map((x)=>x.toString(16).padStart(2, "0") | |
).join(""); | |
} | |
binary() { | |
return this; | |
} | |
base64() { | |
return btoa(String.fromCharCode.apply(null, [ | |
...this | |
])); | |
} | |
base64url() { | |
let a = btoa(String.fromCharCode.apply(null, [ | |
...this | |
])).replace(/=/g, ""); | |
a = a.replace(/\+/g, "-"); | |
a = a.replace(/\//g, "_"); | |
return a; | |
} | |
base32() { | |
const lookup3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; | |
const trim = [ | |
0x0, | |
0x1, | |
0x3, | |
0x7, | |
0xf, | |
0x1f, | |
0x3f, | |
0x7f, | |
0xff | |
]; | |
let output = ""; | |
let bits = 0; | |
let current = 0; | |
for(let i33 = 0; i33 < this.length; i33++){ | |
current = (current << 8) + this[i33]; | |
bits += 8; | |
while(bits >= 5){ | |
bits -= 5; | |
output += lookup3[current >> bits]; | |
current = current & trim[bits]; | |
} | |
} | |
if (bits > 0) { | |
output += lookup3[current << 5 - bits]; | |
} | |
return output; | |
} | |
toString() { | |
return new TextDecoder().decode(this); | |
} | |
} | |
function rsaep(n, e, m) { | |
return power_mod(m, e, n); | |
} | |
function rsadp(key, c) { | |
if (!key.d) throw "Invalid RSA key"; | |
if (key.dp && key.dq && key.qi && key.q && key.p) { | |
const m1 = power_mod(c % key.p, key.dp, key.p); | |
const m2 = power_mod(c % key.q, key.dq, key.q); | |
let h = 0n; | |
if (m1 >= m2) { | |
h = key.qi * (m1 - m2) % key.p; | |
} else { | |
h = key.qi * (m1 - m2 + key.p * (key.p / key.q)) % key.p; | |
} | |
return (m2 + h * key.q) % (key.q * key.p); | |
} else { | |
return power_mod(c, key.d, key.n); | |
} | |
} | |
function rsa_oaep_encrypt(bytes, n, e, m, algorithm) { | |
const em = eme_oaep_encode(new Uint8Array(0), m, bytes, algorithm); | |
const msg = os2ip(em); | |
const c = rsaep(n, e, msg); | |
return i2osp(c, bytes); | |
} | |
function rsa_oaep_decrypt(key, c, algorithm) { | |
const em = rsadp(key, os2ip(c)); | |
const m = eme_oaep_decode(new Uint8Array(0), i2osp(em, key.length), key.length, algorithm); | |
return m; | |
} | |
function rsa_pkcs1_encrypt(bytes, n, e, m) { | |
const p = concat([ | |
0x00, | |
0x02 | |
], random_bytes(bytes - m.length - 3), [ | |
0x00 | |
], m); | |
const msg = os2ip(p); | |
const c = rsaep(n, e, msg); | |
return i2osp(c, bytes); | |
} | |
function rsa_pkcs1_decrypt(key, c) { | |
const em = i2osp(rsadp(key, os2ip(c)), key.length); | |
if (em[0] !== 0) throw "Decryption error"; | |
if (em[1] !== 0x02) throw "Decryption error"; | |
let psCursor = 2; | |
for(; psCursor < em.length; psCursor++){ | |
if (em[psCursor] === 0x00) break; | |
} | |
if (psCursor < 10) throw "Decryption error"; | |
return em.slice(psCursor + 1); | |
} | |
function rsa_pkcs1_verify(key, s, m) { | |
if (!key.e) throw "Invalid RSA key"; | |
let em = i2osp(rsaep(key.n, key.e, os2ip(s)), key.length); | |
if (em[0] !== 0) throw "Decryption error"; | |
if (em[1] !== 0x01) throw "Decryption error"; | |
let psCursor = 2; | |
for(; psCursor < em.length; psCursor++){ | |
if (em[psCursor] === 0x00) break; | |
} | |
if (psCursor < 10) throw "Decryption error"; | |
em = em.slice(psCursor + 1); | |
const ber = ber_simple(ber_decode(em)); | |
const decryptedMessage = ber[1]; | |
if (decryptedMessage.length !== m.length) return false; | |
for(let i34 = 0; i34 < decryptedMessage.length; i34++){ | |
if (decryptedMessage[i34] !== m[i34]) return false; | |
} | |
return true; | |
} | |
function rsa_pkcs1_sign(bytes, n, d, message, algorithm) { | |
const oid = [ | |
0x30, | |
0x0d, | |
0x06, | |
0x09, | |
0x60, | |
0x86, | |
0x48, | |
0x01, | |
0x65, | |
0x03, | |
0x04, | |
0x02, | |
algorithm === "sha512" ? 0x03 : 0x01, | |
0x05, | |
0x00, | |
]; | |
const der = [ | |
0x30, | |
message.length + 2 + oid.length, | |
...oid, | |
0x04, | |
message.length, | |
...message, | |
]; | |
const ps = new Array(bytes - 3 - der.length).fill(0xff); | |
const em = new Uint8Array([ | |
0x00, | |
0x01, | |
...ps, | |
0x00, | |
...der | |
]); | |
const msg = os2ip(em); | |
const c = rsaep(n, d, msg); | |
return new RawBinary(i2osp(c, bytes)); | |
} | |
function emsa_pss_encode(m, emBits, sLen, algorithm) { | |
const mHash = digest(algorithm, m); | |
const hLen = mHash.length; | |
const emLen = Math.ceil(emBits / 8); | |
if (emLen < hLen + sLen + 2) throw "Encoding Error"; | |
const salt = new Uint8Array(sLen); | |
crypto.getRandomValues(salt); | |
const m1 = new Uint8Array([ | |
0x0, | |
0x0, | |
0x0, | |
0x0, | |
0x0, | |
0x0, | |
0x0, | |
0x0, | |
...mHash, | |
...salt | |
]); | |
const h = digest(algorithm, m1); | |
const ps = new Uint8Array(emLen - sLen - hLen - 2); | |
const db = new Uint8Array([ | |
...ps, | |
0x01, | |
...salt | |
]); | |
const dbMask = mgf1(h, emLen - hLen - 1, algorithm); | |
const maskedDB = xor(db, dbMask); | |
const leftMost = 8 * emLen - emBits; | |
maskedDB[0] = maskedDB[0] & 0xff >> leftMost; | |
return new Uint8Array([ | |
...maskedDB, | |
...h, | |
0xbc | |
]); | |
} | |
function emsa_pss_verify(m, em, emBits, sLen, algorithm) { | |
const mHash = digest(algorithm, m); | |
const hLen = mHash.length; | |
const emLen = Math.ceil(emBits / 8); | |
if (emLen < hLen + sLen + 2) return false; | |
if (em[em.length - 1] !== 0xbc) return false; | |
const maskedDB = em.slice(0, emLen - hLen - 1); | |
const h = em.slice(emLen - hLen - 1, emLen - 1); | |
const leftMost = 8 * emLen - emBits; | |
if (maskedDB[0] >> 8 - leftMost != 0) return false; | |
const dbMask = mgf1(h, emLen - hLen - 1, algorithm); | |
const db = xor(maskedDB, dbMask); | |
db[0] = db[0] & 0xff >> leftMost; | |
for(let i35 = 1; i35 < emLen - hLen - sLen - 2; i35++){ | |
if (db[i35] !== 0x00) return false; | |
} | |
if (db[emLen - hLen - sLen - 2] !== 0x01) return false; | |
const salt = db.slice(emLen - hLen - sLen - 1); | |
const m1 = new Uint8Array([ | |
0x0, | |
0x0, | |
0x0, | |
0x0, | |
0x0, | |
0x0, | |
0x0, | |
0x0, | |
...mHash, | |
...salt | |
]); | |
const h1 = digest(algorithm, m1); | |
for(let i110 = 0; i110 < hLen; i110++){ | |
if (h1[i110] !== h[i110]) return false; | |
} | |
return true; | |
} | |
function rsassa_pss_sign(key, m, algorithm) { | |
if (!key.d) throw "Invalid RSA Key"; | |
const hLen = digestLength(algorithm); | |
let em = emsa_pss_encode(m, key.length * 8 - 1, hLen, algorithm); | |
return new RawBinary(i2osp(rsaep(key.n, key.d, os2ip(em)), key.length)); | |
} | |
function rsassa_pss_verify(key, m, signature, algorithm) { | |
if (!key.e) throw "Invalid RSA Key"; | |
const hLen = digestLength(algorithm); | |
const em = i2osp(rsaep(key.n, key.e, os2ip(signature)), key.length); | |
return emsa_pss_verify(m, em, key.length * 8 - 1, hLen, algorithm); | |
} | |
class PureRSA { | |
static async encrypt(key, message, options) { | |
if (!key.e) throw "Invalid RSA key"; | |
if (options.padding === "oaep") { | |
return new RawBinary(rsa_oaep_encrypt(key.length, key.n, key.e, message, options.hash)); | |
} else if (options.padding === "pkcs1") { | |
return new RawBinary(rsa_pkcs1_encrypt(key.length, key.n, key.e, message)); | |
} | |
throw "Invalid parameters"; | |
} | |
static async decrypt(key, ciper, options) { | |
if (!key.d) throw "Invalid RSA key"; | |
if (options.padding === "oaep") { | |
return new RawBinary(rsa_oaep_decrypt(key, ciper, options.hash)); | |
} else if (options.padding === "pkcs1") { | |
return new RawBinary(rsa_pkcs1_decrypt(key, ciper)); | |
} | |
throw "Invalid parameters"; | |
} | |
static async verify(key, signature, message, options) { | |
if (!key.e) throw "Invalid RSA key"; | |
if (options.algorithm === "rsassa-pkcs1-v1_5") { | |
return rsa_pkcs1_verify(key, signature, digest(options.hash, message)); | |
} else { | |
return rsassa_pss_verify(key, message, signature, options.hash); | |
} | |
} | |
static async sign(key, message, options) { | |
if (!key.d) throw "You need private key to sign the message"; | |
if (options.algorithm === "rsassa-pkcs1-v1_5") { | |
return rsa_pkcs1_sign(key.length, key.n, key.d, digest(options.hash, message), options.hash); | |
} else { | |
return rsassa_pss_sign(key, message, options.hash); | |
} | |
} | |
} | |
class encode5 { | |
static hex(data) { | |
if (data.length % 2 !== 0) throw "Invalid hex format"; | |
const output = new RawBinary(data.length >> 1); | |
let ptr = 0; | |
for(let i36 = 0; i36 < data.length; i36 += 2){ | |
output[ptr++] = parseInt(data.substr(i36, 2), 16); | |
} | |
return output; | |
} | |
static bigint(n) { | |
const bytes = []; | |
while(n > 0){ | |
bytes.push(Number(n & 255n)); | |
n = n >> 8n; | |
} | |
bytes.reverse(); | |
return new RawBinary(bytes); | |
} | |
static string(data) { | |
return new RawBinary(new TextEncoder().encode(data)); | |
} | |
static base64(data) { | |
return new RawBinary(Uint8Array.from(atob(data), (c)=>c.charCodeAt(0) | |
)); | |
} | |
static base64url(data) { | |
let input = data.replace(/-/g, "+").replace(/_/g, "/"); | |
const pad = input.length % 4; | |
if (pad) { | |
if (pad === 1) throw "Invalid length"; | |
input += new Array(5 - pad).join("="); | |
} | |
return encode5.base64(input); | |
} | |
static binary(data) { | |
return new RawBinary(data); | |
} | |
static base32(data) { | |
data = data.toUpperCase(); | |
data = data.replace(/=+$/g, ""); | |
const lookup4 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; | |
const size = data.length * 5 >> 3; | |
const output = new RawBinary(size); | |
let ptr = 0; | |
let bits = 0; | |
let current = 0; | |
for(let i37 = 0; i37 < data.length; i37++){ | |
const value = lookup4.indexOf(data[i37]); | |
if (value < 0) throw "Invalid base32 format"; | |
current = (current << 5) + value; | |
bits += 5; | |
if (bits >= 8) { | |
bits -= 8; | |
const t = current >> bits; | |
current -= t << bits; | |
output[ptr++] = t; | |
} | |
} | |
return output; | |
} | |
} | |
function detect_format(key) { | |
if (typeof key === "object") { | |
if (key.kty === "RSA") return "jwk"; | |
} else if (typeof key === "string") { | |
if (key.substr(0, "-----".length) === "-----") return "pem"; | |
} | |
throw new TypeError("Unsupported key format"); | |
} | |
function rsa_import_jwk(key) { | |
if (typeof key !== "object") throw new TypeError("Invalid JWK format"); | |
if (!key.n) throw new TypeError("RSA key requires n"); | |
const n = os2ip(encode5.base64url(key.n)); | |
return { | |
e: key.e ? os2ip(encode5.base64url(key.e)) : undefined, | |
n: os2ip(encode5.base64url(key.n)), | |
d: key.d ? os2ip(encode5.base64url(key.d)) : undefined, | |
p: key.p ? os2ip(encode5.base64url(key.p)) : undefined, | |
q: key.q ? os2ip(encode5.base64url(key.q)) : undefined, | |
dp: key.dp ? os2ip(encode5.base64url(key.dp)) : undefined, | |
dq: key.dq ? os2ip(encode5.base64url(key.dq)) : undefined, | |
qi: key.qi ? os2ip(encode5.base64url(key.qi)) : undefined, | |
length: get_key_size(n) | |
}; | |
} | |
function rsa_import_pem_cert(key) { | |
const trimmedKey = key.substr(27, key.length - 53); | |
const parseKey = ber_simple(ber_decode(base64_to_binary(trimmedKey))); | |
return { | |
length: get_key_size(parseKey[0][5][1][0][0]), | |
n: parseKey[0][5][1][0][0], | |
e: parseKey[0][5][1][0][1] | |
}; | |
} | |
function rsa_import_pem_private(key) { | |
const trimmedKey = key.substr(31, key.length - 61); | |
const parseKey = ber_simple(ber_decode(base64_to_binary(trimmedKey))); | |
return { | |
n: parseKey[1], | |
d: parseKey[3], | |
e: parseKey[2], | |
p: parseKey[4], | |
q: parseKey[5], | |
dp: parseKey[6], | |
dq: parseKey[7], | |
qi: parseKey[8], | |
length: get_key_size(parseKey[1]) | |
}; | |
} | |
function rsa_import_pem_private_pkcs8(key) { | |
const trimmedKey = key.substr(27, key.length - 57); | |
const parseWrappedKey = ber_simple(ber_decode(base64_to_binary(trimmedKey))); | |
const parseKey = ber_simple(ber_decode(parseWrappedKey[2])); | |
return { | |
n: parseKey[1], | |
d: parseKey[3], | |
e: parseKey[2], | |
p: parseKey[4], | |
q: parseKey[5], | |
dp: parseKey[6], | |
dq: parseKey[7], | |
qi: parseKey[8], | |
length: get_key_size(parseKey[1]) | |
}; | |
} | |
function rsa_import_pem_public(key) { | |
const trimmedKey = key.substr(26, key.length - 51); | |
const parseKey = ber_simple(ber_decode(base64_to_binary(trimmedKey))); | |
return { | |
length: get_key_size(parseKey[1][0][0]), | |
n: parseKey[1][0][0], | |
e: parseKey[1][0][1] | |
}; | |
} | |
function rsa_import_pem(key) { | |
if (typeof key !== "string") throw new TypeError("PEM key must be string"); | |
const trimmedKey = key.trim(); | |
const maps = [ | |
[ | |
"-----BEGIN RSA PRIVATE KEY-----", | |
rsa_import_pem_private | |
], | |
[ | |
"-----BEGIN PRIVATE KEY-----", | |
rsa_import_pem_private_pkcs8 | |
], | |
[ | |
"-----BEGIN PUBLIC KEY-----", | |
rsa_import_pem_public | |
], | |
[ | |
"-----BEGIN CERTIFICATE-----", | |
rsa_import_pem_cert | |
], | |
]; | |
for (const [prefix, func] of maps){ | |
if (trimmedKey.indexOf(prefix) === 0) return func(trimmedKey); | |
} | |
throw new TypeError("Unsupported key format"); | |
} | |
function rsa_import_key(key, format) { | |
const finalFormat = format === "auto" ? detect_format(key) : format; | |
if (finalFormat === "jwk") return rsa_import_jwk(key); | |
if (finalFormat === "pem") return rsa_import_pem(key); | |
throw new TypeError("Unsupported key format"); | |
} | |
function createSizeBuffer(size) { | |
if (size <= 127) return new Uint8Array([ | |
size | |
]); | |
const bytes = []; | |
while(size > 0){ | |
bytes.push(size & 0xff); | |
size = size >> 8; | |
} | |
bytes.reverse(); | |
return new Uint8Array([ | |
0x80 + bytes.length, | |
...bytes | |
]); | |
} | |
class BER { | |
static createSequence(children) { | |
const size = children.reduce((accumlatedSize, child)=>accumlatedSize + child.length | |
, 0); | |
return new Uint8Array([ | |
0x30, | |
...createSizeBuffer(size), | |
...children.reduce((buffer, child)=>[ | |
...buffer, | |
...child | |
] | |
, []), | |
]); | |
} | |
static createNull() { | |
return new Uint8Array([ | |
0x05, | |
0x00 | |
]); | |
} | |
static createBoolean(value) { | |
return new Uint8Array([ | |
0x01, | |
0x01, | |
value ? 0x01 : 0x00 | |
]); | |
} | |
static createInteger(value) { | |
if (typeof value === "number") return BER.createBigInteger(BigInt(value)); | |
return BER.createBigInteger(value); | |
} | |
static createBigInteger(value) { | |
if (value === 0n) return new Uint8Array([ | |
0x02, | |
0x01, | |
0x00 | |
]); | |
const isNegative = value < 0; | |
const content = []; | |
let n = isNegative ? -value : value; | |
while(n > 0n){ | |
content.push(Number(n & 255n)); | |
n = n >> 8n; | |
} | |
if (!isNegative) { | |
if (content[content.length - 1] & 0x80) content.push(0x00); | |
} else { | |
for(let i38 = 0; i38 < content.length; i38++)content[i38] = 256 - content[i38]; | |
if (!(content[content.length - 1] & 0x80)) content.push(0xff); | |
} | |
content.reverse(); | |
return new Uint8Array([ | |
0x02, | |
...createSizeBuffer(content.length), | |
...content, | |
]); | |
} | |
static createBitString(value) { | |
return new Uint8Array([ | |
0x03, | |
...createSizeBuffer(value.length + 1), | |
0x00, | |
...value, | |
]); | |
} | |
} | |
function add_line_break(base64_str) { | |
const lines = []; | |
for(let i39 = 0; i39 < base64_str.length; i39 += 64){ | |
lines.push(base64_str.substr(i39, 64)); | |
} | |
return lines.join("\n"); | |
} | |
function rsa_export_pkcs8_public(key) { | |
const content = BER.createSequence([ | |
BER.createSequence([ | |
new Uint8Array([ | |
0x06, | |
0x09, | |
0x2a, | |
0x86, | |
0x48, | |
0x86, | |
0xf7, | |
0x0d, | |
0x01, | |
0x01, | |
0x01, | |
]), | |
BER.createNull(), | |
]), | |
BER.createBitString(BER.createSequence([ | |
BER.createInteger(key.n), | |
BER.createInteger(key.e || 0n), | |
])), | |
]); | |
return "-----BEGIN PUBLIC KEY-----\n" + add_line_break(encode5.binary(content).base64()) + "\n-----END PUBLIC KEY-----\n"; | |
} | |
function rsa_export_pkcs8_private(key) { | |
const content = BER.createSequence([ | |
BER.createInteger(0), | |
BER.createInteger(key.n), | |
BER.createInteger(key.e || 0n), | |
BER.createInteger(key.d || 0n), | |
BER.createInteger(key.p || 0n), | |
BER.createInteger(key.q || 0n), | |
BER.createInteger(key.dp || 0n), | |
BER.createInteger(key.dq || 0n), | |
BER.createInteger(key.qi || 0n), | |
]); | |
const ber = encode5.binary(content).base64(); | |
return "-----BEGIN RSA PRIVATE KEY-----\n" + add_line_break(ber) + "\n-----END RSA PRIVATE KEY-----\n"; | |
} | |
class RSAKey { | |
n; | |
e; | |
d; | |
p; | |
q; | |
dp; | |
dq; | |
qi; | |
length; | |
constructor(params){ | |
this.n = params.n; | |
this.e = params.e; | |
this.d = params.d; | |
this.p = params.p; | |
this.q = params.q; | |
this.dp = params.dp; | |
this.dq = params.dq; | |
this.qi = params.qi; | |
this.length = params.length; | |
} | |
pem() { | |
if (this.d) { | |
return rsa_export_pkcs8_private(this); | |
} else { | |
return rsa_export_pkcs8_public(this); | |
} | |
} | |
jwk() { | |
let jwk = { | |
kty: "RSA", | |
n: encode5.bigint(this.n).base64url() | |
}; | |
if (this.d) jwk = { | |
...jwk, | |
d: encode5.bigint(this.d).base64url() | |
}; | |
if (this.e) jwk = { | |
...jwk, | |
e: encode5.bigint(this.e).base64url() | |
}; | |
if (this.p) jwk = { | |
...jwk, | |
p: encode5.bigint(this.p).base64url() | |
}; | |
if (this.q) jwk = { | |
...jwk, | |
q: encode5.bigint(this.q).base64url() | |
}; | |
if (this.dp) jwk = { | |
...jwk, | |
dp: encode5.bigint(this.dp).base64url() | |
}; | |
if (this.dq) jwk = { | |
...jwk, | |
dq: encode5.bigint(this.dq).base64url() | |
}; | |
if (this.qi) jwk = { | |
...jwk, | |
qi: encode5.bigint(this.qi).base64url() | |
}; | |
return jwk; | |
} | |
} | |
function computeMessage(m) { | |
return typeof m === "string" ? new TextEncoder().encode(m) : m; | |
} | |
function computeOption(options) { | |
return { | |
hash: "sha1", | |
padding: "oaep", | |
...options | |
}; | |
} | |
class RSA { | |
key; | |
constructor(key){ | |
this.key = key; | |
} | |
async encrypt(m, options) { | |
const computedOption = computeOption(options); | |
const func = WebCryptoRSA.isSupported(computedOption) ? WebCryptoRSA.encrypt : PureRSA.encrypt; | |
return new RawBinary(await func(this.key, computeMessage(m), computedOption)); | |
} | |
async decrypt(m, options) { | |
const computedOption = computeOption(options); | |
const func = WebCryptoRSA.isSupported(computedOption) ? WebCryptoRSA.decrypt : PureRSA.decrypt; | |
return new RawBinary(await func(this.key, m, computedOption)); | |
} | |
async verify(signature, message, options) { | |
const computedOption = { | |
algorithm: "rsassa-pkcs1-v1_5", | |
hash: "sha256", | |
...options | |
}; | |
return await PureRSA.verify(this.key, signature, computeMessage(message), computedOption); | |
} | |
async sign(message, options) { | |
const computedOption = { | |
algorithm: "rsassa-pkcs1-v1_5", | |
hash: "sha256", | |
...options | |
}; | |
return await PureRSA.sign(this.key, computeMessage(message), computedOption); | |
} | |
static parseKey(key, format = "auto") { | |
return this.importKey(key, format); | |
} | |
static importKey(key, format = "auto") { | |
return new RSAKey(rsa_import_key(key, format)); | |
} | |
} | |
function assertNever(alg, message) { | |
throw new RangeError(message); | |
} | |
function safeCompare(a, b) { | |
const strA = String(a); | |
const lenA = strA.length; | |
let strB = String(b); | |
let result = 0; | |
if (lenA !== strB.length) { | |
strB = strA; | |
result = 1; | |
} | |
for(let i40 = 0; i40 < lenA; i40++){ | |
result |= strA.charCodeAt(i40) ^ strB.charCodeAt(i40); | |
} | |
return result === 0; | |
} | |
async function encrypt(algorithm, key, message) { | |
switch(algorithm){ | |
case "none": | |
return ""; | |
case "HS256": | |
return new HmacSha256(key).update(message).toString(); | |
case "HS512": | |
return new HmacSha512(key).update(message).toString(); | |
case "RS256": | |
return (await new RSA(RSA.parseKey(key)).sign(message, { | |
algorithm: "rsassa-pkcs1-v1_5", | |
hash: "sha256" | |
})).hex(); | |
case "RS512": | |
return (await new RSA(RSA.parseKey(key)).sign(message, { | |
algorithm: "rsassa-pkcs1-v1_5", | |
hash: "sha512" | |
})).hex(); | |
case "PS256": | |
return (await new RSA(RSA.parseKey(key)).sign(message, { | |
algorithm: "rsassa-pss", | |
hash: "sha256" | |
})).hex(); | |
case "PS512": | |
return (await new RSA(RSA.parseKey(key)).sign(message, { | |
algorithm: "rsassa-pss", | |
hash: "sha512" | |
})).hex(); | |
default: | |
assertNever(algorithm, "no matching crypto algorithm in the header: " + algorithm); | |
} | |
} | |
async function verify({ signature , key , algorithm , signingInput }) { | |
try { | |
switch(algorithm){ | |
case "none": | |
case "HS256": | |
case "HS512": | |
{ | |
return safeCompare(signature, await encrypt(algorithm, key, signingInput)); | |
} | |
case "RS256": | |
{ | |
return await new RSA(RSA.parseKey(key)).verify(decodeString(signature), signingInput, { | |
algorithm: "rsassa-pkcs1-v1_5", | |
hash: "sha256" | |
}); | |
} | |
case "RS512": | |
{ | |
return await new RSA(RSA.parseKey(key)).verify(decodeString(signature), signingInput, { | |
algorithm: "rsassa-pkcs1-v1_5", | |
hash: "sha512" | |
}); | |
} | |
case "PS256": | |
{ | |
return await new RSA(RSA.parseKey(key)).verify(decodeString(signature), signingInput, { | |
algorithm: "rsassa-pss", | |
hash: "sha256" | |
}); | |
} | |
case "PS512": | |
{ | |
return await new RSA(RSA.parseKey(key)).verify(decodeString(signature), signingInput, { | |
algorithm: "rsassa-pss", | |
hash: "sha512" | |
}); | |
} | |
default: | |
assertNever(algorithm, "no matching crypto algorithm in the header: " + algorithm); | |
} | |
} catch (err) { | |
throw err instanceof Error ? err : new Error(err); | |
} | |
} | |
function verify1(algorithm, jwtAlg) { | |
return Array.isArray(algorithm) ? algorithm.includes(jwtAlg) : algorithm === jwtAlg; | |
} | |
new TextEncoder(); | |
const decoder2 = new TextDecoder(); | |
function isExpired(exp, leeway = 0) { | |
return exp + leeway < Date.now() / 1000; | |
} | |
function isTooEarly(nbf, leeway = 0) { | |
return nbf - leeway > Date.now() / 1000; | |
} | |
function isObject(obj) { | |
return obj !== null && typeof obj === "object" && Array.isArray(obj) === false; | |
} | |
function hasInvalidTimingClaims(...claimValues) { | |
return claimValues.some((claimValue)=>claimValue !== undefined ? typeof claimValue !== "number" : false | |
); | |
} | |
function decode5(jwt) { | |
const [header, payload, signature] = jwt.split(".").map(mod.decode).map((uint8Array, index)=>{ | |
switch(index){ | |
case 0: | |
case 1: | |
try { | |
return JSON.parse(decoder2.decode(uint8Array)); | |
} catch { | |
break; | |
} | |
case 2: | |
return encodeToString(uint8Array); | |
} | |
throw TypeError("The serialization is invalid."); | |
}); | |
if (typeof signature !== "string") { | |
throw new Error(`The signature is missing.`); | |
} | |
if (typeof header?.alg !== "string") { | |
throw new Error(`The header 'alg' parameter must be a string.`); | |
} | |
if (!isObject(payload)) { | |
throw new Error(`The jwt claims set is not a JSON object.`); | |
} | |
if (hasInvalidTimingClaims(payload.exp, payload.nbf)) { | |
throw new Error(`The jwt has an invalid 'exp' or 'nbf' claim.`); | |
} | |
if (typeof payload.exp === "number" && isExpired(payload.exp, 1)) { | |
throw RangeError("The jwt is expired."); | |
} | |
if (typeof payload.nbf === "number" && isTooEarly(payload.nbf, 1)) { | |
throw RangeError("The jwt is used too early."); | |
} | |
return { | |
header, | |
payload, | |
signature | |
}; | |
} | |
async function verify2(jwt, key, algorithm) { | |
const { header , payload , signature } = decode5(jwt); | |
if (!verify1(algorithm, header.alg)) { | |
throw new Error(`The jwt's algorithm does not match the specified algorithm '${algorithm}'.`); | |
} | |
if ("crit" in header) { | |
throw new Error("The 'crit' header parameter is currently not supported by this module."); | |
} | |
if (!await verify({ | |
signature, | |
key, | |
algorithm: header.alg, | |
signingInput: jwt.slice(0, jwt.lastIndexOf(".")) | |
})) { | |
throw new Error("The jwt's signature does not match the verification signature."); | |
} | |
return payload; | |
} | |
addEventListener("fetch", event => { | |
event.respondWith(handleRequest(event.request)) | |
}); | |
async function handleRequest(request) { | |
const accessToken = request.headers.get('accessToken'); | |
const {sub, email} = await verify2(accessToken, JWT_SECRET, "HS256"); | |
return new Response(JSON.stringify({sub, email}), { | |
headers: { | |
'content-type': 'application/json;charset=UTF-8' | |
} | |
}); | |
} |
I don't recall which library I used but I only had to author the worker once and it's been working ever since. I followed one of the tutorials Supabase had on JWTs.
You have to set up JWT_SECRET
to get passed in from the env.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
sub
is the subscription ID or PK of the user.