private function generateNewAddress(int $lastIndex) : array
 {
     $lastIndex++;
     $master = $this->masterKey;
     $address = BIP32::build_address($master, "m/44'/0'/0'/0/{$lastIndex}")[0];
     return [$address, $lastIndex];
 }
示例#2
0
 /**
  * Method uses XPUB to generate next deterministic address.
  *
  * @param string $xpub  Master public key (XPUB)
  * @param int    $index Index of the deterministic address
  *
  * @return string Generated address for specified index
  */
 public static function generateAddress($xpub, $index = 0)
 {
     if (!class_exists('BitWasp\\BitcoinLib\\BIP32')) {
         // if class BIP32 is not available, trigger an error
         trigger_error("Library BitWasp/bitcoin-lib-php is required to generate deterministic address", E_USER_ERROR);
     }
     Console::debug("Generating address for XPUB '%s' index %d", $xpub, $index);
     $address = BIP32::build_address($xpub, sprintf('0/%d', $index))[0];
     Console::debug("Generated address (index %d): '%s'", $index, $address);
     return $address;
 }
示例#3
0
 public function handle_mpk_request($bip32_array)
 {
     $this->CI->load->model('bip32_model');
     if (!isset($bip32_array['auth_id'])) {
         // Need this in order to delete it later, as the action is a write action.
         return 'Unable to proceed, no auth ID';
     }
     $check_key_valid = \BitWasp\BitcoinLib\BIP32::import($bip32_array['key']) !== FALSE;
     $insert = array('user_id' => $bip32_array['user_id'], 'key' => $bip32_array['key'], 'provider' => 'Onchain');
     return $check_key_valid ? ($this->CI->bip32_model->add($insert) == TRUE and $this->CI->onchain_model->clear_auth($bip32_array['auth_id'] == TRUE)) ? 'Key set up successfully!' : 'Error setting key' : 'Invalid BIP32 key';
 }
示例#4
0
 public function testChildKeyDerivationOne()
 {
     $test_vectors = [0 => ['master' => '000102030405060708090a0b0c0d0e0f', 'ckd' => [0 => ['child' => "0'", 'priv' => 'xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7', 'pub' => 'xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw'], 1 => ['child' => '1', 'priv' => 'xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs', 'pub' => 'xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ'], 2 => ['child' => "2'", 'priv' => 'xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM', 'pub' => 'xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5'], 3 => ['child' => '2', 'priv' => 'xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334', 'pub' => 'xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV'], 4 => ['child' => '1000000000', 'priv' => 'xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76', 'pub' => 'xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy']]], 1 => ['master' => 'fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542', 'ckd' => [0 => ['child' => "0", 'priv' => 'xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt', 'pub' => 'xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH'], 1 => ['child' => "2147483647'", 'priv' => 'xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9', 'pub' => 'xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a'], 2 => ['child' => "1", 'priv' => 'xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef', 'pub' => 'xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon'], 3 => ['child' => "2147483646'", 'priv' => 'xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc', 'pub' => 'xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL'], 4 => ['child' => '2', 'priv' => 'xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j', 'pub' => 'xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt']]]];
     foreach ($test_vectors as $test => $vector) {
         $master = BIP32::master_key($vector['master']);
         $key = $master;
         foreach ($vector['ckd'] as $test_array) {
             $this->setup();
             $key = $this->bip32->build_key($key, $test_array['child']);
             $this->assertEquals($key[0], $test_array['priv']);
             $pub = $this->bip32->extended_private_to_public($key);
             $this->assertEquals($pub[0], $test_array['pub']);
             $this->tearDown();
         }
     }
 }
