Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
a3bb62a
ci - use image circle/node:12-browsers
kumavis Mar 28, 2020
893aaea
deps - remove old sesify deps
kumavis Mar 28, 2020
dfc0694
deps - readd sesify and set deps install to ignore engines field
kumavis Mar 28, 2020
4325799
fix: disable dnode weak on nodejs for node@10 support
kumavis Apr 20, 2020
018861a
deps - use fork of ethereumjs-wallet for node v12 support
kumavis Apr 20, 2020
b9a3914
ci/scripts/deps-install - remove scrypt from whitelist
kumavis Apr 20, 2020
beef044
deps - shim ethereumjs-wallet for node v12 support
kumavis Apr 20, 2020
663de1a
ci/scripts/deps-install - add workaround for scrypt
kumavis Apr 20, 2020
f0a6f30
ci/scripts/deps-install - add workaround for scrypt
kumavis Apr 20, 2020
53befa9
deps - remove old etherscan-link
kumavis Apr 21, 2020
8d645e1
update .nvmrc
rekmarks Apr 21, 2020
71f5720
deps - bump chromedriver to match ci image
kumavis Apr 23, 2020
4f8961b
test/e2e - fix test for contract creation content
kumavis Apr 23, 2020
6a74611
test/e2e - log webdriver options on start
kumavis Apr 23, 2020
157ce70
test/unit/permissions - fix promise await timing
kumavis Apr 24, 2020
ef583c0
deps - update ethUtil for ethereumjs-wallet stub
kumavis Apr 24, 2020
a72b945
Revert "deps - update ethUtil for ethereumjs-wallet stub"
kumavis Apr 24, 2020
b695530
Revert "deps - shim ethereumjs-wallet for node v12 support"
kumavis Apr 24, 2020
a7b20f0
ci/test-e2e-add-default-port-9222
kumavis Apr 24, 2020
c6ecae7
ci/chromedriver - attack wildly
kumavis Apr 24, 2020
87ebea2
ci/chromedriver - attack wildly
kumavis Apr 24, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
deps - shim ethereumjs-wallet for node v12 support
  • Loading branch information
kumavis committed Apr 21, 2020
commit beef0442d23317ca3f97d9ab4868e003636ee934
160 changes: 156 additions & 4 deletions app/scripts/account-import-strategies/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,32 @@
import log from 'loglevel'
import Wallet from 'ethereumjs-wallet'
import importers from 'ethereumjs-wallet/thirdparty'
import utf8 from 'utf8'
import crypto from 'crypto'
import scryptsy from '@web3-js/scrypt-shim'
import ethUtil from 'ethereumjs-util'


//
// ethereumjs-wallet stub
//

const evpKdfDefaults = {
count: 1,
keysize: 16,
ivsize: 16,
digest: 'md5',
}
class Wallet {
constructor (privateKey) {
if (privateKey && !ethUtil.isValidPrivate(privateKey)) {
throw new Error('Private key does not satisfy the curve requirements (ie. it is invalid)')
}
this.privateKey = privateKey
}
getAddressString () {
return ethUtil.bufferToHex(this.getAddress())
}
}

