Bitcoin Derivation Path


The cool thing about extended keys is that they can derive children, and these child keys can derive more children, and so on. This allows you to create a tree of extended keys, with each key having its own unique derivation path from the master key.
NotationDescription
/Indicate a new branch with number of new child.
'Hardened Child means that no new child can be derived by extended public key, unless you derived from extended private key. Index range from 2147483648 to 4294967296.
without 'Normal Child is the inverse of Hardened Child. Index range from 0 to 2147483647.

Derive From Extended Private Key

<?php 
use BitWasp\Bitcoin\Bitcoin;
use BitWasp\Bitcoin\Crypto\Random\Random;
use BitWasp\Bitcoin\Key\Factory\HierarchicalKeyFactory;
use BitWasp\Bitcoin\Mnemonic\Bip39\Bip39Mnemonic;
use BitWasp\Bitcoin\Mnemonic\Bip39\Bip39SeedGenerator;
use BitWasp\Bitcoin\Mnemonic\MnemonicFactory;
use BitWasp\Buffertools\Buffer;
use BitWasp\Bitcoin\Key\Deterministic\HierarchicalKey;

include_once "../libraries/vendor/autoload.php";
include_once("html_iframe_header.php");

$result = 0;
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
	
	try {
		
		$hdFactory = new HierarchicalKeyFactory();
			
		$bip32Root = $hdFactory->fromExtended($_POST['extended_priv']);
		
		if ($_POST['relative_path']) {
			
			$key = $bip32Root->derivePath($_POST['relative_path']);
			
			$displayPubkey = $key->getPublicKey()->getHex();
			$displayPrikey = $key->getPrivateKey()->getHex();
			$displayExtendedPrikey = $key->toExtendedKey();
			$displayExtendedPubkey = $key->toExtendedPublicKey();
		}
		
		$result = 1;
	} catch (Exception $e) {
        $errmsg .= "Problem found. " . $e->getMessage();
    }
}

if ($errmsg) {
?>
	<div class="alert alert-danger">
		<strong>Error!</strong> <?php echo $errmsg?>
	</div>
<?php
}

if ($result) {
?>
	<h5>Derivation</h5>
	<div class="table-responsive">
		<table border=0 class='table'>
			<tr><td>Relative Path</td><td><?php echo $_POST['relative_path']?></td></tr>
			<tr><td>Public Key</td><td><?php echo $displayPubkey?></td></tr>
			<tr><td>Private Key</td><td><?php echo $displayPrikey?></td></tr>
			<tr><td>Bip32 Extended Private Key</td><td><?php echo $displayExtendedPrikey?></td></tr>
			<tr><td>Bip32 Extended Public Key</td><td><?php echo $displayExtendedPubkey?></td></tr>
		</table>
	</div>
<?php
}
?>
<form action='' method='post'>
	
	<div class="form-group">
		<label for="extended_priv">Bip32 Extended Private Key (Extend From):</label>
		
		<div class="input-group mb-3">
			<input class="form-control" type='text' name='extended_priv' id='extended_priv' value='<?php echo $_POST['extended_priv']?>'>
		</div>
	</div>
	
	<div class="form-group">
		<label for="relative_path">Relative Path (Extend To):</label>
		<input class="form-control" type='text' name='relative_path' id='relative_path' value='<?php echo htmlentities($_POST['relative_path'],ENT_QUOTES)?>'>
		* Do not start with /
	</div>
	
	<input type='submit' class="btn btn-success btn-block"/>
</form>
<?php 
include_once("html_iframe_footer.php");		

Address Derived From Xpub

<?php 
use BitWasp\Bitcoin\Bitcoin;

use BitWasp\Bitcoin\Key\Factory\HierarchicalKeyFactory;
use BitWasp\Bitcoin\Mnemonic\Bip39\Bip39Mnemonic;
use BitWasp\Bitcoin\Mnemonic\Bip39\Bip39SeedGenerator;
use BitWasp\Bitcoin\Mnemonic\MnemonicFactory;
use BitWasp\Buffertools\Buffer;
use BitWasp\Bitcoin\Key\Deterministic\HierarchicalKey;
use BitWasp\Bitcoin\Network\NetworkFactory;
use BitWasp\Bitcoin\Address\PayToPubKeyHashAddress;
use \BitWasp\Bitcoin\Crypto\EcAdapter\Impl\PhpEcc\Key\PublicKey;
use kornrunner\Keccak;

include_once "../libraries/vendor/autoload.php";
include_once("html_iframe_header.php");

function toChecksumAddress($address) 
{
	
	$address = strtolower(str_replace('0x', '', $address));
	$hash = Keccak::hash(strtolower($address), 256);
	$checksumAddress = '0x';
	
	for($i=0;$i<strlen($address);$i++) {
		
		if (intval($hash{$i}, 16) > 7) {
			$checksumAddress .= strtoupper($address{$i});
		} else {
			$checksumAddress .= $address{$i};
		}
	}
	
	return $checksumAddress;
	
}

