forked from olcxjas-softworks/LarpixClient
Add capacitorjs runtime
This commit is contained in:
parent
d0ece489ee
commit
f90c0e6c40
8362 changed files with 1502407 additions and 1 deletions
392
webroot/main.js
Normal file
392
webroot/main.js
Normal file
|
|
@ -0,0 +1,392 @@
|
|||
console.log(window.location.protocol);
|
||||
|
||||
var url = `${window.location.protocol}//${window.location.hostname}/_larpix`;
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
|
||||
const collapseDmsBtn = document.getElementById("collapse-dms");
|
||||
|
||||
const sidebarHome = document.getElementById("sidebar-home");
|
||||
const sidebarHomeButton = sidebarHome.children.item(1);
|
||||
const sidebarHomeIndicator = sidebarHome.children.item(0);
|
||||
|
||||
const sidebarAdd = document.getElementById("sidebar-add");
|
||||
const sidebarAddButton = sidebarAdd.children.item(1);
|
||||
const sidebarAddIndicator = sidebarAdd.children.item(0);
|
||||
|
||||
|
||||
|
||||
function delay(time) {
|
||||
return new Promise(resolve => setTimeout(resolve, time));
|
||||
}
|
||||
async function packetEncPass(pass, key, username) {
|
||||
return await encryptWithNonce(pass, key, getNonce(username, key));
|
||||
}
|
||||
|
||||
async function getNonce(username, key) {
|
||||
|
||||
let nonce;
|
||||
let fetchRes = await (await fetch(`${url}/nextnonce?u=${username}`)).text();
|
||||
|
||||
try {
|
||||
nonce = await decryptString(fetchRes, key);
|
||||
}
|
||||
catch(err) {
|
||||
nonce = await decryptString(fetchRes, "");
|
||||
}
|
||||
return nonce;
|
||||
}
|
||||
|
||||
async function encryptWithNonce(value, key, nonce) {
|
||||
return await encryptString(value, nonce + key);
|
||||
}
|
||||
|
||||
async function calcCommunicationKeyClient(p, g, pubServer) {
|
||||
const secretClientBytes = window.crypto.getRandomValues(new Uint8Array(512));
|
||||
const secretClient = BigInt('0x' + Array.from(secretClientBytes).map(b => b.toString(16).padStart(2, '0')).join(''));
|
||||
const pubClient = power(BigInt(g), secretClient, BigInt(p));
|
||||
const sharedSecret = power(BigInt(pubServer), secretClient, BigInt(p));
|
||||
|
||||
let sharedSecretStr = sharedSecret.toString(16);
|
||||
|
||||
if (sharedSecretStr.length % 2 !== 0) {
|
||||
sharedSecretStr = '0' + sharedSecretStr;
|
||||
}
|
||||
|
||||
const sharedSecretBytes = new Uint8Array(sharedSecretStr.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
|
||||
|
||||
const hashBuffer = await window.crypto.subtle.digest('SHA-256', sharedSecretBytes);
|
||||
const aesKey = new Uint8Array(hashBuffer);
|
||||
|
||||
return [pubClient.toString(), aesKey];
|
||||
}
|
||||
|
||||
function keyDataFromServerJson(jsonFromServer) {
|
||||
const data = JSON.parse(jsonFromServer);
|
||||
|
||||
const p = BigInt(data.p);
|
||||
const g = BigInt(data.g);
|
||||
const pubServer = BigInt(data.pubServer);
|
||||
|
||||
return [p, g, pubServer, data.idKey]
|
||||
}
|
||||
|
||||
function base64ToUint8(base64) {
|
||||
return Uint8Array.from(atob(base64), c => c.charCodeAt(0));
|
||||
}
|
||||
function uint8ToBase64(uint8) {
|
||||
return fixBase64Padding(btoa(String.fromCharCode(...uint8)));
|
||||
}
|
||||
|
||||
async function encrypt(plainText, keyBytes) {
|
||||
const iv = window.crypto.getRandomValues(new Uint8Array(16));
|
||||
const encoder = new TextEncoder();
|
||||
const data = encoder.encode(plainText);
|
||||
|
||||
const cryptoKey = await window.crypto.subtle.importKey(
|
||||
"raw", keyBytes, "AES-CBC", false, ["encrypt"]
|
||||
);
|
||||
|
||||
const encryptedContent = await window.crypto.subtle.encrypt(
|
||||
{name: "AES-CBC", iv: iv},
|
||||
cryptoKey,
|
||||
data
|
||||
);
|
||||
const result = new Uint8Array(iv.length + encryptedContent.byteLength);
|
||||
result.set(iv);
|
||||
result.set(new Uint8Array(encryptedContent), iv.length);
|
||||
|
||||
return uint8ToBase64(result);
|
||||
}
|
||||
|
||||
async function decrypt(cipherTextBase64, keyBytes) {
|
||||
const fullData = base64ToUint8(cipherTextBase64);
|
||||
const iv = fullData.slice(0, 16);
|
||||
const cipherData = fullData.slice(16);
|
||||
|
||||
const cryptoKey = await window.crypto.subtle.importKey(
|
||||
"raw", keyBytes, "AES-CBC", false, ["decrypt"]
|
||||
);
|
||||
|
||||
const decrypted = await window.crypto.subtle.decrypt(
|
||||
{name: "AES-CBC", iv: iv},
|
||||
cryptoKey,
|
||||
cipherData
|
||||
);
|
||||
|
||||
return new TextDecoder().decode(decrypted);
|
||||
}
|
||||
|
||||
|
||||
async function getCryptoKey(passphrase) {
|
||||
const encoder = new TextEncoder();
|
||||
const data = encoder.encode(passphrase);
|
||||
const hash = await crypto.subtle.digest('SHA-256', data);
|
||||
return await crypto.subtle.importKey('raw', hash, {name: 'AES-CBC'}, false, ['encrypt', 'decrypt']);
|
||||
}
|
||||
|
||||
async function encryptBytes(plainBytes, passphrase) {
|
||||
const key = await getCryptoKey(passphrase);
|
||||
const iv = crypto.getRandomValues(new Uint8Array(16));
|
||||
|
||||
const encryptedContent = await crypto.subtle.encrypt(
|
||||
{name: 'AES-CBC', iv: iv},
|
||||
key,
|
||||
plainBytes
|
||||
);
|
||||
|
||||
const result = new Uint8Array(iv.length + encryptedContent.byteLength);
|
||||
result.set(iv);
|
||||
result.set(new Uint8Array(encryptedContent), iv.length);
|
||||
return result;
|
||||
}
|
||||
|
||||
async function decryptBytes(combinedBytes, passphrase) {
|
||||
const key = await getCryptoKey(passphrase);
|
||||
const iv = combinedBytes.slice(0, 16);
|
||||
const data = combinedBytes.slice(16);
|
||||
|
||||
const decryptedContent = await crypto.subtle.decrypt(
|
||||
{name: 'AES-CBC', iv: iv},
|
||||
key,
|
||||
data
|
||||
);
|
||||
|
||||
return new Uint8Array(decryptedContent);
|
||||
}
|
||||
|
||||
async function encryptString(plainText, passphrase) {
|
||||
const encoder = new TextEncoder();
|
||||
const data = encoder.encode(plainText);
|
||||
const pwHash = await crypto.subtle.digest('SHA-256', encoder.encode(passphrase));
|
||||
|
||||
const key = await crypto.subtle.importKey(
|
||||
'raw', pwHash, {name: 'AES-CBC'}, false, ['encrypt']
|
||||
);
|
||||
|
||||
const iv = crypto.getRandomValues(new Uint8Array(16));
|
||||
const encrypted = await crypto.subtle.encrypt(
|
||||
{name: 'AES-CBC', iv: iv},
|
||||
key,
|
||||
data
|
||||
);
|
||||
|
||||
const combined = new Uint8Array(iv.length + encrypted.byteLength);
|
||||
combined.set(iv);
|
||||
combined.set(new Uint8Array(encrypted), iv.length);
|
||||
|
||||
return fixBase64Padding(btoa(String.fromCharCode(...combined)));
|
||||
}
|
||||
|
||||
async function decryptString(base64Text, passphrase) {
|
||||
const encoder = new TextEncoder();
|
||||
const combined = new Uint8Array(atob(base64Text).split("").map(c => c.charCodeAt(0)));
|
||||
|
||||
const pwHash = await crypto.subtle.digest('SHA-256', encoder.encode(passphrase));
|
||||
const key = await crypto.subtle.importKey(
|
||||
'raw', pwHash, {name: 'AES-CBC'}, false, ['decrypt']
|
||||
);
|
||||
|
||||
const iv = combined.slice(0, 16);
|
||||
const data = combined.slice(16);
|
||||
|
||||
const decrypted = await crypto.subtle.decrypt(
|
||||
{name: 'AES-CBC', iv: iv},
|
||||
key,
|
||||
data
|
||||
);
|
||||
|
||||
return new TextDecoder().decode(decrypted);
|
||||
}
|
||||
|
||||
|
||||
async function fetchPost(url, value) {
|
||||
let response = await fetch(url, {
|
||||
method: "POST",
|
||||
credentials: "omit",
|
||||
body: value,
|
||||
headers: {
|
||||
"secret": await encryptWithNonce(passwordHash, passwordHash, await getNonce(username, passwordHash))
|
||||
}
|
||||
});
|
||||
let data = await response.text();
|
||||
return data;
|
||||
}
|
||||
|
||||
async function fetchPostEnc(url, value) {
|
||||
let nonce = await getNonce(username, passwordHash);
|
||||
let response = await fetch(url, {
|
||||
method: "POST",
|
||||
credentials: "omit",
|
||||
body: await encryptWithNonce(value, passwordHash, nonce),
|
||||
headers: {
|
||||
"secret": await encryptWithNonce(passwordHash, passwordHash, nonce)
|
||||
}
|
||||
});
|
||||
let data = await response.text();
|
||||
return data;
|
||||
}
|
||||
|
||||
async function fetchAsync(url) {
|
||||
let response = await fetch(url, {
|
||||
method: "GET",
|
||||
credentials: "omit"
|
||||
});
|
||||
|
||||
let data = await response.text();
|
||||
return data;
|
||||
}
|
||||
|
||||
async function fetchAsyncWAuth(url) {
|
||||
let response = await fetch(url, {
|
||||
method: "GET",
|
||||
credentials: "omit",
|
||||
headers: {
|
||||
"secret": await encryptWithNonce(passwordHash, passwordHash, await getNonce(username, passwordHash))
|
||||
}
|
||||
});
|
||||
|
||||
let data = await response.text();
|
||||
return data;
|
||||
}
|
||||
|
||||
async function getServerInfo(host){
|
||||
console.log(`${window.location.protocol}//${host}/_larpix/serverinfo`)
|
||||
return JSON.parse(await fetchAsync(`${window.location.protocol}//${host}/_larpix/serverinfo`));
|
||||
}
|
||||
|
||||
async function Auth(username, password) {
|
||||
|
||||
let passwordHash = await hashSHA3_512(password);
|
||||
let response = await fetch(`${url}/auth?u=${username}`, {
|
||||
method: "GET",
|
||||
credentials: "omit",
|
||||
headers: {
|
||||
"secret": await encryptWithNonce(passwordHash, passwordHash, await getNonce(username, passwordHash))
|
||||
}
|
||||
});
|
||||
|
||||
let data = await response.text();
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
async function fetchEncrypted(request, body)
|
||||
{
|
||||
let nonce = await getNonce(username, passwordHash);
|
||||
|
||||
let response = await fetch(`${url}/encryptedrequest?u=${username}`, {
|
||||
method: "POST",
|
||||
credentials: "omit",
|
||||
body: await encryptWithNonce(
|
||||
|
||||
JSON.stringify({
|
||||
string1: request,
|
||||
string2: body
|
||||
})
|
||||
|
||||
, passwordHash, nonce),
|
||||
headers: {
|
||||
"secret": await encryptWithNonce(passwordHash, passwordHash, nonce)
|
||||
}
|
||||
});
|
||||
let data = await response.text();
|
||||
return data;
|
||||
}
|
||||
|
||||
function power(base, exponent, mod) {
|
||||
let res = 1n;
|
||||
base = base % mod;
|
||||
while (exponent > 0n) {
|
||||
if (exponent % 2n === 1n) res = (res * base) % mod;
|
||||
base = (base * base) % mod;
|
||||
exponent = exponent / 2n;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function fixBase64Padding(base64String) {
|
||||
let str = base64String.replace(/-/g, '+').replace(/_/g, '/');
|
||||
const pad = str.length % 4;
|
||||
|
||||
if (pad) {
|
||||
if (pad === 1) {
|
||||
throw new Error("");
|
||||
}
|
||||
str += '='.repeat(4 - pad);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
function showNotification(message, type = 'info', duration = 3500) {
|
||||
let container = document.getElementById('notification-container');
|
||||
if (!container) {
|
||||
container = document.createElement('div');
|
||||
container.id = 'notification-container';
|
||||
document.body.appendChild(container);
|
||||
}
|
||||
|
||||
const notif = document.createElement('div');
|
||||
notif.className = `notification ${type}`;
|
||||
notif.textContent = message;
|
||||
|
||||
container.appendChild(notif);
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
notif.classList.add('show');
|
||||
});
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
notif.classList.remove('show');
|
||||
|
||||
notif.addEventListener('transitionend', () => {
|
||||
notif.remove();
|
||||
});
|
||||
}, duration);
|
||||
}
|
||||
|
||||
|
||||
async function hashSHA3_512(input) {
|
||||
const encoder = new TextEncoder();
|
||||
const data = encoder.encode(input);
|
||||
const hashBuffer = await crypto.subtle.digest('SHA-512', data); //-3 kiedys xddddddddddddddddd
|
||||
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
||||
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
||||
return hashHex;
|
||||
}
|
||||
|
||||
|
||||
|
||||
var password = "";
|
||||
var username = "";
|
||||
var passwordHash = "";
|
||||
var host = "";
|
||||
async function mainJS()
|
||||
{
|
||||
username = localStorage.getItem('username');
|
||||
password = localStorage.getItem('password');
|
||||
host = localStorage.getItem('host');
|
||||
passwordHash = await hashSHA3_512(password);
|
||||
}
|
||||
mainJS();
|
||||
|
||||
collapseDmsBtn.addEventListener("click", () => {
|
||||
collapseDmsBtn.classList.toggle("collapsed");
|
||||
});
|
||||
|
||||
sidebarHomeButton.addEventListener("mouseenter", () => {
|
||||
sidebarHomeIndicator.classList.add("hover");
|
||||
});
|
||||
sidebarHomeButton.addEventListener("mouseleave", () => {
|
||||
sidebarHomeIndicator.classList.remove("hover");
|
||||
});
|
||||
|
||||
sidebarAddButton.addEventListener("mouseenter", () => {
|
||||
sidebarAddIndicator.classList.add("hover");
|
||||
});
|
||||
sidebarAddButton.addEventListener("mouseleave", () => {
|
||||
sidebarAddIndicator.classList.remove("hover");
|
||||
});
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue