diff options
Diffstat (limited to 'app/scripts/lib')
-rw-r--r-- | app/scripts/lib/config-manager.js | 47 | ||||
-rw-r--r-- | app/scripts/lib/encryptor.js | 146 | ||||
-rw-r--r-- | app/scripts/lib/idStore.js | 2 | ||||
-rw-r--r-- | app/scripts/lib/sig-util.js | 23 |
4 files changed, 201 insertions, 17 deletions
diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index cced32670..abe5dfc87 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -110,6 +110,27 @@ ConfigManager.prototype.setWallet = function (wallet) { this.setData(data) } +ConfigManager.prototype.setVault = function (encryptedString) { + var data = this.getData() + data.vault = encryptedString + this.setData(data) +} + +ConfigManager.prototype.getVault = function () { + var data = this.getData() + return ('vault' in data) && data.vault +} + +ConfigManager.prototype.getKeychains = function () { + return this.migrator.getData().keychains || [] +} + +ConfigManager.prototype.setKeychains = function (keychains) { + var data = this.migrator.getData() + data.keychains = keychains + this.setData(data) +} + ConfigManager.prototype.getSelectedAccount = function () { var config = this.getConfig() return config.selectedAccount @@ -249,6 +270,17 @@ ConfigManager.prototype.setNicknameForWallet = function (account, nickname) { // observable +ConfigManager.prototype.getSalt = function () { + var data = this.getData() + return ('salt' in data) && data.salt +} + +ConfigManager.prototype.setSalt = function(salt) { + var data = this.getData() + data.salt = salt + this.setData(data) +} + ConfigManager.prototype.subscribe = function (fn) { this._subs.push(fn) var unsubscribe = this.unsubscribe.bind(this, fn) @@ -336,21 +368,6 @@ ConfigManager.prototype.getConversionDate = function () { return (('conversionDate' in data) && data.conversionDate) || 'N/A' } -ConfigManager.prototype.setShouldntShowWarning = function () { - var data = this.getData() - if (data.isEthConfirmed) { - data.isEthConfirmed = !data.isEthConfirmed - } else { - data.isEthConfirmed = true - } - this.setData(data) -} - -ConfigManager.prototype.getShouldntShowWarning = function () { - var data = this.getData() - return ('isEthConfirmed' in data) && data.isEthConfirmed -} - ConfigManager.prototype.getShapeShiftTxList = function () { var data = this.getData() var shapeShiftTxList = data.shapeShiftTxList ? data.shapeShiftTxList : [] diff --git a/app/scripts/lib/encryptor.js b/app/scripts/lib/encryptor.js new file mode 100644 index 000000000..832e6d528 --- /dev/null +++ b/app/scripts/lib/encryptor.js @@ -0,0 +1,146 @@ +var ethUtil = require('ethereumjs-util') + +module.exports = { + + // Simple encryption methods: + encrypt, + decrypt, + + // More advanced encryption methods: + keyFromPassword, + encryptWithKey, + decryptWithKey, + + // Buffer <-> String methods + convertArrayBufferViewtoString, + convertStringToArrayBufferView, + + // Buffer <-> Hex string methods + serializeBufferForStorage, + serializeBufferFromStorage, + + // Buffer <-> base64 string methods + encodeBufferToBase64, + decodeBase64ToBuffer, + + generateSalt, +} + +// Takes a Pojo, returns encrypted text. +function encrypt (password, dataObj) { + return keyFromPassword(password) + .then(function (passwordDerivedKey) { + return encryptWithKey(passwordDerivedKey, dataObj) + }) +} + +function encryptWithKey (key, dataObj) { + var data = JSON.stringify(dataObj) + var dataBuffer = convertStringToArrayBufferView(data) + var vector = global.crypto.getRandomValues(new Uint8Array(16)) + + return global.crypto.subtle.encrypt({ + name: 'AES-GCM', + iv: vector, + }, key, dataBuffer).then(function(buf){ + var buffer = new Uint8Array(buf) + var vectorStr = encodeBufferToBase64(vector) + var vaultStr = encodeBufferToBase64(buffer) + return `${vaultStr}\\${vectorStr}` + }) +} + +// Takes encrypted text, returns the restored Pojo. +function decrypt (password, text) { + return keyFromPassword(password) + .then(function (key) { + return decryptWithKey(key, text) + }) +} + +function decryptWithKey (key, text) { + const parts = text.split('\\') + const encryptedData = decodeBase64ToBuffer(parts[0]) + const vector = decodeBase64ToBuffer(parts[1]) + return crypto.subtle.decrypt({name: 'AES-GCM', iv: vector}, key, encryptedData) + .then(function(result){ + const decryptedData = new Uint8Array(result) + const decryptedStr = convertArrayBufferViewtoString(decryptedData) + const decryptedObj = JSON.parse(decryptedStr) + return decryptedObj + }) +} + +function convertStringToArrayBufferView (str) { + var bytes = new Uint8Array(str.length) + for (var i = 0; i < str.length; i++) { + bytes[i] = str.charCodeAt(i) + } + + return bytes +} + +function convertArrayBufferViewtoString (buffer) { + var str = '' + for (var i = 0; i < buffer.byteLength; i++) { + str += String.fromCharCode(buffer[i]) + } + + return str +} + +function keyFromPassword (password) { + var passBuffer = convertStringToArrayBufferView(password) + return global.crypto.subtle.digest('SHA-256', passBuffer) + .then(function (passHash){ + return global.crypto.subtle.importKey('raw', passHash, {name: 'AES-GCM'}, false, ['encrypt', 'decrypt']) + }) +} + +function serializeBufferFromStorage (str) { + str = ethUtil.stripHexPrefix(str) + var buf = new Uint8Array(str.length / 2) + for (var i = 0; i < str.length; i += 2) { + var seg = str.substr(i, 2) + buf[i / 2] = parseInt(seg, 16) + } + return buf +} + +// Should return a string, ready for storage, in hex format. +function serializeBufferForStorage (buffer) { + var result = '0x' + var len = buffer.length || buffer.byteLength + for (var i = 0; i < len; i++) { + result += unprefixedHex(buffer[i]) + } + return result +} + +function unprefixedHex (num) { + var hex = num.toString(16) + while (hex.length < 2) { + hex = '0' + hex + } + return hex +} + +function encodeBufferToBase64 (buf) { + var b64encoded = btoa(String.fromCharCode.apply(null, buf)) + return b64encoded +} + +function decodeBase64ToBuffer (base64) { + var buf = new Uint8Array(atob(base64).split('') + .map(function(c) { + return c.charCodeAt(0) + })) + return buf +} + +function generateSalt (byteCount = 32) { + var view = new Uint8Array(byteCount) + global.crypto.getRandomValues(view) + var b64encoded = btoa(String.fromCharCode.apply(null, view)) + return b64encoded +} diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js index 46d53c4e1..756becce3 100644 --- a/app/scripts/lib/idStore.js +++ b/app/scripts/lib/idStore.js @@ -103,7 +103,6 @@ IdentityStore.prototype.getState = function () { isUnlocked: this._isUnlocked(), seedWords: seedWords, isConfirmed: configManager.getConfirmed(), - isEthConfirmed: configManager.getShouldntShowWarning(), unconfTxs: configManager.unconfirmedTxs(), transactions: configManager.getTxList(), unconfMsgs: messageManager.unconfirmedMsgs(), @@ -114,7 +113,6 @@ IdentityStore.prototype.getState = function () { conversionRate: configManager.getConversionRate(), conversionDate: configManager.getConversionDate(), gasMultiplier: configManager.getGasMultiplier(), - })) } diff --git a/app/scripts/lib/sig-util.js b/app/scripts/lib/sig-util.js new file mode 100644 index 000000000..f8748f535 --- /dev/null +++ b/app/scripts/lib/sig-util.js @@ -0,0 +1,23 @@ +const ethUtil = require('ethereumjs-util') + +module.exports = { + + concatSig: function (v, r, s) { + const rSig = ethUtil.fromSigned(r) + const sSig = ethUtil.fromSigned(s) + const vSig = ethUtil.bufferToInt(v) + const rStr = padWithZeroes(ethUtil.toUnsigned(rSig).toString('hex'), 64) + const sStr = padWithZeroes(ethUtil.toUnsigned(sSig).toString('hex'), 64) + const vStr = ethUtil.stripHexPrefix(ethUtil.intToHex(vSig)) + return ethUtil.addHexPrefix(rStr.concat(sStr, vStr)).toString('hex') + }, + +} + +function padWithZeroes (number, length) { + var myString = '' + number + while (myString.length < length) { + myString = '0' + myString + } + return myString +} |