Skip to content
This repository was archived by the owner on Oct 30, 2024. It is now read-only.

Commit 71d1c44

Browse files
committed
use scrypt-js
update methods to async: `fromV1`, `fromV3`, `toV3`, `toV3String`, `fromKryptoKit` use single imports for ethereumjs-util
1 parent 59eb071 commit 71d1c44

File tree

5 files changed

+166
-148
lines changed

5 files changed

+166
-148
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"format:fix": "ethereumjs-config-format-fix",
1717
"lint": "ethereumjs-config-lint",
1818
"lint:fix": "ethereumjs-config-lint-fix",
19-
"test": "npm run build && nyc --reporter=lcov mocha ./test/**/*.ts",
19+
"test": "npm run build && nyc --reporter=lcov mocha --require ts-node/register --require source-map-support/register ./test/**/*.ts",
2020
"test:browser": "karma start karma.conf.js",
2121
"tsc": "ethereumjs-config-tsc",
2222
"tslint": "ethereumjs-config-tslint",
@@ -43,12 +43,12 @@
4343
},
4444
"homepage": "https://github.com/ethereumjs/ethereumjs-wallet",
4545
"dependencies": {
46-
"@web3-js/scrypt-shim": "^0.1.0",
4746
"aes-js": "^3.1.1",
4847
"bs58check": "^2.1.2",
4948
"ethereumjs-util": "^7.0.1",
5049
"hdkey": "^1.1.1",
5150
"randombytes": "^2.0.6",
51+
"scrypt-js": "^3.0.1",
5252
"utf8": "^3.0.0",
5353
"uuid": "^3.3.2"
5454
},

src/index.ts

Lines changed: 44 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
import * as crypto from 'crypto'
2-
import * as ethUtil from 'ethereumjs-util'
2+
import {
3+
BN,
4+
keccak256,
5+
bufferToHex,
6+
privateToAddress,
7+
publicToAddress,
8+
toChecksumAddress,
9+
privateToPublic,
10+
importPublic,
11+
isValidPrivate,
12+
isValidPublic,
13+
} from 'ethereumjs-util'
14+
import { scrypt } from 'scrypt-js'
315

416
export { default as hdkey } from './hdkey'
517
export { default as thirdparty } from './thirdparty'
618

719
const bs58check = require('bs58check')
820
const randomBytes = require('randombytes')
9-
const scryptsy = require('@web3-js/scrypt-shim')
1021
const uuidv4 = require('uuid/v4')
1122

1223
// parameters for the toV3() method
@@ -235,11 +246,11 @@ export default class Wallet {
235246
throw new Error('Cannot supply both a private and a public key to the constructor')
236247
}
237248

