From ece1fb6ff59eb9f64d85ea808062e907d415ab8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Wysoki=C5=84ski?= Date: Sun, 27 Nov 2022 08:26:10 +0100 Subject: [PATCH] poc --- package.json | 2 +- src/background.ts | 21 ++++++++++++--------- src/content.ts | 32 ++++++++++++++++++++++++-------- src/crypto.ts | 14 ++++++++------ src/icon.png | Bin 1165 -> 5892 bytes src/manifest.json | 13 +++++++------ src/message.ts | 4 ++++ src/popup.html | 2 +- 8 files changed, 57 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index ff85aeb..9b2bcbb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sessions-ext", - "version": "0.0.1", + "version": "0.1.0", "description": "", "scripts": { "build": "parcel build src/manifest.json --no-content-hash --no-source-maps --dist-dir dist --detailed-report 0", diff --git a/src/background.ts b/src/background.ts index 9d7e5e5..14a8525 100644 --- a/src/background.ts +++ b/src/background.ts @@ -1,15 +1,20 @@ -import { LoginMessage, Message, MessageType } from './message'; +import { LoginMessage, LoginResponse, Message, MessageType } from './message'; import { optionsStorage } from './options-storage'; import { decrypt, encrypt } from './crypto'; const COOKIE_NAME = 'sid'; const HTTP_STATUS_OK = 200; +const API_KEY_HEADER = 'X-Api-Key'; chrome.runtime.onMessage.addListener( - (message: Message, sender, sendResponse) => { - switch (message.type) { - case MessageType.LOGIN: - handleLogin(message); + async (message: Message, sender, sendResponse) => { + try { + switch (message.type) { + case MessageType.LOGIN: + await handleLogin(message); + } + } catch (err: any) { + sendResponse({ error: err.message } as LoginResponse); } } ); @@ -20,8 +25,6 @@ const handleLogin = async (message: LoginMessage) => { url: message.url, }); - console.log(sid); - if (sid) { const success = await tryOpenOverview(message.url); if (success) { @@ -93,7 +96,7 @@ const createOrUpdateCookie = async (server: string, sid: string) => { method: 'PUT', body: sid, headers: { - 'X-Api-Key': opts.apiKey, + [API_KEY_HEADER]: opts.apiKey, 'Content-Type': 'text/plain', }, }); @@ -108,7 +111,7 @@ const getSid = async (server: string): Promise => { const resp = await fetch(url, { method: 'GET', headers: { - 'X-Api-Key': opts.apiKey, + [API_KEY_HEADER]: opts.apiKey, }, }); diff --git a/src/content.ts b/src/content.ts index e845265..558df93 100644 --- a/src/content.ts +++ b/src/content.ts @@ -1,4 +1,6 @@ -import { LoginMessage, MessageType } from './message'; +import { LoginMessage, LoginResponse, MessageType } from './message'; + +let isLoggingIn = false; const renderUI = () => { document @@ -21,21 +23,35 @@ const renderUI = () => { }); }; -const handleClick = (e: MouseEvent) => { +const handleClick = async (e: MouseEvent) => { if (!(e.currentTarget instanceof HTMLAnchorElement)) { return; } e.preventDefault(); + if (isLoggingIn) { + return; + } + + isLoggingIn = true; + const url = new URL(e.currentTarget.href); const server = extractServerFromURL(url); - chrome.runtime.sendMessage({ - type: MessageType.LOGIN, - server, - loginUrl: url.toString(), - url: url.protocol + '//' + url.host.replace('www', server), - } as LoginMessage); + chrome.runtime + .sendMessage({ + type: MessageType.LOGIN, + server, + loginUrl: url.toString(), + url: url.protocol + '//' + url.host.replace('www', server), + } as LoginMessage) + .then((resp: LoginResponse) => { + isLoggingIn = false; + if (!resp?.error) { + return; + } + console.error(resp.error); + }); }; const extractServerFromURL = (url: URL): string => { diff --git a/src/crypto.ts b/src/crypto.ts index 84504c8..289de93 100644 --- a/src/crypto.ts +++ b/src/crypto.ts @@ -1,11 +1,13 @@ const ITERATIONS = 100000; +const SALT_LENGTH = 16; +const IV_LENGTH = 12; const enc = new TextEncoder(); const dec = new TextDecoder(); export const encrypt = async (data: string, password: string) => { - const salt = crypto.getRandomValues(new Uint8Array(16)); - const iv = crypto.getRandomValues(new Uint8Array(12)); + const salt = crypto.getRandomValues(new Uint8Array(SALT_LENGTH)); + const iv = crypto.getRandomValues(new Uint8Array(IV_LENGTH)); const passwordKey = await getPasswordKey(password); const aesKey = await deriveKey(passwordKey, salt, ['encrypt']); const encryptedContent = await crypto.subtle.encrypt( @@ -18,7 +20,7 @@ export const encrypt = async (data: string, password: string) => { ); const encryptedContentArr = new Uint8Array(encryptedContent); - let buf = new Uint8Array( + const buf = new Uint8Array( salt.byteLength + iv.byteLength + encryptedContentArr.byteLength ); buf.set(salt, 0); @@ -29,9 +31,9 @@ export const encrypt = async (data: string, password: string) => { export const decrypt = async (encryptedData: string, password: string) => { const encryptedDataBuff = base64ToBuf(encryptedData); - const salt = encryptedDataBuff.slice(0, 16); - const iv = encryptedDataBuff.slice(16, 16 + 12); - const data = encryptedDataBuff.slice(16 + 12); + const salt = encryptedDataBuff.slice(0, SALT_LENGTH); + const iv = encryptedDataBuff.slice(SALT_LENGTH, SALT_LENGTH + IV_LENGTH); + const data = encryptedDataBuff.slice(SALT_LENGTH + IV_LENGTH); const passwordKey = await getPasswordKey(password); const aesKey = await deriveKey(passwordKey, salt, ['decrypt']); const decryptedContent = await crypto.subtle.decrypt( diff --git a/src/icon.png b/src/icon.png index a4905069f9a21264dfda3d2064565c720a5650ef..85812eabb741b32a36b50bfde020d4d943ce1844 100644 GIT binary patch literal 5892 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 LNkvXXu0mjfnXW5z diff --git a/src/manifest.json b/src/manifest.json index f2421ea..29fec4f 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -1,7 +1,7 @@ { - "name": "Awesome Extension", - "version": "0.0.0", - "description": "An awesome new browser extension", + "name": "Sessions", + "version": "0.1.0", + "description": "A browser extension aiming to simplify coplaying", "homepage_url": "https://tribalwarshelp.com/", "manifest_version": 3, "minimum_chrome_version": "100", @@ -13,10 +13,10 @@ "default_popup": "popup.html" }, "permissions": ["storage", "cookies", "activeTab", "tabs"], - "host_permissions": ["https://*.tribalwars.net/*"], + "host_permissions": ["https://*.tribalwars.net/*", "https://*.plemiona.pl/*"], "content_scripts": [ { - "matches": ["https://www.tribalwars.net/*"], + "matches": ["https://www.tribalwars.net/*", "https://www.plemiona.pl/*"], "js": ["content.ts"], "run_at": "document_end" } @@ -24,5 +24,6 @@ "background": { "service_worker": "background.ts", "type": "module" - } + }, + "author": "Dawid WysokiƄski" } diff --git a/src/message.ts b/src/message.ts index 8760f3c..b48140f 100644 --- a/src/message.ts +++ b/src/message.ts @@ -10,3 +10,7 @@ export type LoginMessage = { }; export type Message = LoginMessage; + +export type LoginResponse = { + error?: string; +}; diff --git a/src/popup.html b/src/popup.html index 0439e14..08e7a4d 100644 --- a/src/popup.html +++ b/src/popup.html @@ -11,7 +11,7 @@
-

Hello

+

Options