const accountImporter = {

importAccount (strategy, args) {
Expand Down Expand Up @@ -34,10 +58,10 @@ const accountImporter = {
'JSON File': (input, password) => {
let wallet
try {
wallet = importers.fromEtherWallet(input, password)
wallet = fromEtherWallet(input, password)
} catch (e) {
log.debug('Attempt to import as EtherWallet format failed, trying V3')
wallet = Wallet.fromV3(input, password, true)
wallet = fromV3(input, password, true)
}

return walletToPrivateKey(wallet)
Expand All @@ -52,3 +76,131 @@ function walletToPrivateKey (wallet) {
}

export default accountImporter


//
// from ethereumjs-wallet
//

function fromV3 (input, password, nonStrict = false) {
const json = typeof input === 'object' ? input : JSON.parse(nonStrict ? input.toLowerCase() : input)
if (json.version !== 3) {
throw new Error('Not a V3 wallet')
}
let derivedKey, kdfparams
if (json.crypto.kdf === 'scrypt') {
kdfparams = json.crypto.kdfparams
// FIXME: support progress reporting callback
derivedKey = scryptsy(Buffer.from(password), Buffer.from(kdfparams.salt, 'hex'), kdfparams.n, kdfparams.r, kdfparams.p, kdfparams.dklen)
} else if (json.crypto.kdf === 'pbkdf2') {
kdfparams = json.crypto.kdfparams
if (kdfparams.prf !== 'hmac-sha256') {
throw new Error('Unsupported parameters to PBKDF2')
}
derivedKey = crypto.pbkdf2Sync(Buffer.from(password), Buffer.from(kdfparams.salt, 'hex'), kdfparams.c, kdfparams.dklen, 'sha256')
} else {
throw new Error('Unsupported key derivation scheme')
}
const ciphertext = Buffer.from(json.crypto.ciphertext, 'hex')
const mac = ethUtil.keccak256(Buffer.concat([derivedKey.slice(16, 32), ciphertext]))
if (mac.toString('hex') !== json.crypto.mac) {
throw new Error('Key derivation failed - possibly wrong passphrase')
}
const decipher = crypto.createDecipheriv(json.crypto.cipher, derivedKey.slice(0, 16), Buffer.from(json.crypto.cipherparams.iv, 'hex'))
const seed = runCipherBuffer(decipher, ciphertext)
return new Wallet(seed)
}

function fromEtherWallet (input, password) {
const json = typeof input === 'object' ? input : JSON.parse(input)
let privateKey
if (!json.locked) {
if (json.private.length !== 64) {
throw new Error('Invalid private key length')
}
privateKey = Buffer.from(json.private, 'hex')
} else {
if (typeof password !== 'string') {
throw new Error('Password required')
}
if (password.length < 7) {
throw new Error('Password must be at least 7 characters')
}
// the "encrypted" version has the low 4 bytes
// of the hash of the address appended
const hash = json.encrypted ? json.private.slice(0, 128) : json.private
// decode openssl ciphertext + salt encoding
const cipher = decodeCryptojsSalt(hash)
if (!cipher.salt) {
throw new Error('Unsupported EtherWallet key format')
}
// derive key/iv using OpenSSL EVP as implemented in CryptoJS
const evp = evpKdf(Buffer.from(password), cipher.salt, { keysize: 32, ivsize: 16 })
const decipher = crypto.createDecipheriv('aes-256-cbc', evp.key, evp.iv)
privateKey = runCipherBuffer(decipher, Buffer.from(cipher.ciphertext))
// NOTE: yes, they've run it through UTF8
privateKey = Buffer.from(utf8.decode(privateKey.toString()), 'hex')
}
const wallet = new Wallet(privateKey)
if (wallet.getAddressString() !== json.address) {
throw new Error('Invalid private key or address')
}
return wallet
}

// http://stackoverflow.com/questions/25288311/cryptojs-aes-pattern-always-ends-with
function decodeCryptojsSalt (input) {
const ciphertext = Buffer.from(input, 'base64')
if (ciphertext.slice(0, 8).toString() === 'Salted__') {
return {
salt: ciphertext.slice(8, 16),
ciphertext: ciphertext.slice(16),
}
}
return { ciphertext }
}

function evpKdf (data, salt, opts) {
const params = mergeEvpKdfOptsWithDefaults(opts)
// A single EVP iteration, returns `D_i`, where block equlas to `D_(i-1)`
function iter (block) {
let hash = crypto.createHash(params.digest)
hash.update(block)
hash.update(data)
hash.update(salt)
block = hash.digest()
for (let i = 1, len = params.count; i < len; i++) {
hash = crypto.createHash(params.digest)
hash.update(block)
block = hash.digest()
}
return block
}
const ret = []
let i = 0
while (Buffer.concat(ret).length < params.keysize + params.ivsize) {
ret[i] = iter(i === 0 ? Buffer.alloc(0) : ret[i - 1])
i++
}
const tmp = Buffer.concat(ret)
return {
key: tmp.slice(0, params.keysize),
iv: tmp.slice(params.keysize, params.keysize + params.ivsize),
}
}

function mergeEvpKdfOptsWithDefaults (opts) {
if (!opts) {
return evpKdfDefaults
}
return {
count: opts.count || evpKdfDefaults.count,
keysize: opts.keysize || evpKdfDefaults.keysize,
ivsize: opts.ivsize || evpKdfDefaults.ivsize,
digest: opts.digest || evpKdfDefaults.digest,
}
}

function runCipherBuffer (cipher, data) {
return Buffer.concat([cipher.update(data), cipher.final()])
}
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@
"ethereumjs-abi": "^0.6.4",
"ethereumjs-tx": "1.3.7",
"ethereumjs-util": "5.1.0",
"ethereumjs-wallet": "dmihal/ethereumjs-wallet#use-scrypt-shim",
"etherscan-link": "^1.0.2",
"ethjs": "^0.4.0",
"ethjs-contract": "^0.2.3",
Expand Down
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10809,7 +10809,7 @@ ethereumjs-wallet@0.6.0, ethereumjs-wallet@^0.6.0:
utf8 "^2.1.1"
uuid "^2.0.1"

ethereumjs-wallet@0.6.3, ethereumjs-wallet@dmihal/ethereumjs-wallet#use-scrypt-shim:
ethereumjs-wallet@0.6.3:
version "0.6.3"
resolved "https://codeload.github.com/dmihal/ethereumjs-wallet/tar.gz/3942d99aa3ed3c8d334bab19d107d772e6e27041"
dependencies:
Expand Down