10

The website blockchain.info has an online wallet system MyWallet which creates backups with a .aes.json extension. While I understand it's a json file encrypted with AES using my passphrase, I'm still confused about what am I supposed to do to decrypt it and load it into a local client.

I have OSX 10.6, but for portability sake let's just talk about command line, hoping at least that one stays the same on multiple platforms.

5 Answers 5

7

I wrote a small Python script which can be used to decrypt your encrypted MyWallet. It does the same as the MyWallet JavaScript, only in Python.

Edit: the code below seems to be outdated, here's a working version as of May 2012.

Copy the following into a file, make it executable, then run it:

#!/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:]
    length = len(encrypted)
    encrypted += ' ' * (15 - (length-1)%16)
    hash = (hmac.new(password, iv + "\x00\x00\x00\x01", hashlib.sha1).digest() +
            hmac.new(password, iv + "\x00\x00\x00\x02", hashlib.sha1).digest())[:32]
    clear = AES.new(hash, AES.MODE_OFB, iv).decrypt(encrypted)[:length]
    return clear

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])

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

It will prompt for the wallet backup and one or two passwords, depending on whether the wallet is single or double encrypted. Paste the wallet backup in rather than saving it to a file.

You'll probably need Python 2.x. I've been unable to find a package of the pycrypto stuff for Python 3. Apparently it will be available in the upcoming 'precise' Ubuntu release.

Edit: It seems the backup format has been changed and so this script doesn't work on recent backups.

13
  • Note that my script doesn't convert the private key into 'sipa' format, which is what the official bitcoin client will need (v0.6 onwards) to import a private key. The private keys in the decrypted wallet are in base58 format, but not the 'sipa' format, which includes a checksum. I intend to fix my script to convert private keys to 'sipa' format. Commented Feb 29, 2012 at 19:07
  • 2
    Now it shows the key in 'sipa' format too. Commented Feb 29, 2012 at 20:11
  • Both valid answers now, accepting this one both for the effort and because of python.
    – o0'.
    Commented Mar 27, 2012 at 11:05
  • 1
    What, code development in stackexchange comments not good enough for ya? ;) Nice work. Commented Apr 30, 2012 at 15:55
  • 2
    So gist.github.com/2757171 is the fixed version. Commented May 20, 2012 at 21:04
5

I don't know how to do it via the command line, but you can use the tool at

https://blockchain.info/DecryptWallet.html

http://pastehtml.com/view/bprww2t3g.html

It's basic, but its cross platform and gets the job done. You can also save it offline.

11
  • t can be saved offline, but it includes the javascript blockchain.info/Resources/wallet/bitcoinjs.js so wouldn't that need to be copied locally and DecryptWallet.html edited to be able to access it? Commented Feb 29, 2012 at 4:03
  • 1
    Well, the whole point of this question is being able to restore it offline in case the service collapses, so it is pretty useless to require the service itself to back it up. Sure, saving it offline helps and does the trick, but it's one more file you risk losing, other than your wallet, so it would be better to have standard tools to do that, if possible.
    – o0'.
    Commented Feb 29, 2012 at 8:20
  • 1
    OK, fine. I'll write a short Python script that can do it. Commented Feb 29, 2012 at 9:51
  • 1
    @Lohoris: You're tempting me to put the javascript in an answer. ;)
    – D.H.
    Commented Feb 29, 2012 at 13:13
  • 1
    It turns out that the bitcoinjs.js file was needed for converting the private key to 'sipa' format. That has been inlined into blockchain.info/DecryptWallet.html now, so it is truly now an offline page. Commented Feb 29, 2012 at 18:27
3

Piuk has just made a patch to MultiBit that enables blockchain.info 'json' and 'aes.json' files to be imported.

This patch was included in MultiBit 0.3.4. Here is the how-to:

Export wallet from blockchain.info -> Import to MultiBit

1) Do a wallet export from blockchain.info

2) Import into MultiBit using the 'Import private keys' screen.

2.1) In the file chooser you choose the blockchain.info file suffix of ".json" or ".aes.json".

2.2) Choose the blockchain.info export file you want to import.

2.3) Add in either the single password or both passwords if it is double encrypted.

2.4) Press "Import private keys".

Because there are no private key creation dates in the blockchain.info exports I unfortunately have to replay the blocks from the genesis block (this takes a couple of hours) so it is more a "get out of jail" option than something you would use day to day.

2

I took the code from Blockchain.info and converted it into a standalone javascript file that you can run with node.js.

There were some issues as the original code didn't handle wrong passwords, and my code now has a single function check_password(encrypted_json, password) that returns true if it can decrypt it, and false if not.

Now, my goal is to take the above and use it to recover a friend's password. I'll generate a list of all combinations he might have chosen, and test it with this script.

0

Here's another wrapper also done in node.js, similar to the response above by ripper234. This one works with stdin so you can use an external tool to pass in values: https://github.com/salibhai1/bitcoin-bruteforce-decrypt

Not the answer you're looking for? Browse other questions tagged or ask your own question.