Generating Bitcoin Wallet Address from Public Key with PHP
Recently, I have been working on some interesting Bitcoin projects and I ran into the issue of converting my public key to a wallet address. I was initially using bitwasp/bitcoin module to achieve this but when I moved the project to a shared host it wasn't working because it needed a PHP Library my host will not allow me install because it is shared. Below is a solution to this. It follows the algorithm stated in Bitcoin documentation on step by step way of generating wallet address from public key.
<?php
/**
* Class BitcoinUtils
* @author Akinyele Olubodun
*/
class BitcoinUtils
{
public function address_from_master_pub($public_key)
{
$step1= $this->hexStringToByteString($public_key);
$step2=hash("sha256",$step1);
$step3=hash('ripemd160', $this->hexStringToByteString($step2));
$step4="00".$step3;
$step5=hash("sha256", $this->hexStringToByteString($step4));
$step6=hash("sha256", $this->hexStringToByteString($step5));
$checksum=substr($step6,0,8);
$step8 = $step4.$checksum;
$step9 = "1".$this->bc_base58_encode($this->bc_hexdec($step8));
return $step9;
}
function hexStringToByteString($hexString){
$len=strlen($hexString);
$byteString="";
for ($i=0;$i<$len;$i=$i+2){
$charnum=hexdec(substr($hexString,$i,2));
$byteString.=chr($charnum);
}
return $byteString;
}
// BCmath version for huge numbers
function bc_arb_encode($num, $basestr) {
if( ! function_exists('bcadd') ) {
Throw new Exception('You need the BCmath extension.');
}
$base = strlen($basestr);
$rep = '';
while( true ){
if( strlen($num) < 2 ) {
if( intval($num) <= 0 ) {
break;
}
}
$rem = bcmod($num, $base);
$rep = $basestr[intval($rem)] . $rep;
$num = bcdiv(bcsub($num, $rem), $base);
}
return $rep;
}
function bc_arb_decode($num, $basestr) {
if( ! function_exists('bcadd') ) {
Throw new Exception('You need the BCmath extension.');
}
$base = strlen($basestr);
$dec = '0';
$num_arr = str_split((string)$num);
$cnt = strlen($num);
for($i=0; $i < $cnt; $i++) {
$pos = strpos($basestr, $num_arr[$i]);
if( $pos === false ) {
Throw new Exception(sprintf('Unknown character %s at offset %d', $num_arr[$i], $i));
}
$dec = bcadd(bcmul($dec, $base), $pos);
}
return $dec;
}
// base 58 alias
function bc_base58_encode($num) {
return $this->bc_arb_encode($num, '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz');
}
function bc_base58_decode($num) {
return $this->bc_arb_decode($num, '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz');
}
//hexdec with BCmath
function bc_hexdec($num) {
return $this->bc_arb_decode(strtolower($num), '0123456789abcdef');
}
function bc_dechex($num) {
return $this->bc_arb_encode($num, '0123456789abcdef');
}
}