示例#5
0
 public function recurse_until_unique_bip32_key($bip32_key_row)
 {
     $this->load->model('used_pubkeys_model');
     // Loop until a unique key is found.
     $valid = FALSE;
     while ($valid == FALSE) {
         $new_key = \BitWasp\BitcoinLib\BIP32::build_key($bip32_key_row['key'], $bip32_key_row['key_index']);
         $public_key = \BitWasp\BitcoinLib\BIP32::extract_public_key($new_key);
         // Check that when previously used keys are removed, result is still one (never used before)
         if (count($this->used_pubkeys_model->remove_used_keys(array($public_key))) == 1) {
             $valid = TRUE;
         } else {
             $bip32_key_row['key_index']++;
         }
     }
     return array('parent_extended_public_key' => $bip32_key_row['key'], 'provider' => isset($bip32_key_row['provider']) ? $bip32_key_row['provider'] : 'Manual', 'extended_public_key' => $new_key[0], 'public_key' => $public_key, 'key_index' => $bip32_key_row['key_index']);
 }
 public function validate_depth_bip32($str)
 {
     $decode = \BitWasp\BitcoinLib\BIP32::import($str);
     return $decode['depth'] == '1';
 }
示例#7
0
<?php

use BitWasp\BitcoinLib\BIP32;
require_once __DIR__ . '/../vendor/autoload.php';
$master = BIP32::master_key(bin2hex(mcrypt_create_iv(64, \MCRYPT_DEV_URANDOM)));
// Load a 128 bit key, and convert this to extended key format.
//$master = BIP32::master_key('41414141414141414141414141414141414141');
$def = "0'/0";
echo "\nMaster key\n m           : {$master[0]} \n";
$key = BIP32::build_key($master, $def);
// Define what derivation you wish to calculate.
// Display private extended key and the address that's derived from it.
echo "Generated key: note that all depth=1 keys are hardened. \n {$key[1]}        : {$key[0]}\n";
echo "             : " . BIP32::key_to_address($key[0]) . "\n";
// Convert the extended private key to the public key, and display the
// address that's derived from it.
$pub = BIP32::extended_private_to_public($key);
echo "Public key\n {$pub[1]}        : {$pub[0]}\n";
echo "             : " . BIP32::key_to_address($pub[0]) . "\n";
//$nextpub = BIP32::build_key($pub, '0');
//echo  "Child key\n";
//echo " {$nextpub[1]}      : {$nextpub[0]}\n";
 /**
  * get the plain public key for the current BIP32 key
  *
  * @return string
  */
 public function publicKey()
 {
     // if this is a BIP32 Private key then we first build the public key
     //  that way it will be cached nicely
     if (!$this->path->isPublicPath()) {
         return $this->buildKey($this->path->publicPath())->publicKey();
     } else {
         if (is_null($this->publicKey)) {
             $this->publicKey = BIP32::extract_public_key($this->tuple());
         }
         return $this->publicKey;
     }
 }
 /**
  * signs a raw transaction
  *
  * @param $rawTransaction
  * @param $inputs
  * @return array
  */
 protected function signTransaction($rawTransaction, $inputs)
 {
     $wallet = [];
     $keys = [];
     $redeemScripts = [];
     foreach ($inputs as $input) {
         //create private keys for signing
         $path = BIP32Path::path($input['path'])->privatePath();
         $keys[] = $this->primaryPrivateKey->buildKey($path);
         $keys[] = $this->backupPrivateKey->buildKey($path->unhardenedPath());
         $redeemScripts[] = $input['redeemScript'];
     }
     //add the keys and redeem scripts to a wallet to sign the transaction with
     BIP32::bip32_keys_to_wallet($wallet, array_map(function (BIP32Key $key) {
         return $key->tuple();
     }, $keys));
     RawTransaction::redeem_scripts_to_wallet($wallet, $redeemScripts);
     return RawTransaction::sign($wallet, $rawTransaction, json_encode($inputs));
 }
