3rdIteration / btcrecover

BTCRecover is an open source wallet password and seed recovery tool. For seed based recovery, this is primarily useful in situations where you have lost/forgotten parts of your mnemonic, or have made an error transcribing it. (So you are either seeing an empty wallet or gettign an error that your seed is invalid) For wallet password or passphrase recovery, it is primarily useful if you have a reasonable idea about what your password might be.
https://btcrecover.readthedocs.io/
GNU General Public License v2.0
580 stars 180 forks source link

Consider Using wallycore for BIP38 #243

Open sigkill opened 3 years ago

sigkill commented 3 years ago

wallycore might be faster for BIP38 brute force attempts. I reviewed the code for btcrpass.py, and notice that it is quite similar to the functions that run in the "brute_force_bip38" projets code. The difference is that project is compiled in CPP, and has no viable tokenlist feature, so even with all the speed, you're stuck due to space constraints.

wallycore - https://wally.readthedocs.io/en/release_0.7.8/crypto/ is probably faster than the present implementation - I looked at btcrpass.py for some time and found that the code is drastically similar to the source code in this other project:

This is used in CPP form in this project: https://github.com/agurodriguez/brute_force_bip38

Specifically: ` def _return_verified_password_or_false_cpu(self, passwords): # BIP38 Encrypted Private Keys l_scrypt = pylibscrypt.scrypt

    passwords = map(lambda p: normalize("NFC", p).encode("utf_8", "ignore"), passwords)
    for count, password in enumerate(passwords, 1):
        if not self.ec_multiplied:
            scrypthash = l_scrypt(password, self.salt, 1 << 14, 8, 8, 64)
            if bip38decrypt_non_ec(scrypthash, self.enc_privkey, self.has_compression_flag, self.has_lotsequence_flag, network_prefix = self.network.prefix_address):
                return password.decode("utf_8", "replace"), count
        else:
            prefactor = l_scrypt(password, self.salt, 1 << 14, 8, 8, 32)
            passpoint = prefactor_to_passpoint(prefactor, self.has_lotsequence_flag, self.enc_privkey)
            encseedb = l_scrypt(passpoint, self.enc_privkey[0:12], 1024, 1, 1, 64)

            if bip38decrypt_ec(prefactor, encseedb, self.enc_privkey, self.has_compression_flag, self.has_lotsequence_flag, network_prefix = self.network.prefix_address):
                return password.decode("utf_8", "replace"), count

    return False, count`

If it were possible to import wallycore.wally_scrypt instead of pylibscrypt.scrypt we should likely see an improvement in passwords per second.

The code that is used in the other project waits for the WALLY_OK output:

Here: https://github.com/agurodriguez/brute_force_bip38/blob/master/src/bip38.hpp and here: https://github.com/agurodriguez/brute_force_bip38/blob/master/src/main.cpp

It is so much faster than btcrecover, but limited again due to the passwordlist and no tokenlist.

sigkill commented 3 years ago

wallycore appears to not support python3.9 - am trying with 3.6 now.