From 981b60f7cc2c9e1e484317450bcc65eb31c076dd Mon Sep 17 00:00:00 2001 From: cp2n19 <cp2n19@soton.ac.uk> Date: Sat, 23 Apr 2022 16:30:11 +0100 Subject: [PATCH] Added instructions page and button to change encryption key - overall improvements to structure of code, addition of several comments --- manifest.json | 8 +++- package-lock.json | 13 ++++++- src/html/instructions.html | 42 +++++++++++++++++++++ src/html/popup.html | 12 ++++++ src/js/popup.js | 76 +++++++++++++++++++++++++++----------- 5 files changed, 128 insertions(+), 23 deletions(-) create mode 100644 src/html/instructions.html diff --git a/manifest.json b/manifest.json index ad6ff51..ba9c079 100644 --- a/manifest.json +++ b/manifest.json @@ -6,7 +6,13 @@ "background": { "service_worker": "src/js/background-packed.js" }, - "permissions": ["storage","activeTab", "scripting"], + "permissions": ["storage","activeTab", "scripting", "downloads"], + "web_accessible_resources": [ + { + "resources": ["src/html/instructions.html"], + "matches": ["<all_urls>"] + } + ], "action": { "default_popup": "src/html/popup.html", "default_icon": { diff --git a/package-lock.json b/package-lock.json index b2dbb4d..00622b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,8 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "crypto-js": "^4.1.1" + "crypto-js": "^4.1.1", + "file-saver": "^2.0.5" }, "devDependencies": { "webpack": "^5.68.0", @@ -535,6 +536,11 @@ "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", "dev": true }, + "node_modules/file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" + }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -1783,6 +1789,11 @@ "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", "dev": true }, + "file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" + }, "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", diff --git a/src/html/instructions.html b/src/html/instructions.html new file mode 100644 index 0000000..5f86591 --- /dev/null +++ b/src/html/instructions.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Instructions</title> +</head> +<body> +<h1>MetaEncryption</h1> + +<h3> + Introduction +</h3> +<p> + Thank you for using MetaEncryption! This extension's purpose is to protect vulnerable metadata generated by your web browser's password manager. That is achieved using cryptographic libraries built in the extension, and encryption practises considered to be the industry standard, so a high level of security and performance is expected and guaranteed. +</p> + +<h3>Instructions</h3> +<ol> + <li>Use the "Encrypt" button to open the file selection dialog</li> + <li>Traverse to "C:\Users\<username>\%AppData%\Local\Google\Chrome\User Data\Default"</li> + <li>Select the "Login Data" file to encrypt - if your browser in synced to your Google Account, then repeat above steps for "Login Data for Account" file</li> + <li>Choose save location for encrypted files</li> + <li>Replace said files with the encrypted ones into above directory</li> + <li>Upon restarting Chrome, or needing to access the database again, use "Decrypt" button to open the file selection dialog</li> + <li>Repeat the same process to select and decrypt the above files, choose save location, and then replace the encrypted ones with them back in said directory</li> +</ol> + +<h3> + Changing Encryption Key +</h3> +<p> + The extension comes with a predetermined, default key to use for encryption - for security purposes, it is highly recommended to change it to a user-specific one to ensure integrity of your data. +</p> + +<p style="color:red;font-size:15px"> + <strong> + WARNING - Ensure that anything you have previously encrypted has been decrypted back before changing your encryption key, otherwise the data will become completely inaccessible, even to its' own user. + </strong> +</p> + +</body> +</html> \ No newline at end of file diff --git a/src/html/popup.html b/src/html/popup.html index 5f640d8..748136f 100644 --- a/src/html/popup.html +++ b/src/html/popup.html @@ -11,6 +11,18 @@ <div class="grid-item"> <input type="button" value="Decrypt" id="decrypt"/> </div> + <div class="grid-item"> + <a href="instructions.html" target="_blank"> + <button> + Instructions + </button> + </a> + </div> + <div class="grid-item"> + <button id="changeKey"> + Change Encryption Key + </button> + </div> <div class="grid-item"> <input type="file" id="getfileEnc" style="display:none"> </div> diff --git a/src/js/popup.js b/src/js/popup.js index 49b69d0..e9b0aea 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -1,31 +1,38 @@ -var crypto = require('crypto-js') +var crypto = require('crypto-js'); +var filesaver = require('file-saver'); let encrypt = document.getElementById("encrypt"); let decrypt = document.getElementById("decrypt"); +let changeKey = document.getElementById("changeKey") let input_enc = document.getElementById("getfileEnc"); let input_dec = document.getElementById("getfileDec"); +//Listener For "Encrypt" Button - initialises encryption process encrypt.addEventListener("click", async () => { let [tab] = await chrome.tabs.query({ active: true, currentWindow: true }); console.log("ENCRYPT button clicked"); input_enc.click(); - // chrome.scripting.executeScript({ - // target: { tabId: tab.id }, - // function: startEncryption - // }); }); +//Listener for "Decrypt" Button - Initialises decryption Process decrypt.addEventListener("click", async () => { let [tab] = await chrome.tabs.query({ active: true, currentWindow: true }); console.log("DECRYPT button clicked"); input_dec.click(); - // chrome.scripting.executeScript({ - // target: {tabId: tab.id}, - // function: startDecryption - // }); }); -// ----- ENCRYPTION TEST ---- +changeKey.addEventListener("click", async () => { + console.log("CHANGE KEY button clicked"); + getUserKey(); +}) + + + +//Encryption Process +//Retrieval of key and IV from chrome storage API, passes them onto CryptoJS to use for AES encryption +//File is read as array buffer and passed as an arguement to CryptoJS to create a WordArray object +//Encrypts WordArray with key and IV using AES, creates a blob from the B64 encoded string +//A URL is then made for the blob, and passed into chrome.downloads API to open a "Save As" dialog for downloading it input_enc.addEventListener("change", () => { let files = input_enc.files; var file = files[0]; @@ -34,26 +41,38 @@ input_enc.addEventListener("change", () => { chrome.storage.local.get(['key','iv'], function(result) { var key = result.key; var iv = result.iv; + // Convert: ArrayBuffer -> WordArray var wordArray = crypto.lib.WordArray.create(reader.result); + // Encryption: I: WordArray -> O: -> Base64 encoded string (OpenSSL-format) var encrypted = crypto.AES.encrypt(wordArray, key,{iv: iv}).toString(); + // Create blob from string var fileEnc = new Blob([encrypted]); + var a = document.createElement("a"); var url = window.URL.createObjectURL(fileEnc); var filename = file.name; - alert(filename); - a.href = url; - a.download = filename; - a.click(); - window.URL.revokeObjectURL(url); + + chrome.downloads.download({ + filename: filename, + url: url, + saveAs: true + }, function (downloadId){ + console.log(downloadId); + } + ); }); }; reader.readAsArrayBuffer(file); }); -// ----- ENCRYPTION TEST ----- + +//Decryption Process +//Similar to Encryption - differences being file is read as text instead of an array buffer (B64 encoded string) +//The decrypted WordArray is then made into a typed array of unsigned 8bit integers, that can then be made into +// a blob of type "application/octet-stream", the type that is read and expected by Chrome input_dec.addEventListener("change", () => { let files = input_dec.files; @@ -80,16 +99,23 @@ input_dec.addEventListener("change", () => { var a = document.createElement("a"); var url = window.URL.createObjectURL(fileDec); var filename = file.name.split('.')[0]; - a.href=url; - a.download=filename; - a.setAttribute('download',filename); - a.click(); - window.URL.revokeObjectURL(url); + + // "../AppData/Local/Google/Chrome/User Data/Default/" + chrome.downloads.download({ + filename: filename, + url: url, + saveAs: true + }, function (downloadId){ + console.log(downloadId); + } + ); }); }; reader.readAsText(file); }); + +//Helper Function that transforms a WordArray into a array of 8bit unsigned integers function convertWordArrayToUint8Array(wordArray) { var arrayOfWords = wordArray.hasOwnProperty("words") ? wordArray.words : []; var length = wordArray.hasOwnProperty("sigBytes") ? wordArray.sigBytes : arrayOfWords.length * 4; @@ -102,4 +128,12 @@ function convertWordArrayToUint8Array(wordArray) { uInt8Array[index++] = word & 0xff; } return uInt8Array; +} + + +function getUserKey(){ + let userKey = window.prompt("Input new encryption key"); + if (userKey == null) + return; + alert(userKey); } \ No newline at end of file -- GitLab