$wallet[1] = BIP32::master_key('b861e093a58718e145b9791af35fb222');
$wallet[2] = BIP32::master_key('b861e093a58718e145b9791af35fb333');
print_r($wallet);
echo "Now we will generate a m/0' extended key. These will yield a private key\n";
$user[0] = BIP32::build_key($wallet[0][0], "3'");
$user[1] = BIP32::build_key($wallet[1][0], "23'");
$user[2] = BIP32::build_key($wallet[2][0], "9'");
print_r($user);
// As the previous is a private key, we should convert to the corresponding
// public key: M/0'
echo "As the previous is a private key, we should convert it to the corresponding\n";
echo "public key: M/0' \n";
$pub[0] = BIP32::extended_private_to_public($user[0]);
$pub[1] = BIP32::extended_private_to_public($user[1]);
$pub[2] = BIP32::extended_private_to_public($user[2]);
print_r($pub);
echo "This is the key you will ask your users for. For repeated transactions\n";
echo "BIP32 allows you to deterministically generate public keys, meaning less\n";
echo "effort for everyone involved\n\n";
echo "Now we can generate many multisignature addresses from what we have here: \n";
for ($i = 0; $i < 3; $i++) {
    $bip32key[0] = BIP32::build_key($pub[0], "0/{$i}");
    $bip32key[1] = BIP32::build_key($pub[1], "0/{$i}");
    $bip32key[2] = BIP32::build_key($pub[2], "0/{$i}");
    print_r($bip32key);
    $pubkey[0] = BIP32::extract_public_key($bip32key[0]);
    $pubkey[1] = BIP32::extract_public_key($bip32key[1]);
    $pubkey[2] = BIP32::extract_public_key($bip32key[2]);
    print_r($pubkey);
    print_r(RawTransaction::create_multisig(2, $pubkey));
}
echo "test two\n";
$master = BIP32::master_key('fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542');
echo "Chain m\n";
echo "    ext priv:\n    " . $master[0] . "\n";
$public = BIP32::extended_private_to_public($master);
echo "    ext pub:\n    " . $public[0] . "\n";
echo "Chain m/0\n";
$key = BIP32::build_key($master, '0');
echo "    ext priv:\n    " . $key[0] . "\n";
$public = BIP32::extended_private_to_public($key);
echo "    ext pub: \n    " . $public[0] . "\n";
echo "Chain m/0/2147483647'\n";
$key = BIP32::build_key($key, "2147483647'");
echo "    ext priv:\n    " . $key[0] . "\n";
$public = BIP32::extended_private_to_public($key);
echo "    ext pub: \n    " . $public[0] . "\n";
echo "Chain m/0/2147483647'/1\n";
$key = BIP32::build_key($key, "1");
echo "    ext priv:\n    " . $key[0] . "\n";
$public = BIP32::extended_private_to_public($key);
echo "    ext pub: \n    " . $public[0] . "\n";
echo "Chain m/0/2147483647'/1/2147483646'\n";
$key = BIP32::build_key($key, "2147483646'");
echo "    ext priv:\n    " . $key[0] . "\n";
$public = BIP32::extended_private_to_public($key);
echo "    ext pub: \n    " . $public[0] . "\n";
echo "Chain m/0/2147483647'/1/2147483646'/2\n";
$key = BIP32::build_key($key, "2");
echo "    ext priv:\n    " . $key[0] . "\n";
$public = BIP32::extended_private_to_public($key);
echo "    ext pub: \n    " . $public[0] . "\n";
 public function testGenerate()
 {
     for ($i = 0; $i < 100; $i++) {
         $entropy = BIP39::generateEntropy(128);
         $this->assertTrue(!!$entropy);
         $mnemonic = BIP39::entropyToMnemonic($entropy);
         $this->assertTrue(!!$entropy);
         $entropy2 = BIP39::mnemonicToEntropy($mnemonic);
         $this->assertTrue(!!$entropy2);
         $this->assertEquals($entropy, $entropy2);
         $bip32 = BIP32::master_key(BIP39::mnemonicToSeedHex($mnemonic, 'PASSWORD'));
         $this->assertTrue(!!$bip32);
     }
     for ($i = 0; $i < 100; $i++) {
         $entropy = BIP39::generateEntropy(256);
         $this->assertTrue(!!$entropy);
         $mnemonic = BIP39::entropyToMnemonic($entropy);
         $this->assertTrue(!!$entropy);
         $entropy2 = BIP39::mnemonicToEntropy($mnemonic);
         $this->assertTrue(!!$entropy2);
         $this->assertEquals($entropy, $entropy2);
         $bip32 = BIP32::master_key(BIP39::mnemonicToSeedHex($mnemonic, 'PASSWORD'));
         $this->assertTrue(!!$bip32);
     }
     for ($i = 0; $i < 100; $i++) {
         $entropy = BIP39::generateEntropy(512);
         $this->assertTrue(!!$entropy);
         $mnemonic = BIP39::entropyToMnemonic($entropy);
         $this->assertTrue(!!$entropy);
         $entropy2 = BIP39::mnemonicToEntropy($mnemonic);
         $this->assertTrue(!!$entropy2);
         $this->assertEquals($entropy, $entropy2);
         $bip32 = BIP32::master_key(BIP39::mnemonicToSeedHex($mnemonic, 'PASSWORD'));
         $this->assertTrue(!!$bip32);
     }
 }
