Pages:
Author

Topic: recover keys from wallet.dat without using pywallet (Read 1651 times)

member
Activity: 351
Merit: 37
thing is fucked up. do you know there's EVP_CIPHER_CTX_free() on scene?
jr. member
Activity: 50
Merit: 30
Hi, since HCP wasnt online for 2 weeks now, does someone by chance has his coredecrypter?

I am unsure if I modified his code at all, however it is original or very close.
If I did edit it, it will print without verfication of the key pairs regadless of the data inputed.
HCP donation address has NOT BEEN CHANGED!


#!/usr/bin/env python

# Bitcoin Core wallet.dat masterkey/privkey decrypter
#
# Coded by HCP 2021
#
# Donations: BTC - 33o4MoDSFrfKSznHLBzwKigpTQvMiWWsHr
#
# Borrows heavily from joric's PoC code here: https://bitcointalksearch.org/topic/m.708668
# Bitcoin wallet keys AES encryption / decryption (see http://github.com/joric/pywallet)
# Uses pycrypto or libssl or libeay32.dll or aes.py from http://code.google.com/p/slowaes

import argparse
import base58
import binascii
import ecdsa
import getpass
import hashlib
import struct
import sys

crypter = None

debug = 0

try:
    from Crypto.Cipher import AES
    crypter = 'pycrypto'
except:
    pass

class Crypter_pycrypto( object ):
    def SetKeyFromPassphrase(self, vKeyData, vSalt, nDerivIterations, nDerivationMethod):
        data = vKeyData + vSalt
        for i in range(nDerivIterations):
            data = hashlib.sha512(data).digest()
        self.SetKey(data[0:32])
        self.SetIV(data[32:32+16])
        return len(data)

    def SetKey(self, key):
        self.chKey = key

    def SetIV(self, iv):
        self.chIV = iv[0:16]

    def Encrypt(self, data):
        return AES.new(self.chKey,AES.MODE_CBC,self.chIV).encrypt(data)[0:32]
 
    def Decrypt(self, data):
        return AES.new(self.chKey,AES.MODE_CBC,self.chIV).decrypt(data)[0:32]

try:
    if not crypter:
        import ctypes
        import ctypes.util
        ssl = ctypes.cdll.LoadLibrary (ctypes.util.find_library ('ssl') or 'libeay32')
        crypter = 'ssl'
except:
    pass

class Crypter_ssl(object):
    def __init__(self):
        self.chKey = ctypes.create_string_buffer (32)
        self.chIV = ctypes.create_string_buffer (16)

    def SetKeyFromPassphrase(self, vKeyData, vSalt, nDerivIterations, nDerivationMethod):
        strKeyData = ctypes.create_string_buffer (vKeyData)
        chSalt = ctypes.create_string_buffer (vSalt)
        return ssl.EVP_BytesToKey(ssl.EVP_aes_256_cbc(), ssl.EVP_sha512(), chSalt, strKeyData,
            len(vKeyData), nDerivIterations, ctypes.byref(self.chKey), ctypes.byref(self.chIV))

    def SetKey(self, key):
        self.chKey = ctypes.create_string_buffer(key)

    def SetIV(self, iv):
        self.chIV = ctypes.create_string_buffer(iv)

    def Encrypt(self, data):
        buf = ctypes.create_string_buffer(len(data) + 16)
        written = ctypes.c_int(0)
        final = ctypes.c_int(0)
        ctx = ssl.EVP_CIPHER_CTX_new()
        ssl.EVP_CIPHER_CTX_init(ctx)
        ssl.EVP_EncryptInit_ex(ctx, ssl.EVP_aes_256_cbc(), None, self.chKey, self.chIV)
        ssl.EVP_EncryptUpdate(ctx, buf, ctypes.byref(written), data, len(data))
        output = buf.raw[:written.value]
        ssl.EVP_EncryptFinal_ex(ctx, buf, ctypes.byref(final))
        output += buf.raw[:final.value]
        return output

    def Decrypt(self, data):
        buf = ctypes.create_string_buffer(len(data) + 16)
        written = ctypes.c_int(0)
        final = ctypes.c_int(0)
        ctx = ssl.EVP_CIPHER_CTX_new()
        ssl.EVP_CIPHER_CTX_init(ctx)
        ssl.EVP_DecryptInit_ex(ctx, ssl.EVP_aes_256_cbc(), None, self.chKey, self.chIV)
        ssl.EVP_DecryptUpdate(ctx, buf, ctypes.byref(written), data, len(data))
        output = buf.raw[:written.value]
        ssl.EVP_DecryptFinal_ex(ctx, buf, ctypes.byref(final))
        output += buf.raw[:final.value]
        return output