238-
if (privateKey && !ethUtil.isValidPrivate(privateKey)) {
249+
if (privateKey && !isValidPrivate(privateKey)) {
239250
throw new Error('Private key does not satisfy the curve requirements (ie. it is invalid)')
240251
}
241252

242-
if (publicKey && !ethUtil.isValidPublic(publicKey)) {
253+
if (publicKey && !isValidPublic(publicKey)) {
243254
throw new Error('Invalid public key')
244255
}
245256
}
@@ -253,10 +264,10 @@ export default class Wallet {
253264
*/
254265
public static generate(icapDirect: boolean = false): Wallet {
255266
if (icapDirect) {
256-
const max = new ethUtil.BN('088f924eeceeda7fe92e1f5b0fffffffffffffff', 16)
267+
const max = new BN('088f924eeceeda7fe92e1f5b0fffffffffffffff', 16)
257268
while (true) {
258269
const privateKey = randomBytes(32) as Buffer
259-
if (new ethUtil.BN(ethUtil.privateToAddress(privateKey)).lte(max)) {
270+
if (new BN(privateToAddress(privateKey)).lte(max)) {
260271
return new Wallet(privateKey)
261272
}
262273
}
@@ -275,7 +286,7 @@ export default class Wallet {
275286

276287
while (true) {
277288
const privateKey = randomBytes(32) as Buffer
278-
const address = ethUtil.privateToAddress(privateKey)
289+
const address = privateToAddress(privateKey)
279290

280291
if (pattern.test(address.toString('hex'))) {
281292
return new Wallet(privateKey)
@@ -291,7 +302,7 @@ export default class Wallet {
291302
*/
292303
public static fromPublicKey(publicKey: Buffer, nonStrict: boolean = false): Wallet {
293304
if (nonStrict) {
294-
publicKey = ethUtil.importPublic(publicKey)
305+
publicKey = importPublic(publicKey)
295306
}
296307
return new Wallet(undefined, publicKey)
297308
}
@@ -335,7 +346,7 @@ export default class Wallet {
335346
* @param input A JSON serialized string, or an object representing V1 Keystore.
336347
* @param password The keystore password.
337348
*/
338-
public static fromV1(input: string | V1Keystore, password: string): Wallet {
349+
public static async fromV1(input: string | V1Keystore, password: string): Promise<Wallet> {
339350
const json: V1Keystore = typeof input === 'object' ? input : JSON.parse(input)
340351
if (json.Version !== '1') {
341352
throw new Error('Not a V1 Wallet')
@@ -345,24 +356,24 @@ export default class Wallet {
345356
}
346357

347358
const kdfparams = json.Crypto.KeyHeader.KdfParams
348-
const derivedKey = scryptsy(
359+
const derivedKey = await scrypt(
349360
Buffer.from(password),
350361
Buffer.from(json.Crypto.Salt, 'hex'),
351362
kdfparams.N,
352363
kdfparams.R,
353364
kdfparams.P,
354365
kdfparams.DkLen,
355-
) as Buffer
366+
)
356367

357368
const ciphertext = Buffer.from(json.Crypto.CipherText, 'hex')
358-
const mac = ethUtil.keccak256(Buffer.concat([derivedKey.slice(16, 32), ciphertext]))
369+
const mac = keccak256(Buffer.concat([derivedKey.slice(16, 32), ciphertext]))
359370
if (mac.toString('hex') !== json.Crypto.MAC) {
360371
throw new Error('Key derivation failed - possibly wrong passphrase')
361372
}
362373

363374
const decipher = crypto.createDecipheriv(
364375
'aes-128-cbc',
365-
ethUtil.keccak256(derivedKey.slice(0, 16)).slice(0, 16),
376+
keccak256(derivedKey.slice(0, 16) as Buffer).slice(0, 16),
366377
Buffer.from(json.Crypto.IV, 'hex'),
367378
)
368379
const seed = runCipherBuffer(decipher, ciphertext)
@@ -375,31 +386,31 @@ export default class Wallet {
375386
* @param input A JSON serialized string, or an object representing V3 Keystore.
376387
* @param password The keystore password.
377388
*/
378-
public static fromV3(
389+
public static async fromV3(
379390
input: string | V3Keystore,
380391
password: string,
381392
nonStrict: boolean = false,
382-
): Wallet {
393+
): Promise<Wallet> {
383394
const json: V3Keystore =
384395
typeof input === 'object' ? input : JSON.parse(nonStrict ? input.toLowerCase() : input)
385396

386397
if (json.version !== 3) {
387398
throw new Error('Not a V3 wallet')
388399
}
389400

390-
let derivedKey: Buffer, kdfparams: any
401+
let derivedKey: Uint8Array, kdfparams: any
391402
if (json.crypto.kdf === 'scrypt') {
392403
kdfparams = json.crypto.kdfparams
393404

394405
// FIXME: support progress reporting callback
395-
derivedKey = scryptsy(
406+
derivedKey = await scrypt(
396407
Buffer.from(password),
397408
Buffer.from(kdfparams.salt, 'hex'),
398409
kdfparams.n,
399410
kdfparams.r,
400411
kdfparams.p,
401412
kdfparams.dklen,
402-
) as Buffer
413+
)
403414
} else if (json.crypto.kdf === 'pbkdf2') {
404415
kdfparams = json.crypto.kdfparams
405416

@@ -419,7 +430,7 @@ export default class Wallet {
419430
}
420431

421432
const ciphertext = Buffer.from(json.crypto.ciphertext, 'hex')
422-
const mac = ethUtil.keccak256(Buffer.concat([derivedKey.slice(16, 32), ciphertext]))
433+
const mac = keccak256(Buffer.concat([derivedKey.slice(16, 32), ciphertext]))
423434
if (mac.toString('hex') !== json.crypto.mac) {
424435
throw new Error('Key derivation failed - possibly wrong passphrase')
425436
}
@@ -455,7 +466,7 @@ export default class Wallet {
455466
const decipher = crypto.createDecipheriv('aes-128-cbc', derivedKey, encseed.slice(0, 16))
456467
const seed = runCipherBuffer(decipher, encseed.slice(16))
457468

458-
const wallet = new Wallet(ethUtil.keccak256(seed))
469+
const wallet = new Wallet(keccak256(seed))
459470
if (wallet.getAddress().toString('hex') !== json.ethaddr) {
460471
throw new Error('Decoded key mismatch - possibly wrong passphrase')
461472
}
@@ -469,7 +480,7 @@ export default class Wallet {
469480
*/
470481
private get pubKey(): Buffer {
471482
if (!keyExists(this.publicKey)) {
472-
this.publicKey = ethUtil.privateToPublic(this.privateKey as Buffer)
483+
this.publicKey = privateToPublic(this.privateKey as Buffer)
473484
}
474485
return this.publicKey
475486
}
@@ -496,7 +507,7 @@ export default class Wallet {
496507
}
497508

498509
public getPrivateKeyString(): string {
499-
return ethUtil.bufferToHex(this.privKey)
510+
return bufferToHex(this.privKey)
500511
}
501512

502513
/**
@@ -511,29 +522,29 @@ export default class Wallet {
511522
* Returns the wallet's public key as a "0x" prefixed hex string
512523
*/
513524
public getPublicKeyString(): string {
514-
return ethUtil.bufferToHex(this.getPublicKey())
525+
return bufferToHex(this.getPublicKey())
515526
}
516527

517528
/**
518529
* Returns the wallet's address.
519530
*/
520531
public getAddress(): Buffer {
521-
return ethUtil.publicToAddress(this.pubKey)
532+
return publicToAddress(this.pubKey)
522533
}
523534

524535
/**
525536
* Returns the wallet's address as a "0x" prefixed hex string
526537
*/
527538
public getAddressString(): string {
528-
return ethUtil.bufferToHex(this.getAddress())
539+
return bufferToHex(this.getAddress())
529540
}
530541

531542
/**
532543
* Returns the wallet's private key as a "0x" prefixed hex string checksummed
533544
* according to [EIP 55](https://github.com/ethereum/EIPs/issues/55).
534545
*/
535546
public getChecksumAddressString(): string {
536-
return ethUtil.toChecksumAddress(this.getAddressString())
547+
return toChecksumAddress(this.getAddressString())
537548
}
538549

539550
/**
@@ -542,15 +553,15 @@ export default class Wallet {
542553
* @param password The password used to encrypt the Keystore.
543554
* @param opts The options for the keystore. See [its spec](https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition) for more info.
544555
*/
545-
public toV3(password: string, opts?: Partial<V3Params>): V3Keystore {
556+
public async toV3(password: string, opts?: Partial<V3Params>): Promise<V3Keystore> {
546557
if (!keyExists(this.privateKey)) {
547558
throw new Error('This is a public key only wallet')
548559
}
549560

550561
const v3Params: V3ParamsStrict = mergeToV3ParamsWithDefaults(opts)
551562

552563
let kdfParams: KDFParams
553-
let derivedKey: Buffer
564+
let derivedKey: Uint8Array
554565
switch (v3Params.kdf) {
555566
case KDFFunctions.PBKDF:
556567
kdfParams = kdfParamsForPBKDF(v3Params)
@@ -565,14 +576,14 @@ export default class Wallet {
565576
case KDFFunctions.Scrypt:
566577
kdfParams = kdfParamsForScrypt(v3Params)
567578
// FIXME: support progress reporting callback
568-
derivedKey = scryptsy(
579+
derivedKey = await scrypt(
569580
Buffer.from(password),
570581
kdfParams.salt,
571582
kdfParams.n,
572583
kdfParams.r,
573584
kdfParams.p,
574585
kdfParams.dklen,
575-
) as Buffer
586+
)
576587
break
577588
default:
578589
throw new Error('Unsupported kdf')
@@ -588,9 +599,7 @@ export default class Wallet {
588599
}
589600

590601
const ciphertext = runCipherBuffer(cipher, this.privKey)
591-
const mac = ethUtil.keccak256(
592-
Buffer.concat([derivedKey.slice(16, 32), Buffer.from(ciphertext)]),
593-
)
602+
const mac = keccak256(Buffer.concat([derivedKey.slice(16, 32), Buffer.from(ciphertext)]))
594603

595604
return {
596605
version: 3,
@@ -632,8 +641,8 @@ export default class Wallet {
632641
)
633642
}
634643

635-
public toV3String(password: string, opts?: Partial<V3Params>): string {
636-
return JSON.stringify(this.toV3(password, opts))
644+
public async toV3String(password: string, opts?: Partial<V3Params>): Promise<string> {
645+
return JSON.stringify(await this.toV3(password, opts))
637646
}
638647
}
639648

src/thirdparty.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import * as crypto from 'crypto'
22
import { keccak256, sha256, toBuffer } from 'ethereumjs-util'
3+
import { scrypt } from 'scrypt-js'
34

45
import Wallet from './index'
56

6-
const scryptsy = require('@web3-js/scrypt-shim')
77
const utf8 = require('utf8')
88
const aesjs = require('aes-js')
99

@@ -173,7 +173,7 @@ export function fromEtherCamp(passphrase: string): Wallet {
173173
/**
174174
* Third Party API: Import a wallet from a KryptoKit seed
175175
*/
176-
export function fromKryptoKit(entropy: string, password: string): Wallet {
176+
export async function fromKryptoKit(entropy: string, password: string): Promise<Wallet> {
177177
function kryptoKitBrokenScryptSeed(buf: Buffer) {
178178
// js-scrypt calls `Buffer.from(String(salt), 'utf8')` on the seed even though it is a buffer
179179
//
@@ -220,7 +220,7 @@ export function fromKryptoKit(entropy: string, password: string): Wallet {
220220
const checksum = entropy.slice(30, 46)
221221

222222
const salt = kryptoKitBrokenScryptSeed(encryptedSeed)
223-
const aesKey = scryptsy(Buffer.from(password, 'utf8'), salt, 16384, 8, 1, 32)
223+
const aesKey = await scrypt(Buffer.from(password, 'utf8'), salt, 16384, 8, 1, 32)
224224

225225
/* FIXME: try to use `crypto` instead of `aesjs`
226226

0 commit comments

Comments
 (0)