Skip to content

Commit

Permalink
Merge pull request #4513 from MetaMask/ValidateEmptyKey
Browse files Browse the repository at this point in the history
Validate empty key
  • Loading branch information
kumavis committed Jun 14, 2018
2 parents 66c77dc + e9cb650 commit 1f83a11
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Current Master

- Attempting to import an empty private key will now show a clear error.
- Fix bug where metamask data would stop being written to disk after prolonged use
- Fix bug where account reset did not work with custom RPC providers.
- Fix bug where nonce mutex was never released
Expand Down
13 changes: 12 additions & 1 deletion app/scripts/account-import-strategies/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,18 @@ const accountImporter = {

strategies: {
'Private Key': (privateKey) => {
const stripped = ethUtil.stripHexPrefix(privateKey)
if (!privateKey) {
throw new Error('Cannot import an empty key.')
}

const prefixed = ethUtil.addHexPrefix(privateKey)
const buffer = ethUtil.toBuffer(prefixed)

if (!ethUtil.isValidPrivate(buffer)) {
throw new Error('Cannot import invalid private key.')
}

const stripped = ethUtil.stripHexPrefix(prefixed)
return stripped
},
'JSON File': (input, password) => {
Expand Down
2 changes: 2 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

62 changes: 45 additions & 17 deletions test/unit/app/account-import-strategies.spec.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,59 @@
const assert = require('assert')
const path = require('path')
const accountImporter = require('../../../app/scripts/account-import-strategies/index')
const ethUtil = require('ethereumjs-util')
const accountImporter = require('../../../app/scripts/account-import-strategies/index')
const { assertRejects } = require('../test-utils')

describe('Account Import Strategies', function () {
const privkey = '0x4cfd3e90fc78b0f86bf7524722150bb8da9c60cd532564d7ff43f5716514f553'
const json = '{"version":3,"id":"dbb54385-0a99-437f-83c0-647de9f244c3","address":"a7f92ce3fba24196cf6f4bd2e1eb3db282ba998c","Crypto":{"ciphertext":"bde13d9ade5c82df80281ca363320ce254a8a3a06535bbf6ffdeaf0726b1312c","cipherparams":{"iv":"fbf93718a57f26051b292f072f2e5b41"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"dklen":32,"salt":"7ffe00488319dec48e4c49a120ca49c6afbde9272854c64d9541c83fc6acdffe","n":8192,"r":8,"p":1},"mac":"2adfd9c4bc1cdac4c85bddfb31d9e21a684e0e050247a70c5698facf6b7d4681"}}'

it('imports a private key and strips 0x prefix', async function () {
const importPrivKey = await accountImporter.importAccount('Private Key', [ privkey ])
assert.equal(importPrivKey, ethUtil.stripHexPrefix(privkey))
})
describe('private key import', function () {
it('imports a private key and strips 0x prefix', async function () {
const importPrivKey = await accountImporter.importAccount('Private Key', [ privkey ])
assert.equal(importPrivKey, ethUtil.stripHexPrefix(privkey))
})

it('fails when password is incorrect for keystore', async function () {
const wrongPassword = 'password2'
it('throws an error for empty string private key', async () => {
assertRejects(async function() {
await accountImporter.importAccount('Private Key', [ '' ])
}, Error, 'no empty strings')
})

try {
await accountImporter.importAccount('JSON File', [ json, wrongPassword])
} catch (error) {
assert.equal(error.message, 'Key derivation failed - possibly wrong passphrase')
}
})
it('throws an error for undefined string private key', async () => {
assertRejects(async function () {
await accountImporter.importAccount('Private Key', [ undefined ])
})
})

it('imports json string and password to return a private key', async function () {
const fileContentsPassword = 'password1'
const importJson = await accountImporter.importAccount('JSON File', [ json, fileContentsPassword])
assert.equal(importJson, '0x5733876abe94146069ce8bcbabbde2677f2e35fa33e875e92041ed2ac87e5bc7')
it('throws an error for undefined string private key', async () => {
assertRejects(async function () {
await accountImporter.importAccount('Private Key', [])
})
})

it('throws an error for invalid private key', async () => {
assertRejects(async function () {
await accountImporter.importAccount('Private Key', [ 'popcorn' ])
})
})
})

describe('JSON keystore import', function () {
it('fails when password is incorrect for keystore', async function () {
const wrongPassword = 'password2'

try {
await accountImporter.importAccount('JSON File', [ json, wrongPassword])
} catch (error) {
assert.equal(error.message, 'Key derivation failed - possibly wrong passphrase')
}
})

it('imports json string and password to return a private key', async function () {
const fileContentsPassword = 'password1'
const importJson = await accountImporter.importAccount('JSON File', [ json, fileContentsPassword])
assert.equal(importJson, '0x5733876abe94146069ce8bcbabbde2677f2e35fa33e875e92041ed2ac87e5bc7')
})
})
})
17 changes: 17 additions & 0 deletions test/unit/test-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const assert = require('assert')

module.exports = {
assertRejects,
}

// assert.rejects added in node v10
async function assertRejects (asyncFn, regExp) {
let f = () => {}
try {
await asyncFn()
} catch (error) {
f = () => { throw error }
} finally {
assert.throws(f, regExp)
}
}

0 comments on commit 1f83a11

Please sign in to comment.