try:
    if not crypter:
        from aes import *
        crypter = 'pure'
except:
    pass

class Crypter_pure(object):
    def __init__(self):
        self.m = AESModeOfOperation()
        self.cbc = self.m.modeOfOperation["CBC"]
        self.sz = self.m.aes.keySize["SIZE_256"]

    def SetKeyFromPassphrase(self, vKeyData, vSalt, nDerivIterations, nDerivationMethod):
        data = vKeyData + vSalt
        for i in range(nDerivIterations):
            data = hashlib.sha512(data).digest()
        self.SetKey(data[0:32])
        self.SetIV(data[32:32+16])
        return len(data)

    def SetKey(self, key):
        self.chKey = [ord(i) for i in key]

    def SetIV(self, iv):
        self.chIV = [ord(i) for i in iv]

    def Encrypt(self, data):
        mode, size, cypher = self.m.encrypt(data, self.cbc, self.chKey, self.sz, self.chIV)
        return ''.join(map(chr, cypher))
 
    def Decrypt(self, data):
        chData = [ord(i) for i in data]
        return self.m.decrypt(chData, self.sz, self.cbc, self.chKey, self.sz, self.chIV)

import hashlib

def Hash(data):
    return hashlib.sha256(hashlib.sha256(data).digest()).digest()

