How hard would it be for jackjack or someone to create a standalone tool to decrypt private keys, if the correct hex strings and passphrase were inputted? Not that I'm implying he should, as he seems to be a very busy person. But If you can search out the required info with a hex editor, it would be a very flexible tool for fragmented wallet files.
Probably not very difficult... because it didn't take me too long to bang this out:
https://keybase.pub/hcp/python/core_decrypter.pyIt's pretty rough... but basically, if you can feed it an "encrypted master key" (or decrypted master key), "encrypted private key" and matching "public key"... it will prompt for wallet passphrase and then attempt to decrypt the master key... then use that to decrypt the private key before outputting the Address+WIF.
I've run some tests on some newly generated wallet.dat data... and the master key/priv key/pub key data from the code example in
joric's post that I linked to earlier... and it seems to be working OK.
As per the comment at the top of the script, it borrows very heavily from
the "Proof of Concept" code from joric's post.... full credit to them!
NOTES:
- Python 2.7x compatible only for now... if there is enough interest, I'll see if I can make it Python3 compatible.
- requires a couple of libraries that you'll likely already have installed if you've been using PyWallet etc (ie. pycrypto, ecdsa etc)... if Python moans at you about modules not being found then install them with pip
- (For now) The encrypted master key needs to be the full 66/67 bytes (132/134 hex chars) of the mkey record in the wallet.dat... This should be of the form:
"30" - 48 byte data record indicator
"48 bytes worth of encrypted master key"
"08" - 8 byte data record indicator
"8 bytes worth of salt"
"4 bytes worth of method" - should be 0 (ie. 00000000)
"4 bytes worth of iterations" - in Little Endian (ie. 1fb80000 ==> 0x0000b8f1 ==> 47345)
"00" - 1 byte end of record indicator (optional)
for example:
3008adc5605413b38a04979bf465d0cff826a25c2c8812e582241477052c6d45c11b27690ba3bf2c1da144600789c2baaa08d8659791be653e15000000001760030000
3008adc5605413b38a04979bf465d0cff826a25c2c8812e582241477052c6d45c11b27690ba3bf2c1 da144600789c2baaa08d8659791be653e15000000001760030000
This modified version of the walletinfo.py script (original
here) will output the "full mkey" from a wallet.dat:
https://keybase.pub/hcp/python/walletinfo.pyUsage:
python walletinfo.py wallet.dat
otherwise, you'll have to do some hexediting of the wallet.dat file to find the data you need... have fun with that
I am also considering modifying the script so you can supply the "parsed" master key data (ie. encrypted key, salt, iterations etc) individually... I guess it depends on what is the most likely format of the hex data extracted from the wallet.dat file.
On subsequent runs for private keys from the same wallet.dat (ie. encrypted with the same master key), you can just use the "decrypted master key" that is output instead of using the "encrypted" master key + walletpassphrase
Example:
C:\core_decrypter>C:\Python27\python.exe core_decrypter.py --enc_mkey 3008ADC5605413B38A04979BF465D0CFF826A25C2C8812E582241477052C6D45C11B27690BA3BF2C1DA144600789C2BAAA08D8659791BE653E150000000017600300 BF1356ABEEB7FD2C7CD6757BA4B459AF64D62A3855592B24F685F642D7143D7F6725230C8B8D9B65D42DA5634DDA9A73 020016BE1AFB579AB2EF6F57220E8946B0653FD5B883E09D70A7825F17C3B07F3D
Enter wallet passphrase:
Keys successfully decrypted:
decrypted mkey: 84d1f2f2380eb3a089ea256b851553ebfbc95555eb11b28a9eaaa7eeb97db4d6
--------------------------------------------------------------
uncomp addr: 13y8obG15gqVBmuRzD7HnokyVqGhQJZBfC
uncomp WIF : 5JXMD129XHcfpWF8hrzKG7eW4zDwZtuQ82gkwfMLz9aQRTxvsrh
--------------------------------------------------------------
comp addr : 15V1kJedt9CJDsEYCofuvfWTyapqJPW4C9
comp WIF : KzLxBy64cgLSLg5P1MdybiLXJba7rC6H42SUxGGoDErSNtSKCJKP
--------------------------------------------------------------
C:\core_decrypter>
On the next run, you can just use the "decrypted mkey" that was displayed:
84d1f2f2380eb3a089ea256b851553ebfbc95555eb11b28a9eaaa7eeb97db4d6
... and remove the --enc_mkey flag from the commandline:
C:\core_decrypter>C:\Python27\python.exe core_decrypter.py 84d1f2f2380eb3a089ea256b851553ebfbc95555eb11b28a9eaaa7eeb97db4d6 ba946bb7db1a98e628d1a93104369d7cbb7a4cba9c9705223a2c7891bdc888a8b1019c27d2c17b28728513a51ba54f1e 0200cc635c13471b913e22bbe568711c19fd7bcb7449a9f09885f9ca53aff3cc6e
Keys successfully decrypted:
decrypted mkey: 84d1f2f2380eb3a089ea256b851553ebfbc95555eb11b28a9eaaa7eeb97db4d6
--------------------------------------------------------------
uncomp addr: 1K3p8CZCRZoKuXtzzawYs2LmKuN1uV2jvd
uncomp WIF : 5JsNBq7rwGPqp1jZLSgawvtusp3E47c2PjPex2QgK4Mhj4Bneuv
--------------------------------------------------------------
comp addr : 1CVQVAeTCPhNUCcVsmSqrZoXWQCksbmgmc
comp WIF : L1sJWoPHQWwpSWEqipMiqSt8PGcpck9b9L6zVsDWWhpNkErSrJwf
--------------------------------------------------------------
C:\core_decrypter>
NOTE that there is no "wallet passphrase" prompt!
If the walletpassphrase is not correct or the hex data is corrupt/incorrect, you will see a warning like this:
C:\core_decrypter>C:\Python27\python.exe core_decrypter.py --enc_mkey 3008ADC5605413B38A04979BF465D0CFF826A25C2C8812E582241477052C6D45C11B27690BA3BF2C1DA144600789C2BAAA08D8659791BE653E150000000017600300 BF1356ABEEB7FD2C7CD6757BA4B459AF64D62A3855592B24F685F642D7143D7F6725230C8B8D9B65D42DA5634DDA9A73 020016BE1AFB579AB2EF6F57220E8946B0653FD5B883E09D70A7825F17C3B07F3D
Enter wallet passphrase:
WARNING!!!
WARNING!!! - computed public keys DO NOT match, passphrase is probably incorrect or hex data is corrupt
WARNING!!!
C:\core_decrypter>
The script calculates the pubkey from the decrypted privkey, then compares to the user supplied "hex pub key". If
both the calculated compressed and uncompressed pubkeys do not match the user provided pubkey, then either the wallet passphrase was incorrect (resulting in a bad master key decrypt) or the priv/pub key hex data could be corrupt/incorrect.
Wallet passphrase for the examples above: password123
Partial Pywallet dump (with encrypted privkeys):
keys": [
{
"addr": "15V1kJedt9CJDsEYCofuvfWTyapqJPW4C9",
"compressed": true,
"encrypted_privkey": "bf1356abeeb7fd2c7cd6757ba4b459af64d62a3855592b24f685f642d7143d7f6725230c8b8d9b65d42da5634dda9a73",
"pubkey": "020016be1afb579ab2ef6f57220e8946b0653fd5b883e09d70a7825f17c3b07f3d",
"reserve": 1
},
{
"addr": "1CVQVAeTCPhNUCcVsmSqrZoXWQCksbmgmc",
"compressed": true,
"encrypted_privkey": "ba946bb7db1a98e628d1a93104369d7cbb7a4cba9c9705223a2c7891bdc888a8b1019c27d2c17b28728513a51ba54f1e",
"pubkey": "0200cc635c13471b913e22bbe568711c19fd7bcb7449a9f09885f9ca53aff3cc6e",
"reserve": 1
},
{
"addr": "1JSo3zCQ8xaj9oGgfts8DMATtQ5ptnwigk",
"compressed": true,
"encrypted_privkey": "65207b28be9d6b142837e192797cc782e3c8f868fddb2fb901895dd4115c6bc1367c0787544f48bc631ec7e8fa0ebb51",
"pubkey": "02020828662e18c691abd0ca216d655c576bbbac560a8852e7aafb42acb76ed9b9",
"reserve": 1
},