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!