示例#13
0
 /**
  * BIP32 Private Keys To Wallet
  *
  * This function accepts $wallet - a reference to an array containing
  * wallet info, indexed by hash160 of expected address.
  * It will attempt to add each key to this wallet, as well as all the
  * details that could be needed later on: public key, uncompressed key,
  * address, an indicator for address compression. Type is always set
  * to pubkeyhash for private key entries in the wallet.
  *
  * @param       $wallet
  * @param array $keys
  * @param null  $magic_byte
  */
 public static function bip32_keys_to_wallet(&$wallet, array $keys, $magic_byte = null)
 {
     $magic_byte = BitcoinLib::magicByte($magic_byte);
     RawTransaction::private_keys_to_wallet($wallet, array_map(function ($key) {
         return BIP32::import($key[0]);
     }, $keys), $magic_byte);
 }
echo "             : " . BIP32::key_to_address($pub[0]) . "\n";
/////////////////////////////
// We're gonna spent the first txout from this tx:
//  https://www.blocktrail.com/BTC/tx/4a2231e13182cdb64fa2f9aae38fca46549891e9dc15e8aaf484d82fc6e0a1d8
// Set up inputs here
$inputs = array(array('txid' => '4a2231e13182cdb64fa2f9aae38fca46549891e9dc15e8aaf484d82fc6e0a1d8', 'vout' => 0));
// Set up outputs here
$outputs = array('1KuE17Fbcdsn3Ns5T9Wzi1epurRnKC9qVr' => BitcoinLib::toSatoshi(0.0004));
////////////////////////////
// Parameters for signing.
// Create JSON inputs parameter
// - These can come from bitcoind, or just knowledge of the txid/vout/scriptPubKey,
//   and redeemScript if needed.
$json_inputs = json_encode(array(array('txid' => '4a2231e13182cdb64fa2f9aae38fca46549891e9dc15e8aaf484d82fc6e0a1d8', 'vout' => 0, 'scriptPubKey' => '76a914' . 'bf012bde5bd12eb7f9a66de5697b241b65a9a3c9' . '88ac')));
// build wallet from private key(s)
$wallet = array();
BIP32::bip32_keys_to_wallet($wallet, array($key), '00');
// Create raw transaction
$raw_transaction = RawTransaction::create($inputs, $outputs);
// Sign the transaction
$signed = RawTransaction::sign($wallet, $raw_transaction, $json_inputs);
print_r($signed);
echo "\n";
// Decode and print the TX
// print_r(RawTransaction::decode($sign['hex']));
// To broadcast the transaction onto the network
//  - grab the $signed['hex']
//  - `bitcoind sendrawtransaction <singed HEX>`
//    or use an API that supports sendraw
// This transaction was broadcasted and confirmed here:
//  https://www.blocktrail.com/BTC/tx/e04c14270b2a9fcff548bc0bdd16b22ec6c2903ea6aaf9f7656b81f1c4c6153b
示例#15
0
 /**
  * create checksum to verify ownership of the master primary key
  *
  * @return string[]     [address, signature]
  */
 protected function createChecksumVerificationSignature()
 {
     $import = BIP32::import($this->primaryPrivateKey->key());
     $public = $this->primaryPrivateKey->publicKey();
     $address = BitcoinLib::public_key_to_address($public, $import['version']);
     return [$address, BitcoinLib::signMessage($address, $import)];
 }
