Merge pull request #878 from MetaMask/i843-MoveSaltIntoEncryptor

Simplify Encryptor API Surface
feature/default_network_editable
Dan Finlay 8 years ago committed by GitHub
commit 427a103083
  1. 50
      app/scripts/keyring-controller.js
  2. 26
      app/scripts/lib/encryptor.js
  3. 13
      test/unit/keyring-controller-test.js
  4. 2
      ui/lib/account-link.js

@ -55,7 +55,7 @@ module.exports = class KeyringController extends EventEmitter {
return { return {
seedWords: this.configManager.getSeedWords(), seedWords: this.configManager.getSeedWords(),
isInitialized: (!!wallet || !!vault), isInitialized: (!!wallet || !!vault),
isUnlocked: !!this.key, isUnlocked: Boolean(this.password),
isDisclaimerConfirmed: this.configManager.getConfirmedDisclaimer(), // AUDIT this.configManager.getConfirmedDisclaimer(), isDisclaimerConfirmed: this.configManager.getConfirmedDisclaimer(), // AUDIT this.configManager.getConfirmedDisclaimer(),
unconfTxs: this.configManager.unconfirmedTxs(), unconfTxs: this.configManager.unconfirmedTxs(),
transactions: this.configManager.getTxList(), transactions: this.configManager.getTxList(),
@ -113,34 +113,24 @@ module.exports = class KeyringController extends EventEmitter {
}) })
} }
migrateAndGetKey (password) { migrateOldVaultIfAny (password) {
let key
const shouldMigrate = !!this.configManager.getWallet() && !this.configManager.getVault() const shouldMigrate = !!this.configManager.getWallet() && !this.configManager.getVault()
return this.loadKey(password) return this.idStoreMigrator.migratedVaultForPassword(password)
.then((derivedKey) => {
key = derivedKey
this.key = key
return this.idStoreMigrator.migratedVaultForPassword(password)
})
.then((serialized) => { .then((serialized) => {
if (serialized && shouldMigrate) { if (serialized && shouldMigrate) {
const keyring = this.restoreKeyring(serialized) const keyring = this.restoreKeyring(serialized)
this.keyrings.push(keyring) this.keyrings.push(keyring)
this.configManager.setSelectedAccount(keyring.getAccounts()[0]) this.configManager.setSelectedAccount(keyring.getAccounts()[0])
return this.persistAllKeyrings() return this.persistAllKeyrings()
.then(() => { return key })
} }
return key return
}) })
} }
createNewVault (password, cb) { createNewVault (password, cb) {
const configManager = this.configManager return this.migrateOldVaultIfAny(password)
const salt = this.encryptor.generateSalt()
configManager.setSalt(salt)
return this.migrateAndGetKey(password)
.then(() => { .then(() => {
this.password = password
return this.persistAllKeyrings() return this.persistAllKeyrings()
}) })
.then(() => { .then(() => {
@ -184,9 +174,9 @@ module.exports = class KeyringController extends EventEmitter {
} }
submitPassword (password, cb) { submitPassword (password, cb) {
this.migrateAndGetKey(password) this.migrateOldVaultIfAny(password)
.then((key) => { .then(() => {
return this.unlockKeyrings(key) return this.unlockKeyrings(password)
}) })
.then((keyrings) => { .then((keyrings) => {
this.keyrings = keyrings this.keyrings = keyrings
@ -200,16 +190,6 @@ module.exports = class KeyringController extends EventEmitter {
}) })
} }
loadKey (password) {
const salt = this.configManager.getSalt() || this.encryptor.generateSalt()
return this.encryptor.keyFromPassword(password + salt)
.then((key) => {
this.key = key
this.configManager.setSalt(salt)
return key
})
}
addNewKeyring (type, opts, cb) { addNewKeyring (type, opts, cb) {
const Keyring = this.getKeyringClassForType(type) const Keyring = this.getKeyringClassForType(type)
const keyring = new Keyring(opts) const keyring = new Keyring(opts)
@ -285,16 +265,16 @@ module.exports = class KeyringController extends EventEmitter {
data: keyring.serialize(), data: keyring.serialize(),
} }
}) })
return this.encryptor.encryptWithKey(this.key, serialized) return this.encryptor.encrypt(this.password, serialized)
.then((encryptedString) => { .then((encryptedString) => {
this.configManager.setVault(encryptedString) this.configManager.setVault(encryptedString)
return true return true
}) })
} }
unlockKeyrings (key) { unlockKeyrings (password) {
const encryptedVault = this.configManager.getVault() const encryptedVault = this.configManager.getVault()
return this.encryptor.decryptWithKey(key, encryptedVault) return this.encryptor.decrypt(this.password, encryptedVault)
.then((vault) => { .then((vault) => {
vault.forEach(this.restoreKeyring.bind(this)) vault.forEach(this.restoreKeyring.bind(this))
return this.keyrings return this.keyrings
@ -402,7 +382,7 @@ module.exports = class KeyringController extends EventEmitter {
}) })
} }
function estimateGas(txData, blockGasLimitHex, cb) { function estimateGas (txData, blockGasLimitHex, cb) {
const txParams = txData.txParams const txParams = txData.txParams
// check if gasLimit is already specified // check if gasLimit is already specified
txData.gasLimitSpecified = Boolean(txParams.gas) txData.gasLimitSpecified = Boolean(txParams.gas)
@ -414,7 +394,7 @@ module.exports = class KeyringController extends EventEmitter {
query.estimateGas(txParams, cb) query.estimateGas(txParams, cb)
} }
function checkForGasError(txData, estimatedGasHex) { function checkForGasError (txData, estimatedGasHex) {
txData.estimatedGas = estimatedGasHex txData.estimatedGas = estimatedGasHex
// all gas used - must be an error // all gas used - must be an error
if (estimatedGasHex === txData.txParams.gas) { if (estimatedGasHex === txData.txParams.gas) {
@ -423,7 +403,7 @@ module.exports = class KeyringController extends EventEmitter {
cb() cb()
} }
function setTxGas(txData, blockGasLimitHex) { function setTxGas (txData, blockGasLimitHex) {
const txParams = txData.txParams const txParams = txData.txParams
// if OOG, nothing more to do // if OOG, nothing more to do
if (txData.simulationFails) { if (txData.simulationFails) {

@ -26,10 +26,16 @@ module.exports = {
// Takes a Pojo, returns cypher text. // Takes a Pojo, returns cypher text.
function encrypt (password, dataObj) { function encrypt (password, dataObj) {
return keyFromPassword(password) const salt = this.generateSalt()
return keyFromPassword(password + salt)
.then(function (passwordDerivedKey) { .then(function (passwordDerivedKey) {
return encryptWithKey(passwordDerivedKey, dataObj) return encryptWithKey(passwordDerivedKey, dataObj)
}) })
.then(function (payload) {
payload.salt = salt
return JSON.stringify(payload)
})
} }
function encryptWithKey (key, dataObj) { function encryptWithKey (key, dataObj) {
@ -44,22 +50,26 @@ function encryptWithKey (key, dataObj) {
var buffer = new Uint8Array(buf) var buffer = new Uint8Array(buf)
var vectorStr = encodeBufferToBase64(vector) var vectorStr = encodeBufferToBase64(vector)
var vaultStr = encodeBufferToBase64(buffer) var vaultStr = encodeBufferToBase64(buffer)
return `${vaultStr}\\${vectorStr}` return {
data: vaultStr,
iv: vectorStr,
}
}) })
} }
// Takes encrypted text, returns the restored Pojo. // Takes encrypted text, returns the restored Pojo.
function decrypt (password, text) { function decrypt (password, text) {
return keyFromPassword(password) const payload = JSON.parse(text)
const salt = payload.salt
return keyFromPassword(password + salt)
.then(function (key) { .then(function (key) {
return decryptWithKey(key, text) return decryptWithKey(key, payload)
}) })
} }
function decryptWithKey (key, text) { function decryptWithKey (key, payload) {
const parts = text.split('\\') const encryptedData = decodeBase64ToBuffer(payload.data)
const encryptedData = decodeBase64ToBuffer(parts[0]) const vector = decodeBase64ToBuffer(payload.iv)
const vector = decodeBase64ToBuffer(parts[1])
return crypto.subtle.decrypt({name: 'AES-GCM', iv: vector}, key, encryptedData) return crypto.subtle.decrypt({name: 'AES-GCM', iv: vector}, key, encryptedData)
.then(function (result) { .then(function (result) {
const decryptedData = new Uint8Array(result) const decryptedData = new Uint8Array(result)

@ -82,13 +82,16 @@ describe('KeyringController', function() {
}) })
describe('#migrateAndGetKey', function() { describe('#migrateOldVaultIfAny', function() {
it('should return the key for that password', function(done) { it('should return and init a new vault', function(done) {
keyringController.migrateAndGetKey(password) keyringController.migrateOldVaultIfAny(password)
.then((key) => { .then(() => {
assert(key, 'a key is returned') assert(keyringController.configManager.getVault(), 'now has a vault')
done() done()
}) })
.catch((reason) => {
assert.ifError(reason)
})
}) })
}) })

@ -1,4 +1,4 @@
module.exports = function(address, network) { module.exports = function (address, network) {
const net = parseInt(network) const net = parseInt(network)
let link let link

Loading…
Cancel
Save