Guessing not many people would test this, I wanted to do it since I read this post. Finally I did it today.
Deleted wallets recovery (encrypted+unencrypted wallet, on Linux+Windows)Pywallet will go through these steps:
1. read every byte on the disk to look for keys (sloooooooooow, ~600Mo/min)
2. create a partial file (in outputdir) so that if you forgot a passphrase but remember it later you don't have to go through step 1 again
3. test all the passphrases for the most possible (encrypted private key / encryption parameters) pairs
4. if there are some private keys still not decrypted, YOU chose whether or not you want to test all passphrase with all encryption parameters with all undecrypted private keys
Note that recov_size must be higher than the size of recov_device and that recov_outputdir must exist
Usage examples for Linux and Windows:
python pywallet_2.1.0b13.py --recover --recov_device /dev/sda --recov_size 30Gio --recov_outputdir /home/jackjack
python pywallet_2.1.0b13.py --recover --recov_device c: --recov_size 30Gio --recov_outputdir c:\recoveredwalletsfolder
So let's set up a filesystem:
# dd if=/dev/zero of=/tmp/fs bs=1M count=20
# mkfs.ext3 /tmp/fs
# mount -o loop /tmp/fs /mnt
# chown btc:btc /mnt
Fill it with a bunch of small files, make some room for the wallet, finally copy the wallet inside. This is to increase the chances of it being fragmented:
$ cp -a $(find /usr/bin -size -30k) /mnt/
cp: writing `/mnt/xwd': No space left on device
[...]
$ rm -f /mnt/{a,c,e,s}*
$ df /mnt/
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop1 19827 14487 4316 78% /mnt
$ cp .bitcoin/wallet.dat /mnt/
$ df /mnt
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/loop1 19827 17894 909 96% /mnt
Using debugfs I check that in fact the wallet is scattered over a bunch of separated blocks. 30 lines of output in my terminal only to enumerate the blocks
. Well now the fun begins!
$ cd pywallet
$ grep ^pywversion pywallet.py
pywversion="2.1.4"
$ mkdir /home/btc/enc/pywallet-recov
$ python pywallet.py --recover --recov_device /mnt/fs --recov_size 20Mio --recov_outputdir /home/btc/enc/pywallet-recov
Enter the passphrase for the wallet that will contain all the recovered keys: wow the password is displayed as I type!
Enter the possible passphrases used in your deleted wallets.
Don't forget that more passphrases = more time to test the possibilities.
Write one passphrase per line and end with an empty line.
Possible passphrase: this is displayed too
Possible passphrase:
Starting recovery.
Read 0.0 Go in 0.0 minutes
Found 1 possible wallets
Found 355 possible encrypted keys
Found 0 possible unencrypted keys
Possible wallet #1
with passphrase #1 ...................................
Private keys not decrypted: 4
Trying all the remaining possibilities (4) might take up to 0 minutes.
Do you want to test them? (y/n): y
Private keys not decrypted: 4
Try another password, check the size of your partition or seek help
The wallet is encrypted and the passphrase is correct
Importing:
Key 1/248 imported:
Address (Bitcoin): 1HvPpmKxmjs…
Privkey (Bitcoin): 5JG5smj…
[…]
The new wallet /home/btc/enc/pywallet-recov/recovered_wallet_1379174268.dat contains the 248 recovered keys
Seems that some keys couldn't be recovered. Maybe they were fragmented but in this case, it's remarkable that only 4 keys were affected.
$ cd
$ cp enc/pywallet-recov/recovered_wallet_1379174268.dat .bitcoin/wallet.dat
$ nice bitcoind &
$ bitcoind getbalance
0.00000000
Uh oh, this wasn't expected… or maybe was it? My original wallet.dat is 3 Mb while the recovered one is around 100 Kb.
$ bitcoind stop
$ nice bitcoind -rescan &
$ bitcoind getbalance
0.00000000
The resulting wallet.dat is still 100 Kb. Currently 5 of my keys have some balance so if only 4 were lost I should have at least something, 0.15 BTC in the worst case.
Later I'll do an intersection on the sets keys-in-my-good-wallet versus keys-in-the-recovered-wallet and will report back, but for now I'm done. Here are a couple of suggestions:
- Passwords are displayed as I type. This shouldn't happen!
- The output says "Found 355 possible encrypted keys". What's up with the 355(total) - 248(recovered) - 4(lost) = 103 missing ones?
- The output contains private keys. I'd prefer to have them (partially) censored.
- pywallet doesn't create the recov_outputdir if it doesn't exist. It should create it, maybe giving a choice to the user.