Skip to content

Instantly share code, notes, and snippets.

@llazzaro
Forked from fcicq/mywallet.py
Last active August 29, 2015 14:08
Show Gist options
  • Save llazzaro/f5277d3747290763a0f1 to your computer and use it in GitHub Desktop.
Save llazzaro/f5277d3747290763a0f1 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))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment