-
-
Save anfedorov/2757171 to your computer and use it in GitHub Desktop.
| #!/usr/bin/env python | |
| import base64, hashlib, hmac, json, sys, getpass | |
| from Crypto.Cipher import AES | |
| from Crypto.Hash import RIPEMD, SHA256 | |
| base58_chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' | |
| def prompt(p): | |
| return getpass.getpass(p + ": ") | |
| def decrypt(encrypted, password): | |
| encrypted = base64.b64decode(encrypted) | |
| iv, encrypted = encrypted[:16], encrypted[16:] | |
| aeshash = pbkdf2(password, iv, 10, 32) | |
| clear = remove_iso10126_padding(AES.new(aeshash, AES.MODE_CBC, iv).decrypt(encrypted)) | |
| return clear | |
| def remove_iso10126_padding(s): | |
| ba = bytearray(s) | |
| pad_len = ba[-1] | |
| return str(ba[:-pad_len]) | |
| def base58_decode(v): | |
| value = 0; ret = '' | |
| for c in v: value = value*58 + base58_chars.find(c) | |
| for i in range(32): | |
| ret = "%c"%(value%256) + ret; value /= 256 | |
| return ret | |
| def base58_encode(v): | |
| value = 0; ret = '' | |
| for c in v: value = value*256 + ord(c) | |
| while value > 0: | |
| ret = base58_chars[value%58] + ret; value /= 58 | |
| return ret | |
| def to_sipa(s): | |
| version = 128 # or 239 for testnet | |
| key = chr(version) + base58_decode(s) | |
| return base58_encode(key + SHA256.new(SHA256.new(key).digest()).digest()[:4]) | |
| # pbkdf2 from http://matt.ucc.asn.au/src/pbkdf2.py | |
| from struct import pack | |
| # this is what you want to call. | |
| def pbkdf2( password, salt, itercount, keylen, hashfn = hashlib.sha1 ): | |
| digest_size = hashfn().digest_size | |
| # l - number of output blocks to produce | |
| l = keylen / digest_size | |
| if keylen % digest_size != 0: | |
| l += 1 | |
| h = hmac.new( password, None, hashfn ) | |
| T = "" | |
| for i in range(1, l+1): | |
| T += pbkdf2_F( h, salt, itercount, i ) | |
| return T[0: keylen] | |
| def xorstr( a, b ): | |
| if len(a) != len(b): | |
| raise "xorstr(): lengths differ" | |
| ret = '' | |
| for i in range(len(a)): | |
| ret += chr(ord(a[i]) ^ ord(b[i])) | |
| return ret | |
| def prf( h, data ): | |
| hm = h.copy() | |
| hm.update( data ) | |
| return hm.digest() | |
| # Helper as per the spec. h is a hmac which has been created seeded with the | |
| # password, it will be copy()ed and not modified. | |
| def pbkdf2_F( h, salt, itercount, blocknum ): | |
| U = prf( h, salt + pack('>i',blocknum ) ) | |
| T = U | |
| for i in range(2, itercount+1): | |
| U = prf( h, U ) | |
| T = xorstr( T, U ) | |
| return T | |
| clear = decrypt(prompt("encrypted wallet"), prompt("password")) | |
| obj = json.loads(clear) | |
| if (obj.has_key('double_encryption')): | |
| print("wallet uses double encryption") | |
| password = obj['sharedKey'].encode('ascii') + prompt("2nd password") | |
| for key in obj['keys']: key['priv'] = decrypt(key['priv'], password) | |
| for key in obj['keys']: key['priv_sipa'] = to_sipa(key['priv']) | |
| print(json.dumps(obj, indent=4, sort_keys = True)) |
I have a problem that I created a wallet in April and I was shure that I remembered my password but now I cant remember it. How can I use this script of your, where do I have to copy/paste program text that you written. I tried to put it in plain .txt file and to change extension to .exe and noting is happening. After that I put yout program text into wallet ande I changed extension of wallet from dat to exe and nothing again. Sorry because I don't understand this field of computing, but can you help me?
Anyone have a JS version of this handy?
Any clue how to make this work to bruteforce the 2nd password? I found one of my wallet backups and I've got .2 btc on it, I know the 1st pass no problem, but forgot my 2nd pass, mnemonic and stuff is long gone. If someone can hook me up with a script to force the 2nd password I'll split the loot with them!
How can I easily verify the result of decrypt() is correct?
A friend of mine lost his wallet password, I would like to iterate on a lots of potential passwords he might have chosen until I find the right one.