简体   繁体   中英

Check Bitcoin wallet.dat passphrase hash in php

I want to match a passphrase against the hash generated with bitcoin2john.py from a specific Bitcoin wallet.dat file.

So first I have created a wallet.dat with the Passphrase "bit".

bitcoin2john.py generates this output for this wallet.dat file: $bitcoin$64$12c098515dc4f4140786e352f05d3065f17a2ca8f15c5f1c93923dc7146380c6$16$146b99a74fa7b536$135174$2$00$2$00

It is possible to crack that hash with hashcat. Haschcat returns the correct passphrase for it: $bitcoin$64$12c098515dc4f4140786e352f05d3065f17a2ca8f15c5f1c93923dc7146380c6$16$146b99a74fa7b536$135174$2$00$2$00:bit

Now I want to do that in PHP (and have been failing for days):

<?php

  $testPassphrase = 'bit';

  /*
   * Hash from wallet.dat with passphrase: "bit"
   * (Could be cracked by hashcat)
   */
  $passHash = '$bitcoin$64$12c098515dc4f4140786e352f05d3065f17a2ca8f15c5f1c93923dc7146380c6$16$146b99a74fa7b536$135174$2$00$2$00';
  
  /*
   * Remove hash identifier (not needed)
   */
  $passHash = str_replace('$bitcoin$', '', $passHash);
  
  /*
   * Split hash into pieces
   * ([0] = ??, [1] = passphrase hash, [2] = salt len, [3] = salt, [4] = iteration count, [5] = salt position, [6] = ??, [7] == ??, [8] == ??)
   */
  $passHashArray = explode('$', $passHash);
  
  /*
   * Combine passphrase and salt
   */
  $passToHash = $testPassphrase.$passHashArray[3];
   
   /*
    * Hash $passToHash $passHasArray[4] times with SHA512
    */
   for($i = 0; $i < $passHashArray[4]; $i++){
     $passToHash = hash('SHA512', $passToHash, true);
   }
   
   /*
    * Get Key and Iv from $passToHash for final encryption
    */
   $key = substr($passToHash, 0, 32);
   $iv = substr($passToHash, 32, 16);
   
   /*
    * final passphrase encryption
    */
   if(in_array('aes-256-cbc', openssl_get_cipher_methods())){
     $testPassphrase = openssl_encrypt($testPassphrase, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
   }

   /*
    * show result (should be: $passHashArray[1] = "12c098515dc4f4140786e352f05d3065f17a2ca8f15c5f1c93923dc7146380c6")
    */
   echo bin2hex($testPassphrase);

?>

I went through the Bitcoin Core code to see how it's done.

In wallet.ccp ( https://github.com/bitcoin/bitcoin/blob/2556a973ed5839c81ad23cc4d3f187f3a777483c/src/wallet/wallet.cpp ) in line 387 the function ChangeWalletPassphrase shows the steps. And in crypter.ccp ( https://github.com/bitcoin/bitcoin/blob/c7ad94428ab6f54661d7a5441e1fdd0ebf034903/src/wallet/crypter.cpp ) in line 13 and 39 the functions BytesToKeySHA512AES and SetKeyFromPassphrase are used.

This is what my PHP samle code does until "final passphrase encryption".

As far as I have found out through Internet research, the key and iv generated with this are then used to encrypt the passphrase with AES-256-CBC. You can also find this in the Bitcoin Core code. But there it looks as if not the passphrase but the MasterKey (_vMasterKey) is encrypted. But I don't have the MasterKey and so Hashcat (from my test scenario) doesn't have it. However, if I encrypt the passphrase, I cannot generate the correct hash.

After days of trial and error with my code, I'm now looking for help here. Thanks in advance for your help!

Here we go!

<?php

  $testPassphrase = 'bit';

  /*
   * Hash from wallet.dat with passphrase: "bit"
   * (Could be cracked by hashcat)
   */
  $passHash = '$bitcoin$64$12c098515dc4f4140786e352f05d3065f17a2ca8f15c5f1c93923dc7146380c6$16$146b99a74fa7b536$135174$2$00$2$00';
  
  /*
   * Remove hash identifier (not needed)
   */
  $passHash = str_replace('$bitcoin$', '', $passHash);
  
  /*
   * Split hash into pieces
   * ([0] = ??, [1] = master key, [2] = salt len, [3] = salt, [4] = iteration count, [5] = salt position, [6] = ??, [7] == ??, [8] == ??)
   */
  $passHashArray = explode('$', $passHash);
  
  /*
   * Combine passphrase and salt
   */
  $passToHash = $testPassphrase.hex2bin($passHashArray[3]);
   
   /*
    * Hash $passToHash $passHasArray[4] times with SHA512
    */
   for($i = 0; $i < $passHashArray[4]; $i++){
     $passToHash = hash('SHA512', $passToHash, true);
   }
   
   /*
    * Get Key and Iv from $passToHash for final encryption
    */
   $key = substr($passToHash, 0, 32);
   $iv = substr($passToHash, 32, 16);
   
   /*
    * final passphrase encryption
    */
   if(in_array('aes-256-cbc', openssl_get_cipher_methods())){
     if(openssl_decrypt(hex2bin($passHashArray[1]), 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv)){
       echo 'password correct';
     }else{
       echo 'decrypt failed';
     }
   }

?>

I tried user14895403 ' s code block but its not working. for this hash: $bitcoin$64$f6c27ed702fab41a526a1c81f4424142b5a066ff43a716d92ab53e7f5e6d44ab$16$b9f7918001779c5b$21815$2$00$2$00 it found a lot of correct passwords passlist: arbitral arteries auricula borecole cabretta catechin cribwork denudate drumbeat girlhood glabrate granddad imbecile indecent lyrebird melamine motherly pansophy riddance

But in Bitcoin Core said passphrase is incorrect for all. Why??

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM