From b8896b3b0df587b62e35bdd91858f42a89539f8d Mon Sep 17 00:00:00 2001 From: Dmitry Kochin Date: Wed, 25 Apr 2018 20:04:03 +0300 Subject: [PATCH 1/5] Added option: --startderive=n - start derivation from the specified index Added column: eth_address - shows Ethereum address for the corresponding public key (to support generation of ETH addresses) Updated code to reflect changes in bit-wasp dependency --- .gitignore | 1 + composer.json | 6 +- composer.lock | 619 ++++++++++++++++++++++++++++++++++++ hd-wallet-derive.php | 4 + lib/wallet_derive.class.php | 72 ++++- 5 files changed, 689 insertions(+), 13 deletions(-) create mode 100644 .gitignore create mode 100644 composer.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..61ead86 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/vendor diff --git a/composer.json b/composer.json index 5020c6d..5a56a74 100644 --- a/composer.json +++ b/composer.json @@ -6,9 +6,7 @@ "ext-json": "*", "php": ">=5.5", "dan-da/texttable-php": "^1.0", - "dan-da/strictmode-php": "^1.0" - }, - - "require-dev": { + "dan-da/strictmode-php": "^1.0", + "kornrunner/keccak": "^1.0" } } diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..005d9e2 --- /dev/null +++ b/composer.lock @@ -0,0 +1,619 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "f28c4b752f7b578068b9ce892c1cc83c", + "packages": [ + { + "name": "bitwasp/bitcoin", + "version": "v0.0.35.0", + "source": { + "type": "git", + "url": "https://github.com/Bit-Wasp/bitcoin-php.git", + "reference": "3dba2e678a6111ae81984637f51b23f760196000" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Bit-Wasp/bitcoin-php/zipball/3dba2e678a6111ae81984637f51b23f760196000", + "reference": "3dba2e678a6111ae81984637f51b23f760196000", + "shasum": "" + }, + "require": { + "bitwasp/buffertools": "^0.4.0", + "bitwasp/secp256k1-php": "^0.1.2", + "composer/semver": "^1.4.0", + "ext-bcmath": "*", + "ext-gmp": "*", + "ext-openssl": "*", + "lastguest/murmurhash": "v1.3.0", + "mdanter/ecc": "^0.4.0", + "paragonie/random_compat": "^1.4.0|^2.0.0", + "php-64bit": ">=5.6", + "pleonasm/merkle-tree": "1.0.0" + }, + "require-dev": { + "bitwasp/testing-php": "^0.1.1", + "ext-json": "*", + "nbobtc/bitcoind-php": "^2.0.0", + "phpunit/phpunit": "^5.4.0", + "squizlabs/php_codesniffer": "^2.0.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "BitWasp\\Bitcoin\\": "src/" + }, + "files": [ + "src/Script/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Unlicense" + ], + "authors": [ + { + "name": "Thomas Kerin", + "homepage": "https://thomaskerin.io", + "role": "Author" + } + ], + "description": "PHP Bitcoin library with functions for transactions, signatures, serialization, Random/Deterministic ECDSA keys, blocks, RPC bindings", + "homepage": "https://github.com/bit-wasp/bitcoin-php", + "time": "2018-03-12T20:36:54+00:00" + }, + { + "name": "bitwasp/buffertools", + "version": "v0.4.1", + "source": { + "type": "git", + "url": "https://github.com/Bit-Wasp/buffertools-php.git", + "reference": "5ac7578fc00d093075a493320bd0a01d1ae0128c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Bit-Wasp/buffertools-php/zipball/5ac7578fc00d093075a493320bd0a01d1ae0128c", + "reference": "5ac7578fc00d093075a493320bd0a01d1ae0128c", + "shasum": "" + }, + "require": { + "mdanter/ecc": "~0.4" + }, + "require-dev": { + "phpunit/phpunit": "~5.0", + "satooshi/php-coveralls": "~0.6.1", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "BitWasp\\Buffertools\\": "src/Buffertools/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Thomas Kerin", + "homepage": "https://thomaskerin.io" + }, + { + "name": "Ruben de Vries", + "email": "ruben@rubensayshi.com" + } + ], + "description": "Toolbox for working with binary and hex data. Similar to NodeJS Buffer.", + "time": "2017-06-21T18:23:36+00:00" + }, + { + "name": "bitwasp/secp256k1-php", + "version": "v0.1.3", + "source": { + "type": "git", + "url": "https://github.com/Bit-Wasp/secp256k1-php.git", + "reference": "0ad10c06f36fa5caea6f7276315c2fae6262708e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Bit-Wasp/secp256k1-php/zipball/0ad10c06f36fa5caea6f7276315c2fae6262708e", + "reference": "0ad10c06f36fa5caea6f7276315c2fae6262708e", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "^6.5", + "squizlabs/php_codesniffer": "2.*", + "symfony/yaml": "^3.4" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Unlicense" + ], + "authors": [ + { + "name": "Ruben de Vries", + "email": "ruben@rubensayshi.com" + }, + { + "name": "Thomas Kerin", + "email": "afk11@users.noreply.github.com" + } + ], + "description": "PHP Extension with bindings for bitcoin/secp256k1.", + "keywords": [ + "ECDSA", + "bitcoin", + "bitwasp", + "cryptocurrency", + "ecc", + "extension", + "php", + "secp256k1" + ], + "time": "2018-02-17T14:24:05+00:00" + }, + { + "name": "composer/semver", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", + "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.5 || ^5.0.5", + "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "time": "2016-08-30T16:08:34+00:00" + }, + { + "name": "dan-da/strictmode-php", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/dan-da/strictmode-php.git", + "reference": "0436f60b0ba0e7be1e99ed97ded422b5fe94dc3b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dan-da/strictmode-php/zipball/0436f60b0ba0e7be1e99ed97ded422b5fe94dc3b", + "reference": "0436f60b0ba0e7be1e99ed97ded422b5fe94dc3b", + "shasum": "" + }, + "require": { + "dan-da/tester-php": "^1.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "strictmode.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "time": "2017-09-06T13:19:46+00:00" + }, + { + "name": "dan-da/tester-php", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/dan-da/tester-php.git", + "reference": "b6d643cc98803a3488b9030d3c3f3eec463325e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dan-da/tester-php/zipball/b6d643cc98803a3488b9030d3c3f3eec463325e5", + "reference": "b6d643cc98803a3488b9030d3c3f3eec463325e5", + "shasum": "" + }, + "bin": [ + "tester.php" + ], + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "time": "2017-09-06T11:40:46+00:00" + }, + { + "name": "dan-da/texttable-php", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/dan-da/texttable-php.git", + "reference": "3a3dfe5c70c1a278366842519fed5f3bbee8d095" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dan-da/texttable-php/zipball/3a3dfe5c70c1a278366842519fed5f3bbee8d095", + "reference": "3a3dfe5c70c1a278366842519fed5f3bbee8d095", + "shasum": "" + }, + "require": { + "dan-da/strictmode-php": "^1.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "texttable.class.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "time": "2017-09-06T13:51:24+00:00" + }, + { + "name": "fgrosse/phpasn1", + "version": "1.5.3", + "source": { + "type": "git", + "url": "https://github.com/fgrosse/PHPASN1.git", + "reference": "40244500384f8b96f5952076f3e05fb56a815c55" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fgrosse/PHPASN1/zipball/40244500384f8b96f5952076f3e05fb56a815c55", + "reference": "40244500384f8b96f5952076f3e05fb56a815c55", + "shasum": "" + }, + "require": { + "ext-gmp": "*", + "php": ">=5.6.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.5", + "satooshi/php-coveralls": "dev-master" + }, + "suggest": { + "php-curl": "For loading OID information from the web if they have not bee defined statically" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5.x-dev" + } + }, + "autoload": { + "psr-4": { + "FG\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Friedrich Große", + "email": "friedrich.grosse@gmail.com", + "homepage": "https://github.com/FGrosse", + "role": "Author" + }, + { + "name": "All contributors", + "homepage": "https://github.com/FGrosse/PHPASN1/contributors" + } + ], + "description": "A PHP Framework that allows you to encode and decode arbitrary ASN.1 structures using the ITU-T X.690 Encoding Rules.", + "homepage": "https://github.com/FGrosse/PHPASN1", + "keywords": [ + "DER", + "asn.1", + "asn1", + "ber", + "binary", + "decoding", + "encoding", + "x.509", + "x.690", + "x509", + "x690" + ], + "time": "2017-12-17T10:18:20+00:00" + }, + { + "name": "kornrunner/keccak", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/kornrunner/php-keccak.git", + "reference": "b3cd83ded1acff7af40b4ca5b8ea76b164ed0c34" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kornrunner/php-keccak/zipball/b3cd83ded1acff7af40b4ca5b8ea76b164ed0c34", + "reference": "b3cd83ded1acff7af40b4ca5b8ea76b164ed0c34", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpunit/phpunit": "~7", + "satooshi/php-coveralls": "~2" + }, + "type": "library", + "autoload": { + "psr-4": { + "kornrunner\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Boris Momcilovic", + "homepage": "https://github.com/kornrunner/php-keccak" + } + ], + "description": "Pure PHP implementation of Keccak", + "keywords": [ + "keccak", + "sha-3" + ], + "time": "2018-03-05T10:32:01+00:00" + }, + { + "name": "lastguest/murmurhash", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/lastguest/murmurhash-php.git", + "reference": "8eb06483456bc98f5adb7707d981a8ef6a065fa2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lastguest/murmurhash-php/zipball/8eb06483456bc98f5adb7707d981a8ef6a065fa2", + "reference": "8eb06483456bc98f5adb7707d981a8ef6a065fa2", + "shasum": "" + }, + "require": { + "php": ">=4.3" + }, + "type": "library", + "autoload": { + "files": [ + "murmurhash3.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Stefano Azzolini", + "email": "lastguest@gmail.com", + "homepage": "https://github.com/lastguest/murmurhash-php" + } + ], + "description": "MurmurHash3 Hash", + "homepage": "https://github.com/lastguest/murmurhash-php", + "keywords": [ + "hash", + "hashing", + "murmur" + ], + "time": "2016-05-16T23:22:58+00:00" + }, + { + "name": "mdanter/ecc", + "version": "v0.4.5", + "source": { + "type": "git", + "url": "https://github.com/phpecc/phpecc.git", + "reference": "9ed6017fbae2fd1105e0d81e703007d353b7587b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpecc/phpecc/zipball/9ed6017fbae2fd1105e0d81e703007d353b7587b", + "reference": "9ed6017fbae2fd1105e0d81e703007d353b7587b", + "shasum": "" + }, + "require": { + "ext-gmp": "*", + "fgrosse/phpasn1": "~1.5", + "paragonie/random_compat": "^1|^2", + "php": ">=5.6.0, <7.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.1|~5.0", + "squizlabs/php_codesniffer": "~2", + "symfony/yaml": "~2.6|~3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Mdanter\\Ecc\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matyas Danter", + "homepage": "http://matejdanter.com/", + "role": "Author" + }, + { + "name": "Thibaud Fabre", + "email": "thibaud@aztech.io", + "homepage": "http://aztech.io", + "role": "Maintainer" + } + ], + "description": "PHP Elliptic Curve Cryptography library", + "homepage": "https://github.com/phpecc/phpecc", + "keywords": [ + "Diffie", + "ECDSA", + "Hellman", + "curve", + "ecdh", + "elliptic", + "nistp192", + "nistp224", + "nistp256", + "nistp521", + "phpecc", + "secp256k1" + ], + "time": "2017-12-12T12:13:30+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v2.0.12", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb", + "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "autoload": { + "files": [ + "lib/random.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "pseudorandom", + "random" + ], + "time": "2018-04-04T21:24:14+00:00" + }, + { + "name": "pleonasm/merkle-tree", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/pleonasm/merkle-tree.git", + "reference": "9ddc9d0a0e396750fada378f3aa90f6c02dd56a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pleonasm/merkle-tree/zipball/9ddc9d0a0e396750fada378f3aa90f6c02dd56a1", + "reference": "9ddc9d0a0e396750fada378f3aa90f6c02dd56a1", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "ext-xdebug": ">=2.2.0", + "phpunit/php-invoker": ">=1.0.0,<1.2.0", + "phpunit/phpunit": "3.7.19", + "satooshi/php-coveralls": "*@dev", + "squizlabs/php_codesniffer": "*" + }, + "type": "library", + "autoload": { + "psr-0": { + "Pleo": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Matthew Nagi", + "email": "matthew.nagi@base-2.net" + } + ], + "description": "An implementation of a Merkle Tree in PHP", + "time": "2013-05-22T20:46:20+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "ext-json": "*", + "php": ">=5.5" + }, + "platform-dev": [] +} diff --git a/hd-wallet-derive.php b/hd-wallet-derive.php index 72c5dde..732830c 100755 --- a/hd-wallet-derive.php +++ b/hd-wallet-derive.php @@ -60,6 +60,7 @@ function get_cli_params() { 'mnemonic-pw:', 'outfile:', 'numderive:', + 'startderive:', 'includeroot', 'path:', 'format:', 'cols:', @@ -112,6 +113,7 @@ function process_cli_params( $params ) { $params['format'] = @$params['format'] ?: 'txt'; $params['cols'] = @$params['cols'] ?: 'all'; $params['numderive'] = @$params['numderive'] ?: 10; + $params['startderive'] = @$params['startderive'] ?: 0; $params['includeroot'] = isset($params['includeroot'] ); return [$params, $success]; @@ -153,6 +155,8 @@ function print_help() { --mnemonic-pw= optionally specify password for mnemonic. --numderive= Number of keys to derive. default=10 + + --startderive= Starting key index to derive. default=0 --cols= a csv list of columns, or "all" all: diff --git a/lib/wallet_derive.class.php b/lib/wallet_derive.class.php index 4cf7640..a10cc54 100644 --- a/lib/wallet_derive.class.php +++ b/lib/wallet_derive.class.php @@ -7,11 +7,20 @@ use \BitWasp\Bitcoin\Address; use \BitWasp\Bitcoin\Key\Deterministic\HierarchicalKeyFactory; use \BitWasp\Buffertools\Buffer; +use \BitWasp\Bitcoin\Address\PayToPubKeyHashAddress; // For Bip39 Mnemonics use \BitWasp\Bitcoin\Mnemonic\Bip39\Bip39SeedGenerator; use BitWasp\Bitcoin\Mnemonic\MnemonicFactory; +// For ethereum addresses +use kornrunner\Keccak; +use BitWasp\Bitcoin\Crypto\EcAdapter\Key\PublicKeyInterface; +use BitWasp\Bitcoin\Crypto\EcAdapter\Impl\PhpEcc\Serializer\Key\PublicKeySerializer; +use BitWasp\Bitcoin\Crypto\EcAdapter\EcAdapterFactory; +use Mdanter\Ecc\Serializer\Point\UncompressedPointSerializer; +use Mdanter\Ecc\EccFactory; + // For generating html tables. require_once __DIR__ . '/html_table.class.php'; @@ -36,6 +45,40 @@ private function get_params() { return $this->params; } + private function getEthereumAddress(PublicKeyInterface $publicKey){ + static $pubkey_serializer = null; + static $point_serializer = null; + if(!$pubkey_serializer){ + $adapter = EcAdapterFactory::getPhpEcc(Bitcoin::getMath(), Bitcoin::getGenerator()); + $pubkey_serializer = new PublicKeySerializer($adapter); + $point_serializer = new UncompressedPointSerializer(EccFactory::getAdapter()); + } + + $pubKey = $pubkey_serializer->parse($publicKey->getHex()); + $point = $pubKey->getPoint(); + $upk = $point_serializer->serialize($point); + $upk = hex2bin(substr($upk, 2)); + + $keccak = Keccak::hash($upk, 256); + $eth_address_lower = strtolower(substr($keccak, -40)); + + $hash = Keccak::hash($eth_address_lower, 256); + $eth_address = ''; + for($i = 0; $i < 40; $i++) { + // the nth letter should be uppercase if the nth digit of casemap is 1 + $char = substr($eth_address_lower, $i, 1); + + if(ctype_digit($char)) + $eth_address .= $char; + else if('0' <= $hash[$i] && $hash[$i] <= '7') + $eth_address .= strtolower($char); + else + $eth_address .= strtoupper($char); + } + + return '0x'. $eth_address; + } + /* Derives child keys/addresses for a given key. */ public function derive_keys($key) { @@ -49,16 +92,20 @@ public function derive_keys($key) { $master = HierarchicalKeyFactory::fromExtended($key, $network); - $start = 0; - $end = $params['numderive']; + $start = $params['startderive']; + $end = $params['startderive'] + $params['numderive']; if( $params['includeroot'] ) { - $address = $master->getPublicKey()->getAddress()->getAddress(); + $publicKey = $master->getPublicKey(); + $address = new PayToPubKeyHashAddress($publicKey->getPubKeyHash()); + $address = $address->getAddress(); + $xprv = $master->isPrivate() ? $master->toExtendedKey($network) : null; $wif = $master->isPrivate() ? $master->getPrivateKey()->toWif($network) : null; - $pubkey = $master->getPublicKey()->getHex(); - $pubkeyhash = $master->getPublicKey()->getPubKeyHash()->getHex(); + $pubkey = $publicKey->getHex(); + $pubkeyhash = $publicKey->getPubKeyHash()->getHex(); $xpub = $master->toExtendedPublicKey($network); + $eth_address = $this->getEthereumAddress($publicKey); $addrs[] = array( 'xprv' => $xprv, 'privkey' => $wif, @@ -66,6 +113,7 @@ public function derive_keys($key) { 'pubkeyhash' => $pubkey, 'xpub' => $xpub, 'address' => $address, + 'eth_address' => $eth_address, 'index' => null, 'path' => 'm'); } @@ -82,12 +130,17 @@ public function derive_keys($key) { // fixme: hack for copay/multisig. maybe should use a callback? if(method_exists($key, 'getPublicKey')) { // bip32 path - $address = $key->getPublicKey()->getAddress()->getAddress(); + $publicKey = $key->getPublicKey(); + $address = new PayToPubKeyHashAddress($publicKey->getPubKeyHash()); + $address = $address->getAddress(); + $xprv = $key->isPrivate() ? $key->toExtendedKey($network) : null; $priv_wif = $key->isPrivate() ? $key->getPrivateKey()->toWif($network) : null; - $pubkey = $key->getPublicKey()->getHex(); - $pubkeyhash = $key->getPublicKey()->getPubKeyHash()->getHex(); + $pubkey = $publicKey->getHex(); + $pubkeyhash = $publicKey->getPubKeyHash()->getHex(); $xpub = $key->toExtendedPublicKey($network); + + $eth_address = $this->getEthereumAddress($publicKey); } else { throw new Exception("multisig keys not supported"); @@ -98,6 +151,7 @@ public function derive_keys($key) { 'pubkeyhash' => $pubkeyhash, 'xpub' => $xpub, 'address' => $address, + 'eth_address' => $eth_address, 'index' => $i, 'path' => $path); } @@ -124,7 +178,7 @@ static public function mnemonicToKey($mnemonic, $password=null) { /* Returns all columns available for reports */ static public function all_cols() { - return ['path', 'address', 'xprv', 'xpub', 'privkey', 'pubkey', 'pubkeyhash', 'index']; + return ['path', 'address', 'xprv', 'xpub', 'privkey', 'pubkey', 'pubkeyhash', 'index', 'eth_address']; } /* Returns default reporting columns From 00fd70d80381dfca2ddfc092851eee0c20fb9fc9 Mon Sep 17 00:00:00 2001 From: Dmitry Kochin Date: Wed, 25 Apr 2018 20:36:49 +0300 Subject: [PATCH 2/5] Update README.md Described changes --- README.md | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 5b60707..ef60753 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # hd-wallet-derive -A command-line tool that derives bip32 addresses and private keys. +A command-line tool that derives bip32 addresses and private keys for Bitcoin and Ethereum. -Derivation reports show privkey (wif encoded), xprv, xpub, and address. +Derivation reports show privkey (wif encoded), xprv, xpub, and addresses for Bitcoin and Ethereum . Input can be a xprv key, xpub key, or bip39 mnemonic string (eg 12 words) with optional password. @@ -246,34 +246,38 @@ The report may be printed in the following formats: Options: -g go! ( required ) - + --key= xpriv or xpub key --mnemonic= bip39 seed words note: either key or nmemonic is required. - + --mnemonic-pw= optionally specify password for mnemonic. - + + --numderive= Number of keys to derive. default=10 + + --startderive= Starting key index to derive. default=0 + --cols= a csv list of columns, or "all" all: - (path,xprv,xpub,privkey,address,index) + (path,address,xprv,xpub,privkey,pubkey,pubkeyhash,index,eth_address) default: - (path,privkey,address) + (path,address,privkey) --outfile= specify output file path. --format= txt|csv|json|jsonpretty|html|list|all default=txt - + if 'all' is specified then a file will be created for each format with appropriate extension. only works when outfile is specified. - + 'list' prints only the first column. see --cols - + --path= bip32 path to derive, relative to provided key (m). eg "", "m/0" or "m/1" default = "m" - + --includeroot include root key as first element of report. - + --logfile= path to logfile. if not present logs to stdout. --loglevel= debug,info,specialinfo,warning,exception,fatalerror default = info From 9185d8036d8d3457af8f35906d5c77ae3374d955 Mon Sep 17 00:00:00 2001 From: danda Date: Fri, 22 Jun 2018 18:08:49 +0800 Subject: [PATCH 3/5] remove composer.lock --- composer.lock | 619 -------------------------------------------------- 1 file changed, 619 deletions(-) delete mode 100644 composer.lock diff --git a/composer.lock b/composer.lock deleted file mode 100644 index 005d9e2..0000000 --- a/composer.lock +++ /dev/null @@ -1,619 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "f28c4b752f7b578068b9ce892c1cc83c", - "packages": [ - { - "name": "bitwasp/bitcoin", - "version": "v0.0.35.0", - "source": { - "type": "git", - "url": "https://github.com/Bit-Wasp/bitcoin-php.git", - "reference": "3dba2e678a6111ae81984637f51b23f760196000" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Bit-Wasp/bitcoin-php/zipball/3dba2e678a6111ae81984637f51b23f760196000", - "reference": "3dba2e678a6111ae81984637f51b23f760196000", - "shasum": "" - }, - "require": { - "bitwasp/buffertools": "^0.4.0", - "bitwasp/secp256k1-php": "^0.1.2", - "composer/semver": "^1.4.0", - "ext-bcmath": "*", - "ext-gmp": "*", - "ext-openssl": "*", - "lastguest/murmurhash": "v1.3.0", - "mdanter/ecc": "^0.4.0", - "paragonie/random_compat": "^1.4.0|^2.0.0", - "php-64bit": ">=5.6", - "pleonasm/merkle-tree": "1.0.0" - }, - "require-dev": { - "bitwasp/testing-php": "^0.1.1", - "ext-json": "*", - "nbobtc/bitcoind-php": "^2.0.0", - "phpunit/phpunit": "^5.4.0", - "squizlabs/php_codesniffer": "^2.0.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "BitWasp\\Bitcoin\\": "src/" - }, - "files": [ - "src/Script/functions.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Unlicense" - ], - "authors": [ - { - "name": "Thomas Kerin", - "homepage": "https://thomaskerin.io", - "role": "Author" - } - ], - "description": "PHP Bitcoin library with functions for transactions, signatures, serialization, Random/Deterministic ECDSA keys, blocks, RPC bindings", - "homepage": "https://github.com/bit-wasp/bitcoin-php", - "time": "2018-03-12T20:36:54+00:00" - }, - { - "name": "bitwasp/buffertools", - "version": "v0.4.1", - "source": { - "type": "git", - "url": "https://github.com/Bit-Wasp/buffertools-php.git", - "reference": "5ac7578fc00d093075a493320bd0a01d1ae0128c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Bit-Wasp/buffertools-php/zipball/5ac7578fc00d093075a493320bd0a01d1ae0128c", - "reference": "5ac7578fc00d093075a493320bd0a01d1ae0128c", - "shasum": "" - }, - "require": { - "mdanter/ecc": "~0.4" - }, - "require-dev": { - "phpunit/phpunit": "~5.0", - "satooshi/php-coveralls": "~0.6.1", - "squizlabs/php_codesniffer": "~2.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "BitWasp\\Buffertools\\": "src/Buffertools/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Thomas Kerin", - "homepage": "https://thomaskerin.io" - }, - { - "name": "Ruben de Vries", - "email": "ruben@rubensayshi.com" - } - ], - "description": "Toolbox for working with binary and hex data. Similar to NodeJS Buffer.", - "time": "2017-06-21T18:23:36+00:00" - }, - { - "name": "bitwasp/secp256k1-php", - "version": "v0.1.3", - "source": { - "type": "git", - "url": "https://github.com/Bit-Wasp/secp256k1-php.git", - "reference": "0ad10c06f36fa5caea6f7276315c2fae6262708e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Bit-Wasp/secp256k1-php/zipball/0ad10c06f36fa5caea6f7276315c2fae6262708e", - "reference": "0ad10c06f36fa5caea6f7276315c2fae6262708e", - "shasum": "" - }, - "require-dev": { - "phpunit/phpunit": "^6.5", - "squizlabs/php_codesniffer": "2.*", - "symfony/yaml": "^3.4" - }, - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Unlicense" - ], - "authors": [ - { - "name": "Ruben de Vries", - "email": "ruben@rubensayshi.com" - }, - { - "name": "Thomas Kerin", - "email": "afk11@users.noreply.github.com" - } - ], - "description": "PHP Extension with bindings for bitcoin/secp256k1.", - "keywords": [ - "ECDSA", - "bitcoin", - "bitwasp", - "cryptocurrency", - "ecc", - "extension", - "php", - "secp256k1" - ], - "time": "2018-02-17T14:24:05+00:00" - }, - { - "name": "composer/semver", - "version": "1.4.2", - "source": { - "type": "git", - "url": "https://github.com/composer/semver.git", - "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573", - "reference": "c7cb9a2095a074d131b65a8a0cd294479d785573", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.5 || ^5.0.5", - "phpunit/phpunit-mock-objects": "2.3.0 || ^3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Composer\\Semver\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nils Adermann", - "email": "naderman@naderman.de", - "homepage": "http://www.naderman.de" - }, - { - "name": "Jordi Boggiano", - "email": "j.boggiano@seld.be", - "homepage": "http://seld.be" - }, - { - "name": "Rob Bast", - "email": "rob.bast@gmail.com", - "homepage": "http://robbast.nl" - } - ], - "description": "Semver library that offers utilities, version constraint parsing and validation.", - "keywords": [ - "semantic", - "semver", - "validation", - "versioning" - ], - "time": "2016-08-30T16:08:34+00:00" - }, - { - "name": "dan-da/strictmode-php", - "version": "v1.0.0", - "source": { - "type": "git", - "url": "https://github.com/dan-da/strictmode-php.git", - "reference": "0436f60b0ba0e7be1e99ed97ded422b5fe94dc3b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dan-da/strictmode-php/zipball/0436f60b0ba0e7be1e99ed97ded422b5fe94dc3b", - "reference": "0436f60b0ba0e7be1e99ed97ded422b5fe94dc3b", - "shasum": "" - }, - "require": { - "dan-da/tester-php": "^1.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "strictmode.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "time": "2017-09-06T13:19:46+00:00" - }, - { - "name": "dan-da/tester-php", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/dan-da/tester-php.git", - "reference": "b6d643cc98803a3488b9030d3c3f3eec463325e5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dan-da/tester-php/zipball/b6d643cc98803a3488b9030d3c3f3eec463325e5", - "reference": "b6d643cc98803a3488b9030d3c3f3eec463325e5", - "shasum": "" - }, - "bin": [ - "tester.php" - ], - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "time": "2017-09-06T11:40:46+00:00" - }, - { - "name": "dan-da/texttable-php", - "version": "v1.0.2", - "source": { - "type": "git", - "url": "https://github.com/dan-da/texttable-php.git", - "reference": "3a3dfe5c70c1a278366842519fed5f3bbee8d095" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/dan-da/texttable-php/zipball/3a3dfe5c70c1a278366842519fed5f3bbee8d095", - "reference": "3a3dfe5c70c1a278366842519fed5f3bbee8d095", - "shasum": "" - }, - "require": { - "dan-da/strictmode-php": "^1.0" - }, - "type": "library", - "autoload": { - "classmap": [ - "texttable.class.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "time": "2017-09-06T13:51:24+00:00" - }, - { - "name": "fgrosse/phpasn1", - "version": "1.5.3", - "source": { - "type": "git", - "url": "https://github.com/fgrosse/PHPASN1.git", - "reference": "40244500384f8b96f5952076f3e05fb56a815c55" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/fgrosse/PHPASN1/zipball/40244500384f8b96f5952076f3e05fb56a815c55", - "reference": "40244500384f8b96f5952076f3e05fb56a815c55", - "shasum": "" - }, - "require": { - "ext-gmp": "*", - "php": ">=5.6.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.5", - "satooshi/php-coveralls": "dev-master" - }, - "suggest": { - "php-curl": "For loading OID information from the web if they have not bee defined statically" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.5.x-dev" - } - }, - "autoload": { - "psr-4": { - "FG\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Friedrich Große", - "email": "friedrich.grosse@gmail.com", - "homepage": "https://github.com/FGrosse", - "role": "Author" - }, - { - "name": "All contributors", - "homepage": "https://github.com/FGrosse/PHPASN1/contributors" - } - ], - "description": "A PHP Framework that allows you to encode and decode arbitrary ASN.1 structures using the ITU-T X.690 Encoding Rules.", - "homepage": "https://github.com/FGrosse/PHPASN1", - "keywords": [ - "DER", - "asn.1", - "asn1", - "ber", - "binary", - "decoding", - "encoding", - "x.509", - "x.690", - "x509", - "x690" - ], - "time": "2017-12-17T10:18:20+00:00" - }, - { - "name": "kornrunner/keccak", - "version": "1.0.2", - "source": { - "type": "git", - "url": "https://github.com/kornrunner/php-keccak.git", - "reference": "b3cd83ded1acff7af40b4ca5b8ea76b164ed0c34" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/kornrunner/php-keccak/zipball/b3cd83ded1acff7af40b4ca5b8ea76b164ed0c34", - "reference": "b3cd83ded1acff7af40b4ca5b8ea76b164ed0c34", - "shasum": "" - }, - "require": { - "php": ">=7.1.0" - }, - "require-dev": { - "phpunit/phpunit": "~7", - "satooshi/php-coveralls": "~2" - }, - "type": "library", - "autoload": { - "psr-4": { - "kornrunner\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Boris Momcilovic", - "homepage": "https://github.com/kornrunner/php-keccak" - } - ], - "description": "Pure PHP implementation of Keccak", - "keywords": [ - "keccak", - "sha-3" - ], - "time": "2018-03-05T10:32:01+00:00" - }, - { - "name": "lastguest/murmurhash", - "version": "1.3.0", - "source": { - "type": "git", - "url": "https://github.com/lastguest/murmurhash-php.git", - "reference": "8eb06483456bc98f5adb7707d981a8ef6a065fa2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/lastguest/murmurhash-php/zipball/8eb06483456bc98f5adb7707d981a8ef6a065fa2", - "reference": "8eb06483456bc98f5adb7707d981a8ef6a065fa2", - "shasum": "" - }, - "require": { - "php": ">=4.3" - }, - "type": "library", - "autoload": { - "files": [ - "murmurhash3.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Stefano Azzolini", - "email": "lastguest@gmail.com", - "homepage": "https://github.com/lastguest/murmurhash-php" - } - ], - "description": "MurmurHash3 Hash", - "homepage": "https://github.com/lastguest/murmurhash-php", - "keywords": [ - "hash", - "hashing", - "murmur" - ], - "time": "2016-05-16T23:22:58+00:00" - }, - { - "name": "mdanter/ecc", - "version": "v0.4.5", - "source": { - "type": "git", - "url": "https://github.com/phpecc/phpecc.git", - "reference": "9ed6017fbae2fd1105e0d81e703007d353b7587b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpecc/phpecc/zipball/9ed6017fbae2fd1105e0d81e703007d353b7587b", - "reference": "9ed6017fbae2fd1105e0d81e703007d353b7587b", - "shasum": "" - }, - "require": { - "ext-gmp": "*", - "fgrosse/phpasn1": "~1.5", - "paragonie/random_compat": "^1|^2", - "php": ">=5.6.0, <7.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.1|~5.0", - "squizlabs/php_codesniffer": "~2", - "symfony/yaml": "~2.6|~3.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Mdanter\\Ecc\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Matyas Danter", - "homepage": "http://matejdanter.com/", - "role": "Author" - }, - { - "name": "Thibaud Fabre", - "email": "thibaud@aztech.io", - "homepage": "http://aztech.io", - "role": "Maintainer" - } - ], - "description": "PHP Elliptic Curve Cryptography library", - "homepage": "https://github.com/phpecc/phpecc", - "keywords": [ - "Diffie", - "ECDSA", - "Hellman", - "curve", - "ecdh", - "elliptic", - "nistp192", - "nistp224", - "nistp256", - "nistp521", - "phpecc", - "secp256k1" - ], - "time": "2017-12-12T12:13:30+00:00" - }, - { - "name": "paragonie/random_compat", - "version": "v2.0.12", - "source": { - "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb", - "reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb", - "shasum": "" - }, - "require": { - "php": ">=5.2.0" - }, - "require-dev": { - "phpunit/phpunit": "4.*|5.*" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." - }, - "type": "library", - "autoload": { - "files": [ - "lib/random.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", - "keywords": [ - "csprng", - "pseudorandom", - "random" - ], - "time": "2018-04-04T21:24:14+00:00" - }, - { - "name": "pleonasm/merkle-tree", - "version": "1.0.0", - "source": { - "type": "git", - "url": "https://github.com/pleonasm/merkle-tree.git", - "reference": "9ddc9d0a0e396750fada378f3aa90f6c02dd56a1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pleonasm/merkle-tree/zipball/9ddc9d0a0e396750fada378f3aa90f6c02dd56a1", - "reference": "9ddc9d0a0e396750fada378f3aa90f6c02dd56a1", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "ext-xdebug": ">=2.2.0", - "phpunit/php-invoker": ">=1.0.0,<1.2.0", - "phpunit/phpunit": "3.7.19", - "satooshi/php-coveralls": "*@dev", - "squizlabs/php_codesniffer": "*" - }, - "type": "library", - "autoload": { - "psr-0": { - "Pleo": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-2-Clause" - ], - "authors": [ - { - "name": "Matthew Nagi", - "email": "matthew.nagi@base-2.net" - } - ], - "description": "An implementation of a Merkle Tree in PHP", - "time": "2013-05-22T20:46:20+00:00" - } - ], - "packages-dev": [], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "ext-json": "*", - "php": ">=5.5" - }, - "platform-dev": [] -} From 440b9a1a0340197cd288acb689f7ddbfdb022c99 Mon Sep 17 00:00:00 2001 From: danda Date: Fri, 22 Jun 2018 18:26:00 +0800 Subject: [PATCH 4/5] spaces to tabs --- lib/wallet_derive.class.php | 56 ++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/wallet_derive.class.php b/lib/wallet_derive.class.php index a10cc54..60f8f36 100644 --- a/lib/wallet_derive.class.php +++ b/lib/wallet_derive.class.php @@ -46,18 +46,18 @@ private function get_params() { } private function getEthereumAddress(PublicKeyInterface $publicKey){ - static $pubkey_serializer = null; - static $point_serializer = null; - if(!$pubkey_serializer){ - $adapter = EcAdapterFactory::getPhpEcc(Bitcoin::getMath(), Bitcoin::getGenerator()); - $pubkey_serializer = new PublicKeySerializer($adapter); - $point_serializer = new UncompressedPointSerializer(EccFactory::getAdapter()); - } - - $pubKey = $pubkey_serializer->parse($publicKey->getHex()); - $point = $pubKey->getPoint(); - $upk = $point_serializer->serialize($point); - $upk = hex2bin(substr($upk, 2)); + static $pubkey_serializer = null; + static $point_serializer = null; + if(!$pubkey_serializer){ + $adapter = EcAdapterFactory::getPhpEcc(Bitcoin::getMath(), Bitcoin::getGenerator()); + $pubkey_serializer = new PublicKeySerializer($adapter); + $point_serializer = new UncompressedPointSerializer(EccFactory::getAdapter()); + } + + $pubKey = $pubkey_serializer->parse($publicKey->getHex()); + $point = $pubKey->getPoint(); + $upk = $point_serializer->serialize($point); + $upk = hex2bin(substr($upk, 2)); $keccak = Keccak::hash($upk, 256); $eth_address_lower = strtolower(substr($keccak, -40)); @@ -65,15 +65,15 @@ private function getEthereumAddress(PublicKeyInterface $publicKey){ $hash = Keccak::hash($eth_address_lower, 256); $eth_address = ''; for($i = 0; $i < 40; $i++) { - // the nth letter should be uppercase if the nth digit of casemap is 1 - $char = substr($eth_address_lower, $i, 1); - - if(ctype_digit($char)) - $eth_address .= $char; - else if('0' <= $hash[$i] && $hash[$i] <= '7') - $eth_address .= strtolower($char); - else - $eth_address .= strtoupper($char); + // the nth letter should be uppercase if the nth digit of casemap is 1 + $char = substr($eth_address_lower, $i, 1); + + if(ctype_digit($char)) + $eth_address .= $char; + else if('0' <= $hash[$i] && $hash[$i] <= '7') + $eth_address .= strtolower($char); + else + $eth_address .= strtoupper($char); } return '0x'. $eth_address; @@ -96,9 +96,9 @@ public function derive_keys($key) { $end = $params['startderive'] + $params['numderive']; if( $params['includeroot'] ) { - $publicKey = $master->getPublicKey(); - $address = new PayToPubKeyHashAddress($publicKey->getPubKeyHash()); - $address = $address->getAddress(); + $publicKey = $master->getPublicKey(); + $address = new PayToPubKeyHashAddress($publicKey->getPubKeyHash()); + $address = $address->getAddress(); $xprv = $master->isPrivate() ? $master->toExtendedKey($network) : null; $wif = $master->isPrivate() ? $master->getPrivateKey()->toWif($network) : null; @@ -130,9 +130,9 @@ public function derive_keys($key) { // fixme: hack for copay/multisig. maybe should use a callback? if(method_exists($key, 'getPublicKey')) { // bip32 path - $publicKey = $key->getPublicKey(); - $address = new PayToPubKeyHashAddress($publicKey->getPubKeyHash()); - $address = $address->getAddress(); + $publicKey = $key->getPublicKey(); + $address = new PayToPubKeyHashAddress($publicKey->getPubKeyHash()); + $address = $address->getAddress(); $xprv = $key->isPrivate() ? $key->toExtendedKey($network) : null; $priv_wif = $key->isPrivate() ? $key->getPrivateKey()->toWif($network) : null; @@ -140,7 +140,7 @@ public function derive_keys($key) { $pubkeyhash = $publicKey->getPubKeyHash()->getHex(); $xpub = $key->toExtendedPublicKey($network); - $eth_address = $this->getEthereumAddress($publicKey); + $eth_address = $this->getEthereumAddress($publicKey); } else { throw new Exception("multisig keys not supported"); From bd3d45585bb75e1b7e8c40346b09400da489ce2a Mon Sep 17 00:00:00 2001 From: danda Date: Fri, 22 Jun 2018 18:27:34 +0800 Subject: [PATCH 5/5] add eth address example --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index ef60753..8d49229 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,20 @@ $ ./hd-wallet-derive.php -g --key=xpub6BfKpqjTwvH21wJGWEfxLppb8sU7C6FJge2kWb9315 +-----------------------------------------------------------------------------------------------------------------+------------------------------------+ ``` +## We can view ethereum addresses. + +``` +$ ./hd-wallet-derive.php --key=xpub6BfKpqjTwvH21wJGWEfxLppb8sU7C6FJge2kWb9315oP4ZVqCXG29cdUtkyu7YQhHyfA5nt63nzcNZHYmqXYHDxYo8mm1Xq1dAC7YtodwUR --cols=path,address,eth_address --numderive=3 -g + ++------+------------------------------------+--------------------------------------------+ +| path | address | eth_address | ++------+------------------------------------+--------------------------------------------+ +| m/0 | 1FZKdR3E7S1UPvqsuqStXAhZiovntFirge | 0xc7eE60fFD437cf206A4E6deFaEd020c54b63d3f5 | +| m/1 | 12UMERLGAHKe5PQPaSYX8sczr52rSAg2Mi | 0x96790F426AC663989605B806Ac8360891bD76359 | +| m/2 | 1Pyk8NLx3gaXSng7XhKoNMLfBffUsJGAjr | 0x76580a4cD31C5EC607a713C922Fd3dE278Ab49c1 | ++------+------------------------------------+--------------------------------------------+ +``` + ## We can get results in a variety of additional formats ### simple list