$details = [];
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
	
	try {
		$networkClass = ($_POST['network'] == "ethereum" ? "bitcoin": $_POST['network']);
		
        Bitcoin::setNetwork(NetworkFactory::$networkClass());
        $network        = Bitcoin::getNetwork();
		$hdFactory = new HierarchicalKeyFactory();
		
		$key = $hdFactory->fromExtended($_POST['xpub'], $network);
		
		$indexes = range((int)$_POST['from_index'],(int)$_POST['to_index']);
		$ecAdapter = Bitcoin::getEcAdapter();
		
		foreach($indexes as $index) {
			$relativePath = strlen($_POST['relative_path']) >0 ? $_POST['relative_path'] . "/"  : "";
			
			$childKey = $key->derivePath( $relativePath . $index);
			
			$publicKey = $childKey->getPublicKey();
			//decompress public key
			$dePublicKey = new PublicKey($ecAdapter,$publicKey->getPoint(),false);
			
			if ($_POST['network'] == 'ethereum') {
				
				$madeUpEthAddress = substr($dePublicKey->getHex(), 2);
				
				$hash = Keccak::hash(hex2bin($madeUpEthAddress), 256);
				$ethAddress = toChecksumAddress('0x' . substr($hash, -40));
				$details[$relativePath . $index] = ["decompressed_pub"=>$dePublicKey->getHex(), "compressed_pub"=>$publicKey->getHex(),"address"=>$ethAddress];
			} else {
				$pubKeyHash = $childKey->getPublicKey()->getPubKeyHash();
				$details[$relativePath . $index] = ["decompressed_pub"=>$dePublicKey->getHex(), "compressed_pub"=>$publicKey->getHex(),"address"=>(new PayToPubKeyHashAddress($pubKeyHash))->getAddress()];
			}
		}
		
	} catch (Exception $e) {
        $errmsg .= "Problem found. " . $e->getMessage();
    }
}

if ($errmsg) {
?>
	<div class="alert alert-danger">
		<strong>Error!</strong> <?php echo $errmsg?>
	</div>
<?php
}

if ($details) {
?>
	<h5>Address Array</h5>
	<div class="table-responsive">
		<table class="table table-bordered">
			<tr><th>Full Relative Path</th><th>Address</th><th>Public Key</th></tr>
		<?php 
		foreach($details as $index => $detail) {
		?>
			<tr><td><?php echo $index?></td><td><?php echo $detail['address']?></td><td><p>Compressed:<br/><?php echo $detail['compressed_pub']?></p><p>Decompressed:<br/><?php echo $detail['decompressed_pub']?></p></td></tr>
		<?php
		}
		?>
		</table>
	</div>
<?php
}
?>
<form action='' method='post'>
	<div class="form-group">
        <label for="network">Network *:</label>
        <select id="network" name="network" class="form-control" >
            <?php
            $networks = get_class_methods(new NetworkFactory());
            foreach($networks as $network) {
                echo "<option value='{$network}'".($network == $_POST['network'] ? " selected": "").">{$network}</option>";
            }
			
			$network = "ethereum";
			echo "<option value='{$network}'".($network == $_POST['network'] ? " selected": "").">{$network}</option>";
            ?>
        </select>
    </div>
	
	<div class="form-group">
		<label for="xpub">Bip32 Extended Public Key (Xpub) *:</label>
		
		<div class="input-group mb-3">
			<input class="form-control" type='text' name='xpub' id='xpub' value='<?php echo $_POST['xpub']?>'>
		</div>
	</div>
	
	<div class="form-group">
        <label for="from_index">From Index *:</label>
        <input class="form-control" type='text' name='from_index' id='from_index' value='<?php echo $_POST['from_index']?>'>
        
    </div>
	
	<div class="form-group">
        <label for="to_index">To Index *:</label>
        <input class="form-control" type='text' name='to_index' id='to_index' value='<?php echo $_POST['to_index']?>'>
    </div>
	
	<div class="form-group">
		<label for="relative_path">Relative Path :</label>
		<input class="form-control" type='text' name='relative_path' id='relative_path' value='<?php echo htmlentities($_POST['relative_path'],ENT_QUOTES)?>'>
		* Do not start with /, this field is optional.
	</div>
	
	
	<input type='submit' class="btn btn-success btn-block"/>
</form>
<?php 
include_once("html_iframe_footer.php");		








Tutorials
About Us
Contents have been open source in GITHUB. Please give me a ⭐ if you found this helpful :)
Community
Problem? Raise me a new issue.
Support Us
Buy me a coffee. so i can spend more nights for this :)

BTCSCHOOLS would like to present you with more pratical but little theory throughout our tutorials. Pages' content are constantly keep reviewed to avoid mistakes, but we cannot warrant correctness of all contents. While using this site, you agree to accept our terms of use, cookie & privacy policy. Copyright 2019 by BTCSCHOOLS. All Rights Reserved.