def main():

    parser = argparse.ArgumentParser(description="Bitcoin Core wallet.dat masterkey/privkey decrypter")
    
    parser.add_argument("--enc_mkey", action="store_true", default=False,
                        help="required if Master Key is Encrypted")
    parser.add_argument("mkey", action="store",
                        help="Master Key (can be encrypted or decrypted)")
    parser.add_argument("privkey", action="store",
                        help="Encrypted Private Key")
    parser.add_argument("pub", action="store",
                        help="Public Key of privkey (compressed or uncompressed)")

    
    results = parser.parse_args()
    
    if (results.enc_mkey):
        encrypted_master_key = binascii.unhexlify(results.mkey)
        encrypted_mkey, salt, method, iterations = struct.unpack_from("< 49p 9p I I", encrypted_master_key)
        
        if (debug):
            print("--------------------------------------------------------------")
            print "Successfully parsed encrypted master key\n"
            print "enc mkey: ", binascii.hexlify(encrypted_mkey)
            print "salt    : ", binascii.hexlify(salt)
            print "method  : ", method
            print "#iters  : ", iterations
            print("--------------------------------------------------------------")
        
        wallet_pass_phrase = getpass.getpass("\nEnter wallet passphrase: ")
    else:
        decrypted_master_key = binascii.unhexlify(results.mkey)
    
    enc_priv_key = binascii.unhexlify(results.privkey)
    pub_key = binascii.unhexlify(results.pub)
    
    global crypter

    if crypter == 'pycrypto':
        crypter = Crypter_pycrypto()
    elif crypter == 'ssl':
        crypter = Crypter_ssl()
        print "using ssl"
    elif crypter == 'pure':
        crypter = Crypter_pure()
        print "using slowaes"
    else:
        print("Need pycrypto of libssl or libeay32.dll or http://code.google.com/p/slowaes")
        exit(1)

    if (results.enc_mkey):
        crypter.SetKeyFromPassphrase(wallet_pass_phrase, salt, iterations, method)
        masterkey = crypter.Decrypt(encrypted_mkey)
        if (debug):
            print "Decrypted Master Key as:"
            print "dec mkey   : ", binascii.hexlify(masterkey)
            print("--------------------------------------------------------------")
    else:
        masterkey = binascii.unhexlify(results.mkey)
        
    crypter.SetKey(masterkey)
    crypter.SetIV(Hash(pub_key))
    
    d = crypter.Decrypt(enc_priv_key)
    e = crypter.Encrypt(d)

    if (debug):
        print 'dec privkey: ', binascii.hexlify(d)
        print("--------------------------------------------------------------")
    
    # Private key to public key (ecdsa transformation)
    private_key = ecdsa.SigningKey.from_string(d, curve = ecdsa.SECP256k1)
    verifying_key = private_key.get_verifying_key()
    uncomp_public_key = getPubKey(verifying_key.pubkey, False)
    if (debug):
        print 'calc pubkey: ', binascii.hexlify(uncomp_public_key)
        print 'orig pubkey: ', binascii.hexlify(pub_key)
        
    # hash sha 256 of pubkey
    sha256_1 = hashlib.sha256(uncomp_public_key)

    # hash ripemd of sha of pubkey
    ripemd160 = hashlib.new("ripemd160")
    ripemd160.update(sha256_1.digest())

    # checksum
    hashed_public_key = binascii.unhexlify("00") + ripemd160.digest()
    checksum_full = hashlib.sha256(hashlib.sha256(hashed_public_key).digest()).digest()
    checksum = checksum_full[:4]
    uncomp_bin_addr = hashed_public_key + checksum

    # encode address to base58 and print
    uncomp_result_address = base58.b58encode(uncomp_bin_addr)
    if (debug):
        print "\nuncomp addr: ", uncomp_result_address
    
    network_byte_key = binascii.unhexlify("80") + d
    priv_checksum_full = hashlib.sha256(hashlib.sha256(network_byte_key).digest()).digest()
    priv_checksum = priv_checksum_full[:4]
    uncomp_full_priv = network_byte_key + priv_checksum
    
    uncomp_wif = base58.b58encode(uncomp_full_priv)
    if (debug):
        print "uncomp WIF : ", uncomp_wif        
        print("--------------------------------------------------------------")
        
    # now do compressed
    comppub_key = getPubKey(verifying_key.pubkey, True)
    if (debug):
        print 'comp pubkey: ', binascii.hexlify(comppub_key)
        print 'orig pubkey: ', binascii.hexlify(pub_key)
        
    # hash sha 256 of pubkey
    sha256_1 = hashlib.sha256(comppub_key)

    # hash ripemd of sha of pubkey
    ripemd160 = hashlib.new("ripemd160")
    ripemd160.update(sha256_1.digest())

    # checksum
    hashed_public_key = binascii.unhexlify("00") + ripemd160.digest()
    checksum_full = hashlib.sha256(hashlib.sha256(hashed_public_key).digest()).digest()
    checksum = checksum_full[:4]
    comp_bin_addr = hashed_public_key + checksum

    # encode address to base58 and print
    comp_result_address = base58.b58encode(comp_bin_addr)
    if (debug):
        print "\ncomp addr  : ", comp_result_address

    network_byte_key = binascii.unhexlify("80") + d + binascii.unhexlify("01")
    priv_checksum_full = hashlib.sha256(hashlib.sha256(network_byte_key).digest()).digest()
    priv_checksum = priv_checksum_full[:4]
    comp_full_priv = network_byte_key + priv_checksum
    
    comp_wif = base58.b58encode(comp_full_priv)
    if (debug):
        print "comp WIF   : ", comp_wif
        print("--------------------------------------------------------------")
        
    if (pub_key != comppub_key) and (pub_key != uncomp_public_key):
        print "\n\nWARNING!!!"
        print "WARNING!!! - computed public keys DO NOT match, passphrase is probably incorrect or hex data is corrupt"
        print "WARNING!!!"
        exit()
    else:
        print "\nKeys successfully decrypted:\n"
        print "decrypted mkey: ", binascii.hexlify(masterkey)
        print("--------------------------------------------------------------")
        print "uncomp addr: ", uncomp_result_address
        print "uncomp WIF : ", uncomp_wif        
        print("--------------------------------------------------------------")
        print "comp addr  : ", comp_result_address
        print "comp WIF   : ", comp_wif
        print("--------------------------------------------------------------")
        

# pywallet openssl private key implementation

def getPubKey(pubkey, compressed=False):
    # public keys are 65 bytes long (520 bits)
    # 0x04 + 32-byte X-coordinate + 32-byte Y-coordinate
    # 0x00 = point at infinity, 0x02 and 0x03 = compressed, 0x04 = uncompressed
    # compressed keys: where is 0x02 if y is even and 0x03 if y is odd
    if compressed:
        if pubkey.point.y() & 1:
            key = '03' + '%064x' % pubkey.point.x()
        else:
            key = '02' + '%064x' % pubkey.point.x()
    else:
        key = '04' + \
              '%064x' % pubkey.point.x() + \
              '%064x' % pubkey.point.y()

    return key.decode('hex')

if __name__ == '__main__':
    main()
legendary
Activity: 1568
Merit: 6660
bitcoincleanup.com / bitmixlist.org
Hi, since HCP wasnt online for 2 weeks now, does someone by chance has his coredecrypter?

The coredecryptor python script is inaccessible from a web prowser because keybase.pub shut down almost a year ago. It was a separate service from Keybase itself IIRC.

However, according to this comment: https://news.ycombinator.com/item?id=34711449 it seems that you are still able to access the directory through the Keybase program itself. I am not sure how that would work though, because I haven't used Keybase since it was acquired by Zoom.
newbie
Activity: 2
Merit: 0
Hi, since HCP wasnt online for 2 weeks now, does someone by chance has his coredecrypter?
member
Activity: 119
Merit: 36


Quote
The passphrase is no problem as I already know it. I wonder if the salt and iteration are viewable within the wallet file? How do these various scripts find them?

I posted a script to explain what goes on. it is here
https://bitcointalksearch.org/topic/wallet-encryption-process-5331322

Please note this script does not match bitcoin decryption exactly (on purpose) it is for demonstration

If you want the script for bitcoin send me a pm.
newbie
Activity: 33
Merit: 0
I am try this method. It is useful for me.  You also try this . If you have a wallet.dat file and need to recover the keys without using pywallet, you can use a tool like Bitcoin Core to extract the keys. Bitcoin Core is a full Bitcoin client and will attempt to recover all keys stored in your wallet.dat file. It is a bit more complicated than using pywallet, but it is an effective way to recover your keys.
newbie
Activity: 3
Merit: 0
newbie
Activity: 22
Merit: 6
root@RémiM:~# python2.7 core_decrypter.py?dl=1.1
-snip-
root@RémiM:~# pip install base58
Requirement already satisfied: base58 in /usr/local/lib/python3.9/dist-packages (2.1.1)
can you help please? Thanks
everytime i try i get thiis
Pip is installing base58 to Python 3.9 while you're using Python 2.7 for core_decrypter.py.
Try to specify the python version when using pip.
thanks. I'll try it.
legendary
Activity: 2534
Merit: 6080
Self-proclaimed Genius
root@RémiM:~# python2.7 core_decrypter.py?dl=1.1
-snip-
root@RémiM:~# pip install base58
Requirement already satisfied: base58 in /usr/local/lib/python3.9/dist-packages (2.1.1)
can you help please? Thanks
everytime i try i get thiis
Pip is installing base58 to Python 3.9 while you're using Python 2.7 for core_decrypter.py.
Try to specify the python version when using pip.
newbie
Activity: 22
Merit: 6
newbie
Activity: 1
Merit: 0
I hope you will get it someday.
You just need to dig a little bit deeper pull it apart and reassemble it in a slightly altered way.
Are you being deliberately obtuse? or am I just missing something obvious? Huh I honestly have no idea what you're talking about when you say that "you can do it"... do what exactly? Huh

The script takes the raw encrypted "mkey" hex, breaks it down into the actual key, the salt, the iterations etc... then prompts for the wallet passphrase... then decrypts the master key... then uses that decrypted master key to decrypt a given "ckey" record (note that the pubkey part of the "ckey" is required as it is used to form the "IV" for the encrypted private key)


So why do I need to dig a little bit deeper? What needs pulling apart? Huh What does the script not currently do, that you think it should? Huh

YOU SAID THAT script takes the raw encrypted "mkey" hex, breaks it down into the actual key, so this actual key is AES key?
And if we crack this actual key do we get decrypted mkey?
(from above example decrypted mkey-84d1f2f2380eb3a089ea256b851553ebfbc95555eb11b28a9eaaa7eeb97db4d6)
member
Activity: 180
Merit: 38
Spit out the right key if you don't know the password.

 
HCP
legendary
Activity: 2086
Merit: 4361
I hope you will get it someday.
You just need to dig a little bit deeper pull it apart and reassemble it in a slightly altered way.
Are you being deliberately obtuse? or am I just missing something obvious? Huh I honestly have no idea what you're talking about when you say that "you can do it"... do what exactly? Huh

The script takes the raw encrypted "mkey" hex, breaks it down into the actual key, the salt, the iterations etc... then prompts for the wallet passphrase... then decrypts the master key... then uses that decrypted master key to decrypt a given "ckey" record (note that the pubkey part of the "ckey" is required as it is used to form the "IV" for the encrypted private key)


So why do I need to dig a little bit deeper? What needs pulling apart? Huh What does the script not currently do, that you think it should? Huh
member
Activity: 180
Merit: 38
Perhaps you can add this also then you can do it

Code:
from Crypto.Cipher import AES
I'm not sure what you mean by this? Huh

That is one of the first things the script attempts to do... it checks to see if pycrypto is installed, if so then it sets up the "crypter" to use that... otherwise it tries OpenSSL, if that fails, then it tries to use "slowaes" and if that fails it prints an error message and exits.

I hope you will get it someday.
You just need to dig a little bit deeper pull it apart and reassemble it in a slightly altered way.
full member
Activity: 217
Merit: 109
Thanks so much for doing this HCP, it gives me another avenue to pursue (probably the last). I don't have much spare time at the moment to try it out and it's very time consuming for me, being the computer thicko that I am Smiley. I might need some pointers if you don't mind, once I have a go at it. Thanks again, nice work. Smiley
HCP
legendary
Activity: 2086
Merit: 4361
Perhaps you can add this also then you can do it

Code:
from Crypto.Cipher import AES
I'm not sure what you mean by this? Huh

That is one of the first things the script attempts to do... it checks to see if pycrypto is installed, if so then it sets up the "crypter" to use that... otherwise it tries OpenSSL, if that fails, then it tries to use "slowaes" and if that fails it prints an error message and exits.
member
Activity: 180
Merit: 38
Perhaps you can add this also then you can do it

Code:
from Crypto.Cipher import AES

 
HCP
legendary
Activity: 2086
Merit: 4361
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.py

It'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! Wink




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 Tongue





- (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:
Code:
3008adc5605413b38a04979bf465d0cff826a25c2c8812e582241477052c6d45c11b27690ba3bf2c1da144600789c2baaa08d8659791be653e15000000001760030000

Quote
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.py

Usage:
Code:
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 Tongue

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. Huh





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:
Code:
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:
Code:
84d1f2f2380eb3a089ea256b851553ebfbc95555eb11b28a9eaaa7eeb97db4d6

... and remove the --enc_mkey flag from the commandline:
Code:
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! Wink





If the walletpassphrase is not correct or the hex data is corrupt/incorrect, you will see a warning like this:
Code:
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):
Code:
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
        },
full member
Activity: 217
Merit: 109
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.
HCP
legendary
Activity: 2086
Merit: 4361
...
For the curious... Gavin Anderson explains some of this here: https://bitcointalksearch.org/topic/m.656114

And it seems that Joric showed some specific Python based code for dealing with the encryption/decryption here: https://bitcointalksearch.org/topic/m.708668

I will have to experiment further when I get some time... but it's Mother's Day here today Wink
Pages:
Jump to: