Pages:
Author

Topic: Pywallet 2.2: manage your wallet [Update required] - page 35. (Read 208288 times)

mrx
member
Activity: 86
Merit: 10
Having difficulties playing with ixcoin privkeys. They have a high addr version (138).

Code:
ixcoin/src/base58.h:160
#define ADDRESSVERSION   ((unsigned char)(fTestNet ? 111 : 138))  //ixcoin

Code:
2012-01-26 17:23:19+0800 [HTTPChannel,0,172.16.0.3] 172.16.0.3 - - [26/Jan/2012:09:23:19 +0000] "GET /Info?key=MQhdkZfkga2JruxZxpUd39cB6THeTYBootwszNbjGuRUbRxxxx&msg=&pubkey=&sig=&vers=138&format=reg&need=1 HTTP/1.1" 200 18 "http://172.16.0.110:8989/" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1017.2 Safari/535.19"
2012-01-26 17:23:41+0800 [HTTPChannel,0,172.16.0.3] Unhandled Error
        Traceback (most recent call last):
          File "/usr/lib/python2.6/dist-packages/twisted/web/http.py", line 807, in requestReceived
            self.process()
          File "/usr/lib/python2.6/dist-packages/twisted/web/server.py", line 125, in process
            self.render(resrc)
          File "/usr/lib/python2.6/dist-packages/twisted/web/server.py", line 132, in render
            body = resrc.render(self)
          File "/usr/lib/python2.6/dist-packages/twisted/web/resource.py", line 210, in render
            return m(request)
        --- ---
          File "pywalletm.py", line 1771, in render_GET
            pkey = regenerate_key(sec)
          File "pywalletm.py", line 448, in regenerate_key
            b = ASecretToSecret(sec)
          File "pywalletm.py", line 442, in ASecretToSecret
            if vch and vch[0] == chr(addrtype+128):
        exceptions.ValueError: chr() arg not in range(256)

138 + 128 > 255 so pywallet failed to translate those keys. Any workarounds?
legendary
Activity: 1176
Merit: 1280
May Bitcoin be touched by his Noodly Appendage
Many thanks Joric!
I didn't manage to find a working library for it and you found 3 of them...

I have exams this week, so I think I will put that in my fork this week-end or maybe next week
member
Activity: 67
Merit: 130
To whom it may concern - I added encrypted wallets support this morning - http://github.com/joric/pywallet
Here is the shorter, more readable version - PoC and simultaneously the unit test.
Code:
#!/usr/bin/env python

# 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

crypter = None

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():

    #address
    addr = '1AJ3vE2NNYW2Jzv3fLwyjKF1LYbZ65Ez64'
    sec = '5JMhGPWc3pkdgPd9jqVZkRtEp3QB3Ze8ihv62TmmvzABmkNzBHw'
    secret = '47510706d76bc74a5d57bdcffc68c9bbbc2d496bef87c91de7f616129ac62b5f'.decode('hex')
    pubkey = '046211d9b7836892c8eef49c4d0cad7797815eff95108e1d30745c03577596c9c00d2cb1ab27c7f95c28771278f89b7ff40da49fe9b4ee834a3f6a88324db837d8'.decode('hex')
    ckey = '0f8c75e4c6ab3c642dd06786af80ca3a93e391637d029f1da919dad77d3c8e477efd479814ddf4c459aeba042420868f'.decode('hex')

    #master key
    crypted_key = '1e1d7ab34d8007f214eb528a1007c6721b9cd1d2c257adb25378ea8e47e3bdd22cfe93a8b6f18dcbe4206fe8c8178ff1'.decode('hex')
    salt = '3f94e3c670b695dd'.decode('hex')
    rounds = 47135
    method = 0
    password = '12345'

    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)

    crypter.SetKeyFromPassphrase(password, salt, rounds, method)
    masterkey = crypter.Decrypt(crypted_key)
    crypter.SetKey(masterkey)
    crypter.SetIV(Hash(pubkey))
    d = crypter.Decrypt(ckey)
    e = crypter.Encrypt(d)

    print "masterkey:", masterkey.encode('hex')
    print 'c:', ckey.encode('hex')
    print 'd:', d.encode('hex')
    print 'e:', e.encode('hex')

if __name__ == '__main__':
    main()
member
Activity: 84
Merit: 14
I'm running python 2.7.1+ and jackjack-jj-pywallet-db5f0e9, on ubuntu 11.04 64 bit. I do...

$ sudo add-apt-repository ppa:twisted-dev/ppa
$ sudo aptitude install build-essential python-dev python-twisted python-bsddb3

... and so far, so good. But then...

$ sudo easy_install ecdsa
Processing ecdsa
error: Not a recognized archive type: ecdsa

I had a hunt around in synaptic, and the links in jackjack's first post in this thread, but no joy. Arghh, I have had this working before in debian squeeze! Anybody got any ideas how to fix this up for ubuntu 11.04?

edit: Just for the record,

# aptitude install build-essential python-dev python-twisted python-bsddb3 python-setuptools
# easy_install ecdsa

... does the job in debian squeeze (32 bit). I just tried it.
legendary
Activity: 1428
Merit: 1093
Core Armory Developer
So I think I will help everyone with this wallet-extraction thing.  I was the one that found unencrypted keys in the 0.4.0 encrypted wallet, so I'm pretty sure I can find the encrypted keys Smiley  And Armory uses a very similar technique for encryption, so I'm basically already set up for this.  A few things I hope someone will be able to answer for me.  

(1)  I need to find nDeriveIterations.  Is there an easy way to find it for a hex-diver like me, or do I actually have to open the DB file with a BDB library to get to it?
(2)  I wish I'd thought of using the public key as the IV... that's pretty smart.  I assume it is the 65-byte private key that you double-sha256, correct?   Then, is it the first 16 bytes that are used for the IV?  AES256 IVs are only 16 bytes...
(3)  Is there any modification to the passphrase before applying X sha512 operations to it?  Is there any PBKDF2 calls somewhere?  (if there is, I'm not as well-prepared as I thought)

If anyone wants to simply use the work I've already done and split any appropriate bounties, I would be up for that Smiley  I have a python script which currently goes through the wallet.dat file pulls out every single public key, and then grabs any plaintext private keys nearby.  Of course, they private keys are not plaintext in this situation, but I can spit out the data where I expect the keys to be.  Then using CLI input params, I can actually apply the X sha512 operations and AES256-CBC decryption, provided with X and the passphrase.

I wouldn't mind doing this anyway, because I had planned on creating a wallet-conversion/import tool for Armory, but figured it was too much of a hassle.  Maybe now is a good time to deal with it Smiley

donator
Activity: 229
Merit: 106
Hi jackjack, I have a corrupted wallet.dat with about 100 BTCs inside, it was encrypted, could this tool help me recover it? I offer 40 BTCs for anyone help me recover BTCs from this wallet. Details in the this topic:
https://bitcointalksearch.org/topic/help-recovering-from-walletdat-55975
legendary
Activity: 1176
Merit: 1280
May Bitcoin be touched by his Noodly Appendage
Christmas update

New feature: Pywallet checks if it is up-to-date and if not, shows a link to update (automatically)
Encryption still in progress, cryptographic functions in python are such a pain...
legendary
Activity: 1176
Merit: 1280
May Bitcoin be touched by his Noodly Appendage
Thanks a lot Gavin, this will be very helpful!
hero member
Activity: 742
Merit: 500
RE: documentation about key encryption:

See the comment at the top of crypter.h:

Code:
Private key encryption is done based on a CMasterKey,                                                                                                   
which holds a salt and random encryption key.                                                                                                           
                                                                                                                                                       
CMasterKeys are encrypted using AES-256-CBC using a key                                                                                                 
derived using derivation method nDerivationMethod                                                                                                       
(0 == EVP_sha512()) and derivation iterations nDeriveIterations.                                                                                       
vchOtherDerivationParameters is provided for alternative algorithms                                                                                     
which may require more parameters (such as scrypt).                                                                                                     
                                                                                                                                                       
Wallet Private Keys are then encrypted using AES-256-CBC                                                                                               
with the double-sha256 of the public key as the IV, and the                                                                                             
master key's key as the encryption key (see keystore.[ch]).                                                                                             

The way I think of it:  Take the passphrase and salt and SHA512-hash them nDerivationIterations times.  That gets you an encryption key and initialization vector.

Use those to AES-256-decrypt the encrypted_key master key.

Now you can AES-256-decrypt the private keys, using the master key as the key and the (double-sha256-hash) PUBLIC part of the keypair as the initialization vector.

The "SHA-512-hash them a bunch of times" is actually done by the OpenSSL EVP_BytesToKey routine-- documentation for that is here: http://www.openssl.org/docs/crypto/EVP_BytesToKey.html



I'd been wondering about this for awhile. Thanks for the info.

Glad to see you are working on this again jackjack.  Once I can retire one of my old wallets, I'll send you a donation.
legendary
Activity: 1652
Merit: 2311
Chief Scientist
RE: documentation about key encryption:

See the comment at the top of crypter.h:

Code:
Private key encryption is done based on a CMasterKey,                                                                                                   
which holds a salt and random encryption key.                                                                                                           
                                                                                                                                                       
CMasterKeys are encrypted using AES-256-CBC using a key                                                                                                 
derived using derivation method nDerivationMethod                                                                                                       
(0 == EVP_sha512()) and derivation iterations nDeriveIterations.                                                                                       
vchOtherDerivationParameters is provided for alternative algorithms                                                                                     
which may require more parameters (such as scrypt).                                                                                                     
                                                                                                                                                       
Wallet Private Keys are then encrypted using AES-256-CBC                                                                                               
with the double-sha256 of the public key as the IV, and the                                                                                             
master key's key as the encryption key (see keystore.[ch]).                                                                                             

The way I think of it:  Take the passphrase and salt and SHA512-hash them nDerivationIterations times.  That gets you an encryption key and initialization vector.

Use those to AES-256-decrypt the encrypted_key master key.

Now you can AES-256-decrypt the private keys, using the master key as the key and the (double-sha256-hash) PUBLIC part of the keypair as the initialization vector.

The "SHA-512-hash them a bunch of times" is actually done by the OpenSSL EVP_BytesToKey routine-- documentation for that is here: http://www.openssl.org/docs/crypto/EVP_BytesToKey.html


legendary
Activity: 1176
Merit: 1280
May Bitcoin be touched by his Noodly Appendage
Is there any documentation about key encryption? Or anybody knowing how to encrypt/decrypt privkeys?
I can continue my research but if somebody already knows that it would be better

I have the passphrase and these data about the master key, how can I decrypt encrypted privkeys?
Code:
        "encrypted_key": "bda3f31ce15e5e2072fb4fbe7b6e6a55c2da23b067c4f5599a50fa053e617f72aecb31d73dea36bed72b57d19736ea93", 
        "nDerivationIterations": 62351,
        "nDerivationMethod": 0,
        "nID": 1,
        "otherParams": "",
        "salt": "f325081b21a3b80e"
legendary
Activity: 1176
Merit: 1280
May Bitcoin be touched by his Noodly Appendage
My today's success story: Computer of friend of mine crashed two days ago. He went to some IT guy, asking for repair. That guy recommended "format & reinstall" (wow, are all issues with Windows still solving this way?) and asked, if backup of office document and some other stuff is enough for him. Today, friend called me that he has reformatted harddisk and fresh install of Windows and he completely forgot to his bitcoin wallet with 80 BTC, asking me if there is any way how to recover them. I played with pywallet some time ago and I barely noticed such cool feature of finding private keys on raw device, so I told him I'll try the recovery.

It went smooth (except that issue with corrupted blocks - which btw means that "format & reinstall" didn't fix previous issues with Windows) and his wallet has been fully recovered. Thank you jackjack for so cool application, small donation is going your way.
I'm glad it worked even after a reinstall! Thanks for the donation


I keep getting errors for anything I try to do from the web interface, but dumping the wallet and importing keys from the command line work fine. Is this an issue with 5xxxx wallet versions?
What's written in the console?

atm i havent enough time, gonna send u a message when il have enough time Smiley until then i work a bit on my own changing ur code if this is ok Wink

greetings
Thanks


Also I just add the --dont_check_walletversion option to use 0.3.25+ wallet versions
newbie
Activity: 40
Merit: 0
I keep getting errors for anything I try to do from the web interface, but dumping the wallet and importing keys from the command line work fine. Is this an issue with 5xxxx wallet versions?
legendary
Activity: 1386
Merit: 1097
My today's success story: Computer of friend of mine crashed two days ago. He went to some IT guy, asking for repair. That guy recommended "format & reinstall" (wow, are all issues with Windows still solving this way?) and asked, if backup of office document and some other stuff is enough for him. Today, friend called me that he has reformatted harddisk and fresh install of Windows and he completely forgot to his bitcoin wallet with 80 BTC, asking me if there is any way how to recover them. I played with pywallet some time ago and I barely noticed such cool feature of finding private keys on raw device, so I told him I'll try the recovery.

It went smooth (except that issue with corrupted blocks - which btw means that "format & reinstall" didn't fix previous issues with Windows) and his wallet has been fully recovered. Thank you jackjack for so cool application, small donation is going your way.

legendary
Activity: 1792
Merit: 1008
/dev/null
Hi there!
I had to leave for some time, sorry for that
I won't have as much time as before but I won't leave for months anymore

The priority is of course to make pywallet able to deal with encrypted wallets
I can't give you any ETA but I'll do my best

Btw, thanks for your pull requests on Github, I'll check and commit them

any progress? do you need help? Smiley
Tbh I didn't even start
I really need time so yes I need help

If someone have some free time and want to help me, please let me know, especially if you are a programmer

atm i havent enough time, gonna send u a message when il have enough time Smiley until then i work a bit on my own changing ur code if this is ok Wink

greetings
legendary
Activity: 1176
Merit: 1280
May Bitcoin be touched by his Noodly Appendage
I'm trying wallet recovery on corrupted notebook disk, but it failed on IOError when pywallet touched corrupted sector. Following code fixes this issue by skipping bad block in first_read():

Code:
                try:
                        data = os.read (fd, inc)
                except Exception as exc:
                        os.lseek(fd, inc, os.SEEK_CUR)
                        print str(exc)
                        i += inc
                        continue
Thanks, this will be added very soon
legendary
Activity: 1176
Merit: 1280
May Bitcoin be touched by his Noodly Appendage
Hi there!
I had to leave for some time, sorry for that
I won't have as much time as before but I won't leave for months anymore

The priority is of course to make pywallet able to deal with encrypted wallets
I can't give you any ETA but I'll do my best

Btw, thanks for your pull requests on Github, I'll check and commit them

any progress? do you need help? Smiley
Tbh I didn't even start
I really need time so yes I need help

If someone have some free time and want to help me, please let me know, especially if you are a programmer
legendary
Activity: 1386
Merit: 1097
I'm trying wallet recovery on corrupted notebook disk, but it failed on IOError when pywallet touched corrupted sector. Following code fixes this issue by skipping bad block in first_read():

Code:
                try:
                        data = os.read (fd, inc)
                except Exception as exc:
                        os.lseek(fd, inc, os.SEEK_CUR)
                        print str(exc)
                        i += inc
                        continue
legendary
Activity: 1792
Merit: 1008
/dev/null
Hi there!
I had to leave for some time, sorry for that
I won't have as much time as before but I won't leave for months anymore

The priority is of course to make pywallet able to deal with encrypted wallets
I can't give you any ETA but I'll do my best

Btw, thanks for your pull requests on Github, I'll check and commit them

any progress? do you need help? Smiley
full member
Activity: 176
Merit: 100
When trying to install ecdsa on OS X, I get:
Code:
Searching for ecdsa
Reading http://pypi.python.org/simple/ecdsa/
Download error: [Errno 65] No route to host -- Some packages may not be found!
Couldn't find index page for 'ecdsa' (maybe misspelled?)

Any alternative ways to install?

EDIT: Never mind, the site was down or something, but it's back up now.

EDIT #2: I ran into the version mismatch problem, so I edited the source and made max version 51000.  Works perfectly with 0.5.1 as far as I can see.
Pages:
Jump to: