コード例 #1
0
<?php

use BitWasp\BitcoinLib\BitcoinLib;
require_once __DIR__ . '/../vendor/autoload.php';
$magic_byte = '00';
$keypair = BitcoinLib::get_new_key_set($magic_byte);
echo "Key pair: \n";
print_r($keypair);
echo "\n";
$compress = BitcoinLib::compress_public_key($keypair['pubKey']);
echo "Compressed public key: {$compress} \n";
$decompress = BitcoinLib::decompress_public_key($compress);
echo "Decompressed key info: \n";
print_r($decompress);
echo "\n";
$address = BitcoinLib::public_key_to_address($compress, $magic_byte);
echo "decoding {$address}\n";
echo BitcoinLib::base58_decode($address);
echo "\n\n";
$sc = '5357';
$ad = BitcoinLib::public_key_to_address($sc, '05');
echo $ad . "\n";
コード例 #2
0
 public function testPublicKeyCompression()
 {
     $cnt = (getenv('BITCOINLIB_EXTENSIVE_TESTING') ?: 1) * 2;
     for ($i = 0; $i < $cnt; $i++) {
         $key = BitcoinLib::get_new_private_key();
         $public = BitcoinLib::private_key_to_public_key($key, FALSE);
         $compress = BitcoinLib::compress_public_key($public);
         $decompress = BitcoinLib::decompress_public_key($compress);
         $this->assertTrue($decompress['public_key'] == $public);
     }
 }
コード例 #3
0
 /**
  * Public Key From MPK
  *
  * This function is used to generate a public key from the supplied
  * $mpk - the master public key, and an $iteration indicating which
  * address in the sequence should be generated.
  *
  * @param    string $mpk
  * @param    int    $iteration
  * @return    string
  */
 public static function public_key_from_mpk($mpk, $iteration, $change = 0, $compressed = false)
 {
     $change = $change == 0 ? '0' : '1';
     $math = EccFactory::getAdapter();
     $gen = EccFactory::getSecgCurves($math)->generator256k1();
     // Generate the curve, and the generator point.
     // Prepare the input values, by converting the MPK to X and Y coordinates
     $x = $math->hexDec(substr($mpk, 0, 64));
     $y = $math->hexDec(substr($mpk, 64, 64));
     // Generate a scalar from the $iteration and $mpk
     $z = $math->hexDec(hash('sha256', hash('sha256', "{$iteration}:{$change}:" . pack('H*', $mpk), true)));
     // Add the Point defined by $x and $y, to the result of EC multiplication of $z by $gen
     $pt = $gen->getCurve()->getPoint($x, $y, $gen->getOrder());
     $pt = $pt->add($gen->mul($z));
     // Generate the uncompressed public key.
     $keystr = '04' . str_pad($math->decHex($pt->getX()), 64, '0', STR_PAD_LEFT) . str_pad($math->decHex($pt->getY()), 64, '0', STR_PAD_LEFT);
     return $compressed == true ? BitcoinLib::compress_public_key($keystr) : $keystr;
 }
コード例 #4
0
 /**
  * CKD
  *
  * This recursive function accepts $master, a parent extended key,
  * and an array of address bytes (the $address_definition tuple). It
  * pop's the next value from the $address_definition tuple and
  * generates the desired key. If the $address_definition tuple is
  * empty, then it returns the key. If not, then it calls itself again
  * with the new key and the tuple with the remaining key indexes to
  * generate, but will terminate with an array containing the desired
  * key at index 0, and it's human readable definition in the second.
  *
  * @param    string $master
  * @param    array  $address_definition
  * @param    array  $generated (internal, should never be set in your code)
  * @return    array
  */
 public static function CKD($master, $address_definition, $generated = array())
 {
     $previous = self::import($master);
     if ($previous['type'] == 'private') {
         $private_key = $previous['key'];
         $public_key = null;
     } else {
         $private_key = null;
         $public_key = $previous['key'];
     }
     $i = array_pop($address_definition);
     $is_prime = self::check_is_prime_hex($i);
     if ($is_prime == 1) {
         if ($previous['type'] == 'public') {
             throw new \InvalidArgumentException("Can't derive private key from public key");
         }
         $data = '00' . $private_key . $i;
     } else {
         $public_key = $public_key ?: BitcoinLib::private_key_to_public_key($private_key, true);
         $data = $public_key . $i;
     }
     /*
      * optimization;
      *  if this isn't the last derivation then the fingerprint is irrelevant so we can just spoof it!
      *  that way we don't need the public key for the fingerprint
      */
     if (empty($address_definition)) {
         $public_key = $public_key ?: BitcoinLib::private_key_to_public_key($private_key, true);
         $fingerprint = substr(hash('ripemd160', hash('sha256', pack("H*", $public_key), true)), 0, 8);
     } else {
         $fingerprint = "FFFFFFFF";
     }
     $I = hash_hmac('sha512', pack("H*", $data), pack("H*", $previous['chain_code']));
     $I_l = substr($I, 0, 64);
     $I_r = substr($I, 64, 64);
     if (self::check_valid_hmac_key($I_l) == false) {
         // Check the key is in a valid range.
         // calculate the next i in the sequence, and start over with that.
         $new_i = self::calc_address_bytes(self::get_address_number($i) + 1, $is_prime);
         array_push($address_definition, $new_i);
         return self::CKD($master, $address_definition, $generated);
     }
     // Keep a record of the address being built. Done after error
     // checking so only valid keys get to this point.
     if (count($generated) == 0 && $previous['depth'] == 0) {
         array_push($generated, $previous['type'] == 'private' ? 'm' : 'M');
     }
     array_push($generated, self::get_address_number($i, $is_prime) . ($is_prime == 1 ? "'" : null));
     $math = EccFactory::getAdapter();
     $g = EccFactory::getSecgCurves($math)->generator256k1();
     $n = $g->getOrder();
     $Il_dec = $math->hexDec($I_l);
     if ($previous['type'] == 'private') {
         $private_key_dec = $math->hexDec($private_key);
         $key_dec = $math->mod($math->add($Il_dec, $private_key_dec), $n);
         $key = str_pad(BitcoinLib::hex_encode($key_dec), 64, '0', STR_PAD_LEFT);
     } else {
         if ($previous['type'] == 'public') {
             // newPoint + parentPubkeyPoint
             $decompressed = BitcoinLib::decompress_public_key($public_key);
             // Can return false. Throw exception?
             $new_point = $g->mul($Il_dec)->add($decompressed['point']);
             // Prepare offset, by multiplying Il by g, and adding this to the previous public key point.
             // Create a new point by adding the two.
             $new_x = str_pad(BitcoinLib::hex_encode($new_point->getX()), 64, '0', STR_PAD_LEFT);
             $new_y = str_pad(BitcoinLib::hex_encode($new_point->getY()), 64, '0', STR_PAD_LEFT);
             $key = BitcoinLib::compress_public_key('04' . $new_x . $new_y);
         } else {
             throw new \InvalidArgumentException("Unknown previous type in CKD");
         }
     }
     $data = array('network' => $previous['network'], 'testnet' => $previous['testnet'], 'magic_bytes' => $previous['magic_bytes'], 'type' => $previous['type'], 'depth' => $previous['depth'] + 1, 'fingerprint' => $fingerprint, 'i' => $i, 'address_number' => self::get_address_number($i), 'chain_code' => $I_r, 'key' => $key);
     return count($address_definition) > 0 ? self::CKD(self::encode($data), $address_definition, $generated) : array(self::encode($data), implode('/', $generated));
 }