Question

https://en.bitcoin.it/wiki/Wallet_import_format

Trying to follow this example here to do this in PHP, but I get stuck at step 3.

I can't seem to get the same SHA256 hash.

I take the extended key from step 2 800C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D

and SHA256 it.

I should get 8147786C4D15106333BF278D71DADAF1079EF2D2440A4DDE37D747DED5403592 according to step 3 but I just get E2E4146A36E9C455CF95A4F259F162C353CD419CC3FD0E69AE36D7D1B6CD2C09

What am I doing wrong?

Was it helpful?

Solution

This is because you are hashing the literal string

"800C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D"

This is not what what needs to happen. This is a string of bytes. It's in HEX format just to make viewing it easier. In reality, this represents a binary string. That's what you need to be hashing.

hex2bin is your friend here.

<?php
$hex = '800C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D';
echo hash('sha256', hex2bin($hex));

DEMO: https://eval.in/69440

Another example:

<?php
$key = '0C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D';
$binKey = hex2bin($key);

$binKey = hex2bin(80).$binKey;

echo hash('sha256', $binKey);

DEMO: https://eval.in/69443

OTHER TIPS

Here is the working PHP-code example:

<?php

//EXAMPLE INPUT: 0C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D
//EXAMPLE OUTPUT: 5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ
//see https://en.bitcoin.it/wiki/Wallet_import_format for more info

function decodeHex($hex)
{
    $hex = strtoupper($hex);
    $chars = '0123456789ABCDEF';
    $return = '0';
    for($i = 0; $i < strlen($hex); $i++)
    {
        $current = (string)strpos($chars, $hex[$i]);
        $return = (string)bcmul($return, '16', 0);
        $return = (string)bcadd($return, $current, 0);
    }
    return $return;
}

function encodeBase58($hex)
{
    $orighex = $hex;
    $chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
    $hex = decodeHex($hex);
    $return = '';
    while(bccomp($hex, 0) == 1)
    {
        $dv = (string)bcdiv($hex, '58', 0);
        $rem = (integer)bcmod($hex, '58');
        $hex = $dv;
        $return = $return.$chars[$rem];
    }
    $return = strrev($return);

    //leading zeros
    for($i = 0; $i < strlen($orighex) && substr($orighex, $i, 2) == '00'; $i += 2)
    {
        $return = '1' . $return;
    }

    return $return;
}

if(!isset($_SERVER['argv'][1]))
{
    exit("Usage: php convert_bitcoin_private_key_to_wif_format.php private_key\n");
}

$privateKey = $_SERVER['argv'][1];

//add a 0x80 byte in front of it 
$buffer = '80' . $privateKey; 
$extendedKey = $buffer;

//perform SHA-256 hash on the extended key 
$buffer = strtoupper(hash('sha256', hex2bin($buffer)));

//perform SHA-256 hash on result of SHA-256 hash 
$buffer = strtoupper(hash('sha256', hex2bin($buffer)));

//take the first 4 bytes of the second SHA-256 hash, this is the checksum 
$checksum = substr($buffer, 0, 8);

//add the checksum at the end of the extended key
$buffer = $extendedKey . $checksum;

//convert the result from a byte string into a base58 string
$buffer = encodeBase58($buffer);

echo($buffer . "\n");

?>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top