PBKDF2 ? Really ?
Are you sure about that ?
Yes. You said:
That is incorrect.
The keys are stored encrypted with AES-256-CBC and not SHA512.
So you can not extract a sha-512 from a wallet.
But OP is getting wallet.dat password mixed up with private key (ckey) encryption. They are using two different algorithms/concepts.
The AES-256-CBC is a cipher that is
used inside the PBKDF2 derivation, along with the SHA512 hash function. You can't just do a KDF without a hash function and a cipher to go with it. It is even referencing number of rounds and nDerivation method inside SetKeyFromPassphrase:
// This hashes the password (strKeyData, SecureString is the class used to represent a password)
// a number of times to a SHA512 hash *which is then* split in half to get an AES-256-CBC key and IV.
int CCrypter::BytesToKeySHA512AES(const std::vector& chSalt, const SecureString& strKeyData, int count, unsigned char *key,unsigned char *iv) const
~
// This is the actual KDF function. It checks for the parameters mentioned in the linked thread.
bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::vector& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod)
{
if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE)
return false;
int i = 0;
if (nDerivationMethod == 0)
i = BytesToKeySHA512AES(chSalt, strKeyData, nRounds, vchKey.data(), vchIV.data());
~snip
Notice how there's only an nDerivationMethod of 0. According to achow's comment in the thread I linked this stands for SHA-512 derivation function.
/*
* The rest of this stuff is just using the AES-256-CBC key *generated* from the PBKDF2 function
* above to encrypt uint256 stuff i.e. private keys
*/
bool CCrypter::SetKey(const CKeyingMaterial& chNewKey, const std::vector& chNewIV)
bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector &vchCiphertext) const
bool CCrypter::Decrypt(const std::vector& vchCiphertext, CKeyingMaterial& vchPlaintext) const
bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector &vchCiphertext)
bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext)
bool DecryptKey(const CKeyingMaterial& vMasterKey, const std::vector& vchCryptedSecret, const CPubKey& vchPubKey, CKey& key)
As you can see, the password has never been encrypted anywhere, that's why it makes no sense to talk about extracting the encrypted password, because there is no encrypted password, only AES keys generated from the password.
Even these are not stored in the file, only a bunch of constant values along with the salt separated by dollar sign $ to make up the bitcoin wallet hash (which I sometimes [wrongly] call PBKDF2 hash)
The password generates the encryption keys, that's also the reason why wallet.dat files have one of the slowest keys/second cracking time, versus regular AES256CBC (in the KDF this function + the hashing is repeated several hundred times!)