diff --git a/README.md b/README.md index 2045ce03..70efd48f 100644 --- a/README.md +++ b/README.md @@ -9,15 +9,15 @@ There are multiple packages in the project that combine to build the overall ext * dist-> // Folder containing the combined distribution components, used to install the extension * packages-> // Folder for scripts compents that support the extension * common-> // Contains core elements used in other packages - * crypto-> // Wrapper for accessing the local encrypted account information + * crypto-> // Wrapper for encrypting and decrypting account information * dapp-> // AlgoSigner library that gets injected in dApps - * extension-> // Extension definition files - * ui-> // Front end application for interaction within the extension interface - * node_modues-> // Installed packages. Is not present unless you are re-building the package contents - * ... + * extension-> // Extension definition and core files + * storage -> // Handles saving and loading of account information + * test-project -> // Test wrapper for the package files + * ui-> // Front end application for interaction within the extension interface \ * manifest.json // Extension definition file * package.json // Algosigner package, required packages, and scripts to build the project * readme.md // Project overview ## Installation -The ./dist/ folder is the only required folder to install the extension. This can be rebuilt using 'npm run build' if desired, from the project root. This will rebuild the packages and move their output to the ./dist/ folder. To install in Chrome, from chrome://extensions/, with developer mode active, on the top right of the screen you can select 'Load Unpacked' and choose the dist folder. This will add an icon to the browser toolbar. +The ./dist/ folder is the only required folder to install the extension. This can be rebuilt using 'npm run build' from the project root after 'npm install'. This will rebuild the packages and move their output to the ./dist/ folder. To install in Chrome, from chrome://extensions/, with developer mode active, on the top right of the screen you can select 'Load Unpacked' and choose the dist folder. This will add an icon to the browser toolbar. diff --git a/packages/common/tsconfig.json b/packages/common/tsconfig.json index 77d6d873..66eb949d 100644 --- a/packages/common/tsconfig.json +++ b/packages/common/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "ES2016", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ + "target": "ES2017", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ "module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ "declaration": false, /* Generates corresponding '.d.ts' file. */ "sourceMap": false, /* Generates corresponding '.map' file. */ diff --git a/packages/crypto/tsconfig.json b/packages/crypto/tsconfig.json index 9ca99631..1ffde032 100644 --- a/packages/crypto/tsconfig.json +++ b/packages/crypto/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "ES2016", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ + "target": "ES2017", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ "module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ "declaration": false, /* Generates corresponding '.d.ts' file. */ "sourceMap": false, /* Generates corresponding '.map' file. */ diff --git a/packages/dapp/src/fn/router.ts b/packages/dapp/src/fn/router.ts index ade43abb..86c56675 100644 --- a/packages/dapp/src/fn/router.ts +++ b/packages/dapp/src/fn/router.ts @@ -17,13 +17,31 @@ export class Router { this.handler = this.default; window.addEventListener("message",(event) => { var d = event.data; - if("source" in d){ - if(d.source == "extension") { - d.source = 'router'; - d.origin = window.location.origin; - this.handler(d); - } + + try { + if (typeof d === 'string') { + let result = JSON.parse(d); + let type = Object.prototype.toString.call(result); + if(type === '[object Object]' || type === '[object Array]') { + // We can display message output here, but as a string object it doesn't match our format and is likely from other sources + } + } + else { + if(Object.prototype.toString.call(d) === '[object Object]' && "source" in d){ + if(d.source == "extension") { + d.source = 'router'; + d.origin = window.location.origin; + this.handler(d); + } + } + } } + catch { + console.log(`Unable to determine source from message. \nEvent:${JSON.stringify(event)}`); + } + + + }); } default(d:any){ diff --git a/packages/dapp/tsconfig.json b/packages/dapp/tsconfig.json index 33c02e56..ade1d2fc 100644 --- a/packages/dapp/tsconfig.json +++ b/packages/dapp/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { /* Basic Options */ - "target": "ES2016", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ + "target": "ES2017", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ "module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ // "lib": [], /* Specify library files to be included in the compilation. */ // "allowJs": true, /* Allow javascript files to be compiled. */ diff --git a/packages/extension/README.md b/packages/extension/README.md index e7f62ccd..6acfe8d5 100644 --- a/packages/extension/README.md +++ b/packages/extension/README.md @@ -1,54 +1,21 @@ -# Proof of Concept Information -This code creates a simplistic extension with very limited functionality to demonstrate flow, encryption and decryption. This flow will show the unencrypted passwords, generated keys, salts and saved info to give a representation of how information is handled outside of the user interface. +# AlgoSigner Extension +Extension definition and core files for use in AlgoSigner. Handles messaging, data manipulation, and manages other packages for encryption, and storage. -## Project Location and Structure +## Extension Package Overview *https://github.com/PureStake* -* algosigner-> // Base project folder - * background-> // Folder for scripts combined into background.js - * account-> - * createAccount.js // Create account keys, mnemonic - * data-> - * extensionStorage.js // Handles requests regarding chrome storage - * localEncryption_AES.js // Encryption using AES - * loclHash.js // Derivation and Hash using PBKDF2 and SHA3 - * dist-> // Extension Installation Folder - * algosigner.html // Display components for the extension - * background.js // Compilation of scripts - * logo.png // Placeholder logo as PureStake logo - * manifest.json // Extension definition file - * node_modues-> // Installed packages - * ... - * algosigner.html // Display components for the extension - * algosigner.js // Page integration script - * background.js // Compilation of scripts - * logo.png // Placeholder logo as PureStake logo +* extension-> // Base project folder + * src-> + * background-> // Folder for scripts combined into background.js + * account-> // Create and handle account keys, mnemonic + * messaging-> // Files for handling communication between DAPP's, the UI and the background processes of the extension + * transaction-> // Transaction actions and validation of transaction structure + * utils-> // Basic functionality needed for the extension including data translation, validation and ledger information + * encryptionWrap // Wrapper of both crypto and storage for organizing information for saving and loading + * content-> // Handles data messages coming in from the content script + * public-> // Contains additional files for inclusion in the outgoing folder like extension images * manifest.json // Extension definition file - * package-lock.json // Algosigner package and installed packages - * package.json // Algosigner package and required packages - * readme.md // Project overview + * package.json // Extension package and required packages + * readme.md // Extension package overview ## Installation -The dist folder is the only required folder. This can be rebuilt using 'npm run build' if desired from the project root. From chrome://extensions/ with developer mode active on the top right of the screen you can select 'Load Unpacked' and choose the dist folder. This will add an icon to the browser toolbar. - -After clicking the browser icon a popup window will show. On it there are 2 interactable passphrase text boxes and 6 buttons with a large demo log area at the bottom. There is a public key area near the top to demonstrate that once the key is active the public key component is in memory. - -## Available Actions -The first step should be generating a mnemonic. If a passphrase is not entered the buttons will default to using 'Password1'. - -###### Simulate Login -Attempts to simulate login using the current passphrase. The log area will show the entered passphrase and wallet name on disk, the encrypted wallet on disk, then display login failure or success based on a decryption check. - -###### Generate Mnemonic -Shows the create or import flow of a mnemonic. In this case the previous account object is cleared and a create is performed. The new mnemonic is shown as plain text along with the passphrase, this then moves that value into the account object and shows that the information is the same as the mnemonic. A new unlock key is created, and the resulting salts are passed back. There are two salts, one during derivation and one for encryption. The final value is that of the encrypted account mnemonic value. - -###### View Mnemonic Encryption -Shows retrieval of a mnemonic. Plain text account name and passphrase are shown. Using the account name, the encrypted version is pulled from local browser storage. Once located the passphrase and salt listed on the account object are used to create an encrypted unlock key. This key is used to unencrypt the account, then both the raw account and decrypted mnemonic are shown to indicate that the data moves back to an encrypted state except for the information being retrieved. - -###### Set New Passphrase -Utilizing the Passphrase and New Passphrase text boxes to change the passphrase. This shows the account name previous passphrase and new passphrase in plain text. A new salt value is generated and this creates a new hashed key for the passphrase. The encrypted account object is pulled from local browser storage using the account name. This salt information and the current passphrase are used to decrypt the account object. Then the new account salt is created and the account is re-encrypted with the new hashed passphrase key. - -###### View Password Hash -Shows password hashing flow. The plain text account name and password are shown. If there is a current encrypted account object the attached salt is used, if not a new one will be generated. Then the passphrase will go through 1000 iterations of passphrase derivation and the resulting hashed passphrase key will be shown. - -###### View Wallet Account -Shows the raw stored account object. Demonstrates that all that is required to retrieve an account is the account name. This account name is shown in plain text and retrieves the encrypted local raw account object. +Install NodeJS, run 'npm install', then 'npm run build'. diff --git a/packages/extension/src/content/content.ts b/packages/extension/src/content/content.ts index 81281e7d..edfb0d81 100644 --- a/packages/extension/src/content/content.ts +++ b/packages/extension/src/content/content.ts @@ -26,15 +26,29 @@ class Content { let ctx = this; window.addEventListener("message",(ev) => { var d = ev.data; - if("source" in d){ - if(d.source == "dapp") { - let eventId: string = d.body.id; - ctx.events[eventId] = ev; - } - if(d.source == "dapp" || d.source == "router") { - extensionBrowser.runtime.sendMessage(d); // {source, body} + try { + if (typeof d === 'string') { + let result = JSON.parse(d); + let type = Object.prototype.toString.call(result); + if(type === '[object Object]' || type === '[object Array]') { + // We can display message output here, but as a string object it doesn't match our format and is likely from other sources + } + } + else { + if(Object.prototype.toString.call(d) === '[object Object]' && "source" in d){ + if(d.source == "dapp") { + let eventId: string = d.body.id; + ctx.events[eventId] = ev; + } + if(d.source == "dapp" || d.source == "router") { + extensionBrowser.runtime.sendMessage(d); // {source, body} + } + } } } + catch { + console.log(`Unable to determine source from message. \n${d}`); + } }); } @@ -43,12 +57,14 @@ class Content { chromeRuntimeListener() { let ctx = this; extensionBrowser.runtime.onMessage.addListener((d) => { - let body = d.body; - if(body.id in ctx.events) { - ctx.events[body.id].ports[0].postMessage(d); - delete ctx.events[body.id]; - } else { - window.postMessage(d, window.location.origin); + if( Object.prototype.toString.call(d) === '[object Object]' && "body" in d) { + let body = d.body; + if(body.id in ctx.events) { + ctx.events[body.id].ports[0].postMessage(d); + delete ctx.events[body.id]; + } else { + window.postMessage(d, window.location.origin); + } } }); } diff --git a/packages/extension/src/public/images/icon.png b/packages/extension/src/public/images/icon.png index 02e430c5..6d22d2de 100644 Binary files a/packages/extension/src/public/images/icon.png and b/packages/extension/src/public/images/icon.png differ diff --git a/packages/extension/tsconfig.json b/packages/extension/tsconfig.json index 61a10746..21a533a2 100644 --- a/packages/extension/tsconfig.json +++ b/packages/extension/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "ES2016", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ + "target": "ES2017", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ "module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ "declaration": false, /* Generates corresponding '.d.ts' file. */ "sourceMap": false, /* Generates corresponding '.map' file. */ diff --git a/packages/storage/tsconfig.json b/packages/storage/tsconfig.json index 6f6f3ca1..027a4d5f 100644 --- a/packages/storage/tsconfig.json +++ b/packages/storage/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "ES2016", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ + "target": "ES2017", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ "module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ "declaration": false, /* Generates corresponding '.d.ts' file. */ "sourceMap": false, /* Generates corresponding '.map' file. */ diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json index 26ed7ac2..e4ebad79 100644 --- a/packages/ui/tsconfig.json +++ b/packages/ui/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { /* Basic Options */ - "target": "ES2016", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ + "target": "ES2017", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ "module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ // "lib": [], /* Specify library files to be included in the compilation. */ "allowJs": true, /* Allow javascript files to be compiled. */