From: miha-q <>
Date: Mon, 20 Jan 2025 18:27:02 +0000 (-0500)
Subject: Mon Jan 20 01:27:02 PM EST 2025
X-Git-Url: http://www.foleosoft.com/?a=commitdiff_plain;h=2544842bcb778c7ccee76444b461625a0fbe8e33;p=QAnsel.git
Mon Jan 20 01:27:02 PM EST 2025
---
diff --git a/src/www/imports/code.html b/src/www/imports/code.html
index 4d2ba5e..0ee9e62 100644
--- a/src/www/imports/code.html
+++ b/src/www/imports/code.html
@@ -1,10 +1,10 @@
- EstoulsAPI
+ RosadoAPI
-
+
@@ -107,7 +107,7 @@ else
{
var a = document.createElement("a");
a.href = "/apk";
- a.download = "EstoulsAPI.apk";
+ a.download = "RosadoAPI.apk";
a.style.display = "none";
document.body.appendChild(a);
a.click();
@@ -212,10 +212,10 @@ else
return;
}
- EstoulsAPI.username = dat[0];
- EstoulsAPI.apikey = dat[1];
- EstoulsAPI.endpoint = "https://" + dat[2];
- EstoulsAPI.request(IstinaEditor.getText()).then(x =>
+ RosadoAPI.username = dat[0];
+ RosadoAPI.apikey = dat[1];
+ RosadoAPI.endpoint = "https://" + dat[2];
+ RosadoAPI.request(IstinaEditor.getText()).then(x =>
{
if (x.success && x.response.trim().length > 0)
{
diff --git a/src/www/imports/estouls-api.js b/src/www/imports/estouls-api.js
deleted file mode 100644
index 73760d7..0000000
--- a/src/www/imports/estouls-api.js
+++ /dev/null
@@ -1,357 +0,0 @@
-var EstoulsAPI =
-{
- username: undefined,
- apikey: undefined,
- endpoint: undefined,
-
- Math32:
- {
- clamp: a =>
- {
- while (a < 0 || a > 0xFFFFFFFF)
- a += a < 0 ? 0x100000000 : -0x100000000;
- return a;
- },
- shl: (a, b) => EstoulsAPI.Math32.clamp(a << b),
- shr: (a, b) => EstoulsAPI.Math32.clamp(a >>> b),
- rtl: (a, b) => EstoulsAPI.Math32.clamp((a << b) | (a >>> (32 - b))),
- rtr: (a, b) => EstoulsAPI.Math32.clamp((a >>> b) | (a << (32 - b))),
- add: (a, b) => EstoulsAPI.Math32.clamp(a + b),
- sub: (a, b) => EstoulsAPI.Math32.clamp(a + b),
- or: (a, b) => EstoulsAPI.Math32.clamp(a | b),
- xor: (a, b) => EstoulsAPI.Math32.clamp(a ^ b)
- },
- HMACSHA256:
- {
- sign: async (key, msg) =>
- {
- key = new Uint8Array(key);
- msg = new Uint8Array(msg);
- var ikey = await crypto.subtle.importKey
- (
- "raw",
- key,
- { name: "HMAC", hash: { name: "SHA-256" }},
- false,
- ["sign", "verify"]
- );
- return new Uint8Array(await window.crypto.subtle.sign({ name: "HMAC", }, ikey, msg));
- }
- },
- ChaCha20:
- {
- QR: (cc, a, b, c, d) =>
- {
- cc[a] = EstoulsAPI.Math32.add(cc[a], cc[b]);
- cc[d] = EstoulsAPI.Math32.xor(cc[d], cc[a]);
- cc[d] = EstoulsAPI.Math32.rtl(cc[d], 16);
-
- cc[c] = EstoulsAPI.Math32.add(cc[c], cc[d]);
- cc[b] = EstoulsAPI.Math32.xor(cc[b], cc[c]);
- cc[b] = EstoulsAPI.Math32.rtl(cc[b], 12);
-
- cc[a] = EstoulsAPI.Math32.add(cc[a], cc[b]);
- cc[d] = EstoulsAPI.Math32.xor(cc[d], cc[a]);
- cc[d] = EstoulsAPI.Math32.rtl(cc[d], 8);
-
- cc[c] = EstoulsAPI.Math32.add(cc[c], cc[d]);
- cc[b] = EstoulsAPI.Math32.xor(cc[b], cc[c]);
- cc[b] = EstoulsAPI.Math32.rtl(cc[b], 7);
- },
- DR: (cc) =>
- {
- EstoulsAPI.ChaCha20.QR(cc, 0, 4, 8, 12);
- EstoulsAPI.ChaCha20.QR(cc, 1, 5, 9, 13);
- EstoulsAPI.ChaCha20.QR(cc, 2, 6, 10, 14);
- EstoulsAPI.ChaCha20.QR(cc, 3, 7, 11, 15);
- EstoulsAPI.ChaCha20.QR(cc, 0, 5, 10, 15);
- EstoulsAPI.ChaCha20.QR(cc, 1, 6, 11, 12);
- EstoulsAPI.ChaCha20.QR(cc, 2, 7, 8, 13);
- EstoulsAPI.ChaCha20.QR(cc, 3, 4, 9, 14);
- },
- CB: (cc) =>
- {
- var i;
- var x = new Array(16);
- for (i = 0; i < 16; i++)
- {
- x[i] = cc[i];
- }
- for (i = 0; i < 10; i++)
- {
- EstoulsAPI.ChaCha20.DR(cc);
- }
- for (i = 0; i < 16; i++)
- {
- cc[i] = EstoulsAPI.Math32.add(cc[i], x[i]);
- }
- },
- S: (cc, cs) =>
- {
- for (var i = 0; i < 16; i++)
- {
- cs[4 * i] = (cc[i] & 0xFF);
- cs[4 * i + 1] = ((cc[i] >> 8) & 0xFF);
- cs[4 * i + 2] = ((cc[i] >> 16) & 0xFF);
- cs[4 * i + 3] = ((cc[i] >> 24) & 0xFF);
- }
- },
- B: (key, nonce, block, out) =>
- {
- var cc =
- [
- 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574,
-
- key[0] | (key[1] << 8) | (key[2] << 16) | (key[3] << 24),
- key[4] | (key[5] << 8) | (key[6] << 16) | (key[7] << 24),
- key[8] | (key[9] << 8) | (key[10] << 16) | (key[11] << 24),
- key[12] | (key[13] << 8) | (key[14] << 16) | (key[15] << 24),
-
- key[16] | (key[17] << 8) | (key[18] << 16) | (key[19] << 24),
- key[20] | (key[21] << 8) | (key[22] << 16) | (key[23] << 24),
- key[24] | (key[25] << 8) | (key[26] << 16) | (key[27] << 24),
- key[28] | (key[29] << 8) | (key[30] << 16) | (key[31] << 24),
-
- block,
-
- nonce[0] | (nonce[1] << 8) | (nonce[2] << 16) | (nonce[3] << 24),
- nonce[4] | (nonce[5] << 8) | (nonce[6] << 16) | (nonce[7] << 24),
- nonce[8] | (nonce[9] << 8) | (nonce[10] << 16) | (nonce[11] << 24)
- ];
-
- EstoulsAPI.ChaCha20.CB(cc);
- EstoulsAPI.ChaCha20.S(cc, out);
- },
- encrypt: async (key, nonce, block, data) =>
- {
- var count = data.length;
- if (count > (274877906944 - block * 64)) return null;
- var ret = new Array(0);
- var ccblock = new Array(64);
- var size = 0;
- while (count > 64)
- {
- ret.length = size + 64;
- EstoulsAPI.ChaCha20.B(key, nonce, block++, ccblock);
- for (var i = 0; i < 64; i++) ret[size + i] = ccblock[i];
- size += 64;
- count -= 64;
- }
- if (count > 0)
- {
- ret.length = size + count;
- EstoulsAPI.ChaCha20.B(key, nonce, block, ccblock);
- for (var i = 0; i < count; i++) ret[size + i] = ccblock[i];
- }
- for (var i = 0; i < data.length; i++) ret[i] ^= data[i];
- return new Uint8Array(ret);
- }
- },
-
- Base64:
- {
- encode: async (x) =>
- {
- return await new Promise(r =>
- {
- const reader = new FileReader();
- reader.addEventListener("load", () => r(reader.result.split(",")[1]));
- reader.readAsDataURL(new Blob([new Uint8Array(x)]));
- });
- },
-
- decode: (b64) =>
- {
- var dec1 = (v) =>
- {
- switch (v)
- {
- case 'A': return 0;
- case 'B': return 1;
- case 'C': return 2;
- case 'D': return 3;
- case 'E': return 4;
- case 'F': return 5;
- case 'G': return 6;
- case 'H': return 7;
- case 'I': return 8;
- case 'J': return 9;
- case 'K': return 10;
- case 'L': return 11;
- case 'M': return 12;
- case 'N': return 13;
- case 'O': return 14;
- case 'P': return 15;
- case 'Q': return 16;
- case 'R': return 17;
- case 'S': return 18;
- case 'T': return 19;
- case 'U': return 20;
- case 'V': return 21;
- case 'W': return 22;
- case 'X': return 23;
- case 'Y': return 24;
- case 'Z': return 25;
- case 'a': return 26;
- case 'b': return 27;
- case 'c': return 28;
- case 'd': return 29;
- case 'e': return 30;
- case 'f': return 31;
- case 'g': return 32;
- case 'h': return 33;
- case 'i': return 34;
- case 'j': return 35;
- case 'k': return 36;
- case 'l': return 37;
- case 'm': return 38;
- case 'n': return 39;
- case 'o': return 40;
- case 'p': return 41;
- case 'q': return 42;
- case 'r': return 43;
- case 's': return 44;
- case 't': return 45;
- case 'u': return 46;
- case 'v': return 47;
- case 'w': return 48;
- case 'x': return 49;
- case 'y': return 50;
- case 'z': return 51;
- case '0': return 52;
- case '1': return 53;
- case '2': return 54;
- case '3': return 55;
- case '4': return 56;
- case '5': return 57;
- case '6': return 58;
- case '7': return 59;
- case '8': return 60;
- case '9': return 61;
- case '+': return 62;
- case '/': return 63;
- }
- return 255;
- };
-
- var ret = new Array(0);
- var buffer = 0;
- var bufferS = 0;
- for (var i = 0; i < b64.length; i++)
- {
- if (b64[i] == '=') { bufferS = 0; continue; };
- var val = dec1(b64[i]);
- if (val == 255) return null;
- buffer = ((buffer << 6) | val) & 0xFFFF;
- bufferS += 6;
- if (bufferS >= 8)
- {
- var shift = (16 - bufferS) & 0xFF;
- buffer = (buffer << shift) & 0xFFFF;
- ret[ret.length] = (buffer >>> 8) & 0xFF;
- buffer = buffer & 0x00FF;
- buffer = (buffer >>> shift) & 0xFFFF;
- bufferS -= 8;
- }
- }
- if (bufferS > 0)
- {
- buffer = (buffer << (16 - bufferS)) & 0xFFFF;
- ret[ret.length] = (buffer >>> 8) & 0xFF;
- }
- return new Uint8Array(ret);
- }
- },
-
- Hex:
- {
- encode: (x) =>
- {
- var ret = "";
- x.forEach(y => { ret += y.toString(16).padStart(2, "0"); });
- return ret;
- },
- decode: (x) =>
- {
- var arr = new Array(0);
- for (var i = 0; i < x.length; i += 2)
- {
- arr[arr.length] = parseInt(x.charAt(i) + x.charAt(i + 1), 16);
- }
- return new Uint8Array(arr);
- }
- },
-
- generateRequest: async (msg) =>
- {
- msg = new TextEncoder().encode(msg);
- var key = EstoulsAPI.Hex.decode(EstoulsAPI.apikey);
- //var sess = crypto.getRandomValues(new Uint8Array(12));
- var r = () => { return Math.floor(Math.random() * 10000) % 256 };;
- var sess = new Uint8Array([r(), r(), r(), r(), r(), r(), r(), r(), r(), r(), r(), r()]);
- var rawdata = await EstoulsAPI.ChaCha20.encrypt(key, sess, 0, msg);
- var dgst = await EstoulsAPI.Hex.encode(await EstoulsAPI.HMACSHA256.sign(key, rawdata));
- var data = await EstoulsAPI.Base64.encode(rawdata);
- var resp = "user=" + EstoulsAPI.username;
- resp += "&sess=" + EstoulsAPI.Hex.encode(sess);
- resp += "&dgst=" + dgst;
- resp += "&data=" + data;
- return resp;
- },
-
- parseResponse: async (msg) =>
- {
- if (!msg.includes("user=") || !msg.includes("&sess=") || !msg.includes("&dgst=") || !msg.includes("&data="))
- {
- return { success: false, response: "invalid response" };
- }
- var user = msg.split("user=")[1].split("&")[0].trim();
- var sess = msg.split("&sess=")[1].split("&")[0].trim();
- var dgst = msg.split("&dgst=")[1].split("&")[0].trim();
- var data = msg.split("&data=")[1].split("&")[0].trim();
-
- if (user != EstoulsAPI.username)
- {
- return { success: false, response: "invalid user in response" };
- }
- data = EstoulsAPI.Base64.decode(data);
- sess = EstoulsAPI.Hex.decode(sess);
- var key = EstoulsAPI.Hex.decode(EstoulsAPI.apikey);
- var sig = await EstoulsAPI.Hex.encode(await EstoulsAPI.HMACSHA256.sign(key, data));
- if (sig != dgst)
- {
- return { success: false, response: "invalid signature" };
- }
- var resp = await EstoulsAPI.ChaCha20.encrypt(key, sess, 0, data);
- return { success: true, response: new TextDecoder().decode(resp) };
- },
-
- request: async (msg) =>
- {
- if (msg.trim().length == 0) return { success: true, response: "" };
- var req = await EstoulsAPI.generateRequest(msg);
- return await new Promise(r =>
- {
- const xhr = new XMLHttpRequest();
- xhr.open("POST", EstoulsAPI.endpoint, true);
- xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
- xhr.onreadystatechange = (x) =>
- {
- if (xhr.readyState === XMLHttpRequest.DONE)
- {
- if (xhr.status === 200)
- {
- EstoulsAPI.parseResponse(xhr.responseText).then(pr => { r(pr); }).catch(x => alert("ERR(3)"));
- }
- else
- {
- r({success: false, response: xhr.status});
- }
- }
- }
- xhr.send(req);
- }).catch(x => alert("ERR(1): " + x));
- }
-
-};
-
diff --git a/src/www/imports/rosado-api.js b/src/www/imports/rosado-api.js
new file mode 100644
index 0000000..bb8d769
--- /dev/null
+++ b/src/www/imports/rosado-api.js
@@ -0,0 +1,356 @@
+var RosadoAPI =
+{
+ username: undefined,
+ apikey: undefined,
+ endpoint: undefined,
+
+ Math32:
+ {
+ clamp: a =>
+ {
+ while (a < 0 || a > 0xFFFFFFFF)
+ a += a < 0 ? 0x100000000 : -0x100000000;
+ return a;
+ },
+ shl: (a, b) => RosadoAPI.Math32.clamp(a << b),
+ shr: (a, b) => RosadoAPI.Math32.clamp(a >>> b),
+ rtl: (a, b) => RosadoAPI.Math32.clamp((a << b) | (a >>> (32 - b))),
+ rtr: (a, b) => RosadoAPI.Math32.clamp((a >>> b) | (a << (32 - b))),
+ add: (a, b) => RosadoAPI.Math32.clamp(a + b),
+ sub: (a, b) => RosadoAPI.Math32.clamp(a + b),
+ or: (a, b) => RosadoAPI.Math32.clamp(a | b),
+ xor: (a, b) => RosadoAPI.Math32.clamp(a ^ b)
+ },
+ HMACSHA256:
+ {
+ sign: async (key, msg) =>
+ {
+ key = new Uint8Array(key);
+ msg = new Uint8Array(msg);
+ var ikey = await crypto.subtle.importKey
+ (
+ "raw",
+ key,
+ { name: "HMAC", hash: { name: "SHA-256" }},
+ false,
+ ["sign", "verify"]
+ );
+ return new Uint8Array(await window.crypto.subtle.sign({ name: "HMAC", }, ikey, msg));
+ }
+ },
+ ChaCha20:
+ {
+ QR: (cc, a, b, c, d) =>
+ {
+ cc[a] = RosadoAPI.Math32.add(cc[a], cc[b]);
+ cc[d] = RosadoAPI.Math32.xor(cc[d], cc[a]);
+ cc[d] = RosadoAPI.Math32.rtl(cc[d], 16);
+
+ cc[c] = RosadoAPI.Math32.add(cc[c], cc[d]);
+ cc[b] = RosadoAPI.Math32.xor(cc[b], cc[c]);
+ cc[b] = RosadoAPI.Math32.rtl(cc[b], 12);
+
+ cc[a] = RosadoAPI.Math32.add(cc[a], cc[b]);
+ cc[d] = RosadoAPI.Math32.xor(cc[d], cc[a]);
+ cc[d] = RosadoAPI.Math32.rtl(cc[d], 8);
+
+ cc[c] = RosadoAPI.Math32.add(cc[c], cc[d]);
+ cc[b] = RosadoAPI.Math32.xor(cc[b], cc[c]);
+ cc[b] = RosadoAPI.Math32.rtl(cc[b], 7);
+ },
+ DR: (cc) =>
+ {
+ RosadoAPI.ChaCha20.QR(cc, 0, 4, 8, 12);
+ RosadoAPI.ChaCha20.QR(cc, 1, 5, 9, 13);
+ RosadoAPI.ChaCha20.QR(cc, 2, 6, 10, 14);
+ RosadoAPI.ChaCha20.QR(cc, 3, 7, 11, 15);
+ RosadoAPI.ChaCha20.QR(cc, 0, 5, 10, 15);
+ RosadoAPI.ChaCha20.QR(cc, 1, 6, 11, 12);
+ RosadoAPI.ChaCha20.QR(cc, 2, 7, 8, 13);
+ RosadoAPI.ChaCha20.QR(cc, 3, 4, 9, 14);
+ },
+ CB: (cc) =>
+ {
+ var i;
+ var x = new Array(16);
+ for (i = 0; i < 16; i++)
+ {
+ x[i] = cc[i];
+ }
+ for (i = 0; i < 10; i++)
+ {
+ RosadoAPI.ChaCha20.DR(cc);
+ }
+ for (i = 0; i < 16; i++)
+ {
+ cc[i] = RosadoAPI.Math32.add(cc[i], x[i]);
+ }
+ },
+ S: (cc, cs) =>
+ {
+ for (var i = 0; i < 16; i++)
+ {
+ cs[4 * i] = (cc[i] & 0xFF);
+ cs[4 * i + 1] = ((cc[i] >> 8) & 0xFF);
+ cs[4 * i + 2] = ((cc[i] >> 16) & 0xFF);
+ cs[4 * i + 3] = ((cc[i] >> 24) & 0xFF);
+ }
+ },
+ B: (key, nonce, block, out) =>
+ {
+ var cc =
+ [
+ 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574,
+
+ key[0] | (key[1] << 8) | (key[2] << 16) | (key[3] << 24),
+ key[4] | (key[5] << 8) | (key[6] << 16) | (key[7] << 24),
+ key[8] | (key[9] << 8) | (key[10] << 16) | (key[11] << 24),
+ key[12] | (key[13] << 8) | (key[14] << 16) | (key[15] << 24),
+
+ key[16] | (key[17] << 8) | (key[18] << 16) | (key[19] << 24),
+ key[20] | (key[21] << 8) | (key[22] << 16) | (key[23] << 24),
+ key[24] | (key[25] << 8) | (key[26] << 16) | (key[27] << 24),
+ key[28] | (key[29] << 8) | (key[30] << 16) | (key[31] << 24),
+
+ block,
+
+ nonce[0] | (nonce[1] << 8) | (nonce[2] << 16) | (nonce[3] << 24),
+ nonce[4] | (nonce[5] << 8) | (nonce[6] << 16) | (nonce[7] << 24),
+ nonce[8] | (nonce[9] << 8) | (nonce[10] << 16) | (nonce[11] << 24)
+ ];
+
+ RosadoAPI.ChaCha20.CB(cc);
+ RosadoAPI.ChaCha20.S(cc, out);
+ },
+ encrypt: async (key, nonce, block, data) =>
+ {
+ var count = data.length;
+ if (count > (274877906944 - block * 64)) return null;
+ var ret = new Array(0);
+ var ccblock = new Array(64);
+ var size = 0;
+ while (count > 64)
+ {
+ ret.length = size + 64;
+ RosadoAPI.ChaCha20.B(key, nonce, block++, ccblock);
+ for (var i = 0; i < 64; i++) ret[size + i] = ccblock[i];
+ size += 64;
+ count -= 64;
+ }
+ if (count > 0)
+ {
+ ret.length = size + count;
+ RosadoAPI.ChaCha20.B(key, nonce, block, ccblock);
+ for (var i = 0; i < count; i++) ret[size + i] = ccblock[i];
+ }
+ for (var i = 0; i < data.length; i++) ret[i] ^= data[i];
+ return new Uint8Array(ret);
+ }
+ },
+
+ Base64:
+ {
+ encode: async (x) =>
+ {
+ return await new Promise(r =>
+ {
+ const reader = new FileReader();
+ reader.addEventListener("load", () => r(reader.result.split(",")[1]));
+ reader.readAsDataURL(new Blob([new Uint8Array(x)]));
+ });
+ },
+
+ decode: (b64) =>
+ {
+ var dec1 = (v) =>
+ {
+ switch (v)
+ {
+ case 'A': return 0;
+ case 'B': return 1;
+ case 'C': return 2;
+ case 'D': return 3;
+ case 'E': return 4;
+ case 'F': return 5;
+ case 'G': return 6;
+ case 'H': return 7;
+ case 'I': return 8;
+ case 'J': return 9;
+ case 'K': return 10;
+ case 'L': return 11;
+ case 'M': return 12;
+ case 'N': return 13;
+ case 'O': return 14;
+ case 'P': return 15;
+ case 'Q': return 16;
+ case 'R': return 17;
+ case 'S': return 18;
+ case 'T': return 19;
+ case 'U': return 20;
+ case 'V': return 21;
+ case 'W': return 22;
+ case 'X': return 23;
+ case 'Y': return 24;
+ case 'Z': return 25;
+ case 'a': return 26;
+ case 'b': return 27;
+ case 'c': return 28;
+ case 'd': return 29;
+ case 'e': return 30;
+ case 'f': return 31;
+ case 'g': return 32;
+ case 'h': return 33;
+ case 'i': return 34;
+ case 'j': return 35;
+ case 'k': return 36;
+ case 'l': return 37;
+ case 'm': return 38;
+ case 'n': return 39;
+ case 'o': return 40;
+ case 'p': return 41;
+ case 'q': return 42;
+ case 'r': return 43;
+ case 's': return 44;
+ case 't': return 45;
+ case 'u': return 46;
+ case 'v': return 47;
+ case 'w': return 48;
+ case 'x': return 49;
+ case 'y': return 50;
+ case 'z': return 51;
+ case '0': return 52;
+ case '1': return 53;
+ case '2': return 54;
+ case '3': return 55;
+ case '4': return 56;
+ case '5': return 57;
+ case '6': return 58;
+ case '7': return 59;
+ case '8': return 60;
+ case '9': return 61;
+ case '+': return 62;
+ case '/': return 63;
+ }
+ return 255;
+ };
+
+ var ret = new Array(0);
+ var buffer = 0;
+ var bufferS = 0;
+ for (var i = 0; i < b64.length; i++)
+ {
+ if (b64[i] == '=') { bufferS = 0; continue; };
+ var val = dec1(b64[i]);
+ if (val == 255) return null;
+ buffer = ((buffer << 6) | val) & 0xFFFF;
+ bufferS += 6;
+ if (bufferS >= 8)
+ {
+ var shift = (16 - bufferS) & 0xFF;
+ buffer = (buffer << shift) & 0xFFFF;
+ ret[ret.length] = (buffer >>> 8) & 0xFF;
+ buffer = buffer & 0x00FF;
+ buffer = (buffer >>> shift) & 0xFFFF;
+ bufferS -= 8;
+ }
+ }
+ if (bufferS > 0)
+ {
+ buffer = (buffer << (16 - bufferS)) & 0xFFFF;
+ ret[ret.length] = (buffer >>> 8) & 0xFF;
+ }
+ return new Uint8Array(ret);
+ }
+ },
+
+ Hex:
+ {
+ encode: (x) =>
+ {
+ var ret = "";
+ x.forEach(y => { ret += y.toString(16).padStart(2, "0"); });
+ return ret;
+ },
+ decode: (x) =>
+ {
+ var arr = new Array(0);
+ for (var i = 0; i < x.length; i += 2)
+ {
+ arr[arr.length] = parseInt(x.charAt(i) + x.charAt(i + 1), 16);
+ }
+ return new Uint8Array(arr);
+ }
+ },
+
+ generateRequest: async (msg) =>
+ {
+ msg = new TextEncoder().encode(msg);
+ var key = RosadoAPI.Hex.decode(RosadoAPI.apikey);
+ //var sess = crypto.getRandomValues(new Uint8Array(12));
+ var r = () => { return Math.floor(Math.random() * 10000) % 256 };;
+ var sess = new Uint8Array([r(), r(), r(), r(), r(), r(), r(), r(), r(), r(), r(), r()]);
+ var rawdata = await RosadoAPI.ChaCha20.encrypt(key, sess, 0, msg);
+ var dgst = await RosadoAPI.Hex.encode(await RosadoAPI.HMACSHA256.sign(key, rawdata));
+ var data = await RosadoAPI.Base64.encode(rawdata);
+ var resp = "user=" + RosadoAPI.username;
+ resp += "&sess=" + RosadoAPI.Hex.encode(sess);
+ resp += "&dgst=" + dgst;
+ resp += "&data=" + data;
+ return resp;
+ },
+
+ parseResponse: async (msg) =>
+ {
+ if (!msg.includes("user=") || !msg.includes("&sess=") || !msg.includes("&dgst=") || !msg.includes("&data="))
+ {
+ return { success: false, response: "invalid response" };
+ }
+ var user = msg.split("user=")[1].split("&")[0].trim();
+ var sess = msg.split("&sess=")[1].split("&")[0].trim();
+ var dgst = msg.split("&dgst=")[1].split("&")[0].trim();
+ var data = msg.split("&data=")[1].split("&")[0].trim();
+
+ if (user != RosadoAPI.username)
+ {
+ return { success: false, response: "invalid user in response" };
+ }
+ data = RosadoAPI.Base64.decode(data);
+ sess = RosadoAPI.Hex.decode(sess);
+ var key = RosadoAPI.Hex.decode(RosadoAPI.apikey);
+ var sig = await RosadoAPI.Hex.encode(await RosadoAPI.HMACSHA256.sign(key, data));
+ if (sig != dgst)
+ {
+ return { success: false, response: "invalid signature" };
+ }
+ var resp = await RosadoAPI.ChaCha20.encrypt(key, sess, 0, data);
+ return { success: true, response: new TextDecoder().decode(resp) };
+ },
+
+ request: async (msg) =>
+ {
+ if (msg.trim().length == 0) return { success: true, response: "" };
+ var req = await RosadoAPI.generateRequest(msg);
+ return await new Promise(r =>
+ {
+ const xhr = new XMLHttpRequest();
+ xhr.open("POST", RosadoAPI.endpoint, true);
+ xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+ xhr.onreadystatechange = (x) =>
+ {
+ if (xhr.readyState === XMLHttpRequest.DONE)
+ {
+ if (xhr.status === 200)
+ {
+ RosadoAPI.parseResponse(xhr.responseText).then(pr => { r(pr); }).catch(x => alert("ERR(3)"));
+ }
+ else
+ {
+ r({success: false, response: xhr.status});
+ }
+ }
+ }
+ xhr.send(req);
+ }).catch(x => alert("ERR(1): " + x));
+ }
+};
+
diff --git a/src/www/index.html b/src/www/index.html
index deace9b..638bc79 100644
--- a/src/www/index.html
+++ b/src/www/index.html
@@ -3,7 +3,7 @@
QAnsel - Quantum Computer Simulator
-
+
@@ -934,10 +934,10 @@
errorModal("Please click the gear icon and input your API key.");
return;
}
- EstoulsAPI.username = key.split(":")[0];
- EstoulsAPI.apikey = key.split(":")[1];
- EstoulsAPI.endpoint = "https://" + key.split(":")[2];
- EstoulsAPI.request(IstinaEditor.getText()).then(x =>
+ RosadoAPI.username = key.split(":")[0];
+ RosadoAPI.apikey = key.split(":")[1];
+ RosadoAPI.endpoint = "https://" + key.split(":")[2];
+ RosadoAPI.request(IstinaEditor.getText()).then(x =>
{
$("#blocker-div")[0].remove();
$("#blocker-img")[0].remove();