示例#16
0
 public function testNewBlankWithoutMnemonicsWallet()
 {
     $client = $this->setupBlocktrailSDK();
     $identifier = $this->getRandomTestIdentifier();
     $primaryPrivateKey = BIP32::master_key(BIP39::mnemonicToSeedHex(BIP39::entropyToMnemonic(BIP39::generateEntropy(512)), "password"), 'bitcoin', true);
     $backupPublicKey = BIP32::extended_private_to_public(BIP32::master_key(BIP39::mnemonicToSeedHex(BIP39::entropyToMnemonic(BIP39::generateEntropy(512)), "password"), 'bitcoin', true));
     /**
      * @var $wallet \Blocktrail\SDK\Wallet
      */
     $e = null;
     try {
         $wallet = $client->initWallet(["identifier" => $identifier]);
     } catch (ObjectNotFound $e) {
         list($wallet, $primaryMnemonic, $backupMnemonic, $blocktrailPublicKeys) = $client->createNewWallet(["identifier" => $identifier, "primary_private_key" => $primaryPrivateKey, "backup_public_key" => $backupPublicKey, "key_index" => 9999]);
     }
     $this->assertTrue(!!$e, "New wallet with ID [{$identifier}] already exists...");
     $wallet = $client->initWallet(["identifier" => $identifier, "primary_private_key" => $primaryPrivateKey]);
     $this->wallets[] = $wallet;
     // store for cleanup
     $this->assertEquals(0, $wallet->getBalance()[0]);
     $e = null;
     try {
         $wallet->pay(["2N6Fg6T74Fcv1JQ8FkPJMs8mYmbm9kitTxy" => BlocktrailSDK::toSatoshi(0.001)]);
     } catch (\Exception $e) {
     }
     $this->assertTrue(!!$e, "Wallet without balance is able to pay...");
 }
示例#17
0
<?php

use BitWasp\BitcoinLib\BIP32;
require_once __DIR__ . '/../vendor/autoload.php';
// Load a 128 bit key, and convert this to extended key format.
$master = BIP32::master_key('41414141414141414141414141414141414141');
$def = "0'";
echo "\nMaster key\n m           : {$master[0]} \n";
// Define what derivation you wish to calculate.
$key = BIP32::build_key($master, $def);
// Build the extended key
// Display private extended key and the address that's derived from it.
echo "Generated key: note that all depth=1 keys are hardened. \n {$key[1]}        : {$key[0]}\n";
echo "             : " . BIP32::key_to_address($key[0]) . "\n";
// Convert the extended private key to the public key, and display the
// address that's derived from it.
$pub = BIP32::extended_private_to_public($key);
echo "Public key\n {$pub[1]}        : {$pub[0]}\n";
echo "             : " . BIP32::key_to_address($pub[0]) . "\n";
$nextpub = BIP32::build_key($pub, '0');
echo "Child key\n";
echo " {$nextpub[1]}      : {$nextpub[0]}\n";
 /**
  * create a new key;
  *  1) a BIP39 mnemonic
  *  2) a seed from that mnemonic with the password
  *  3) a private key from that seed
  *
  * @param string    $passphrase             the password to use in the BIP39 creation of the seed
  * @param string    $forceEntropy           forced entropy instead of random entropy for testing purposes
  * @return array
  */
 protected function generateNewSeed($passphrase = "", $forceEntropy = null)
 {
     // generate master seed, retry if the generated private key isn't valid (FALSE is returned)
     do {
         $mnemonic = $this->generateNewMnemonic($forceEntropy);
         $seed = BIP39::mnemonicToSeedHex($mnemonic, $passphrase);
         $key = BIP32::master_key($seed, $this->network, $this->testnet);
     } while (!$key);
     return [$mnemonic, $seed, $key];
 }
示例#19
0
<?php

use BitWasp\BitcoinLib\BIP32;
use BitWasp\BitcoinLib\BIP39\BIP39;
require_once __DIR__ . '/../vendor/autoload.php';
$password = "******";
$entropy = BIP39::generateEntropy(256);
$mnemonic = BIP39::entropyToMnemonic($entropy);
$seed = BIP39::mnemonicToSeedHex($mnemonic, $password);
unset($entropy);
// ignore, forget about this, don't use it!
var_dump($mnemonic);
// this is what you print on a piece of paper, etc
var_dump($password);
// this is secret of course
var_dump($seed);
// this is what you use to generate a key
$key = BIP32::master_key($seed);
// enjoy