diff options
-rw-r--r-- | app/scripts/background.js | 8 | ||||
-rw-r--r-- | app/scripts/edge-encryptor.js | 69 | ||||
-rw-r--r-- | package.json | 1 |
3 files changed, 78 insertions, 0 deletions
diff --git a/app/scripts/background.js b/app/scripts/background.js index 6bf7707e8..7bececba1 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -15,6 +15,7 @@ const MetamaskController = require('./metamask-controller') const firstTimeState = require('./first-time-state') const setupRaven = require('./setupRaven') const setupMetamaskMeshMetrics = require('./lib/setupMetamaskMeshMetrics') +const EdgeEncryptor = require('./edge-encryptor') const STORAGE_KEY = 'metamask-config' const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' @@ -30,6 +31,12 @@ global.METAMASK_NOTIFIER = notificationManager const release = platform.getVersion() const raven = setupRaven({ release }) +// browser check if it is Edge - https://stackoverflow.com/questions/9847580/how-to-detect-safari-chrome-ie-firefox-and-opera-browser +// Internet Explorer 6-11 +const isIE = !!document.documentMode +// Edge 20+ +const isEdge = !isIE && !!window.StyleMedia + let popupIsOpen = false // state persistence @@ -78,6 +85,7 @@ function setupController (initState) { initState, // platform specific api platform, + encryptor: isEdge ? new EdgeEncryptor() : undefined, }) global.metamaskController = controller diff --git a/app/scripts/edge-encryptor.js b/app/scripts/edge-encryptor.js new file mode 100644 index 000000000..9d6ac37b3 --- /dev/null +++ b/app/scripts/edge-encryptor.js @@ -0,0 +1,69 @@ +const asmcrypto = require('asmcrypto.js') +const Unibabel = require('browserify-unibabel') + +class EdgeEncryptor { + + encrypt (password, dataObject) { + + var salt = this._generateSalt() + return this.keyFromPassword(password, salt) + .then(function (key) { + + var data = JSON.stringify(dataObject) + var dataBuffer = Unibabel.utf8ToBuffer(data) + var vector = global.crypto.getRandomValues(new Uint8Array(16)) + var resultbuffer = asmcrypto.AES_GCM.encrypt(dataBuffer, key, vector) + + var buffer = new Uint8Array(resultbuffer) + var vectorStr = Unibabel.bufferToBase64(vector) + var vaultStr = Unibabel.bufferToBase64(buffer) + return JSON.stringify({ + data: vaultStr, + iv: vectorStr, + salt: salt, + }) + }) + } + + decrypt (password, text) { + + const payload = JSON.parse(text) + const salt = payload.salt + return this.keyFromPassword(password, salt) + .then(function (key) { + const encryptedData = Unibabel.base64ToBuffer(payload.data) + const vector = Unibabel.base64ToBuffer(payload.iv) + return new Promise((resolve, reject) => { + var result + try { + result = asmcrypto.AES_GCM.decrypt(encryptedData, key, vector) + } catch (err) { + return reject(new Error('Incorrect password')) + } + const decryptedData = new Uint8Array(result) + const decryptedStr = Unibabel.bufferToUtf8(decryptedData) + const decryptedObj = JSON.parse(decryptedStr) + resolve(decryptedObj) + }) + }) + } + + keyFromPassword (password, salt) { + + var passBuffer = Unibabel.utf8ToBuffer(password) + var saltBuffer = Unibabel.base64ToBuffer(salt) + return new Promise((resolve) => { + var key = asmcrypto.PBKDF2_HMAC_SHA256.bytes(passBuffer, saltBuffer, 10000) + resolve(key) + }) + } + + _generateSalt (byteCount = 32) { + var view = new Uint8Array(byteCount) + global.crypto.getRandomValues(view) + var b64encoded = btoa(String.fromCharCode.apply(null, view)) + return b64encoded + } +} + +module.exports = EdgeEncryptor diff --git a/package.json b/package.json index 74a9f15d0..c47c46004 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ ] }, "dependencies": { + "asmcrypto.js": "0.22.0", "async": "^2.5.0", "await-semaphore": "^0.1.1", "babel-runtime": "^6.23.0", |