diff --git a/manifest.json b/manifest.json index ad6ff51bbc5b24fe3a09c7411d8564f6564d0e83..ba9c0795c023e67e967adb895478376617011c86 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 b2dbb4d157cf22fd21818b5fe0e095720cb30b96..00622b52465bea17ba162bab6e0f2c9e39963d1d 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 0000000000000000000000000000000000000000..5f865911d42180449a4c46ccd965161065479378 --- /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 5f640d8a974a062b4da125ea5a43e6abfb38c7a8..748136f190772e73230f0c322bb14b5358728d91 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 49b69d0fff819e08bc5d634a89a6c1ce1be968b9..e9b0aea796dc463e256224e02478146749ec716d 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