¿Cómo restaurar localmente una copia de seguridad de MyWallet?

El sitio web blockchain.info tiene un sistema de billetera en línea MyWallet que crea copias de seguridad con una extensión .aes.json. Si bien entiendo que es un archivo json cifrado con AES usando mi frase de contraseña, todavía estoy confundido acerca de lo que se supone que debo hacer para descifrarlo y cargarlo en un cliente local.

Tengo OSX 10.6, pero en aras de la portabilidad hablemos de la línea de comandos, con la esperanza de que al menos se mantenga igual en varias plataformas.

Respuestas (5)

Escribí un pequeño script de Python que se puede usar para descifrar su MyWallet encriptado. Hace lo mismo que MyWallet JavaScript , solo que en Python.

Editar: el código a continuación parece estar desactualizado, aquí hay una versión funcional a partir de mayo de 2012.

Copie lo siguiente en un archivo, hágalo ejecutable y ejecútelo:

#!/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))

Le solicitará la copia de seguridad de la billetera y una o dos contraseñas, dependiendo de si la billetera tiene encriptación simple o doble. Pegue la copia de seguridad de la billetera en lugar de guardarla en un archivo.

Probablemente necesitará Python 2.x. No he podido encontrar un paquete de pycrypto para Python 3. Al parecer, estará disponible en la próxima versión 'precisa' de Ubuntu .

Editar: parece que el formato de la copia de seguridad ha cambiado y, por lo tanto, este script no funciona en las copias de seguridad recientes.

Tenga en cuenta que mi secuencia de comandos no convierte la clave privada en formato 'sipa', que es lo que necesitará el cliente oficial de bitcoin (v0.6 en adelante) para importar una clave privada. Las claves privadas en la billetera descifrada están en formato base58, pero no en formato 'sipa', que incluye una suma de verificación. Tengo la intención de arreglar mi script para convertir claves privadas al formato 'sipa'.
Ahora también muestra la clave en formato 'sipa'.
Ambas respuestas válidas ahora, aceptando esta tanto por el esfuerzo como por Python.
Agregué la entrada de la billetera desde el archivo y me tomé la libertad de crear un proyecto en bitbucket para eso: bitbucket.org/lohoris/mywallet-restore
¿Qué, el desarrollo de código en los comentarios de stackexchange no es lo suficientemente bueno para ti? ;) Buen trabajo.
Cuando pruebo esto en mi billetera respaldada, aparece "ValueError: no se pudo decodificar ningún objeto JSON". Soy nuevo en el trabajo con esta biblioteca criptográfica, ¿cómo me sugeriría que solucione los problemas?
Me pasa lo mismo ahora. Parece que el formato de la copia de seguridad ha cambiado. Un vistazo rápido a la fuente de blockchain.info/DecryptWallet.html muestra que ahora prueba 4 modos de encriptación diferentes, cada uno con 0 a 19 iteraciones de encriptación AES, que no creo que solía hacer.
Ese código es una mierda. El modo utilizado actualmente es CBC. La forma en que pasa las iteraciones también es confusa (y no en el código ezcrypto original AFAICT), ya que esa opción en realidad especifica la cantidad de rondas ejecutadas en PBKDF2 al derivar una clave de la contraseña (y son 10 rondas, siempre). Aquí hay una versión funcional para el formato más reciente: gist.github.com/2757146
@AndreyFedorov "La esencia que estabas buscando ha sido eliminada. ¡Lo siento!"
Entonces gist.github.com/2757171 es la versión fija.
Sí, lo siento por eso.
¿Cómo puedo verificar fácilmente que el resultado de decrypt() es correcto? Un amigo mío perdió la contraseña de su billetera, me gustaría repetir muchas contraseñas potenciales que podría haber elegido hasta que encuentre la correcta.
Parece que el script de python requiere Crypto:Cypher, como un novato de python, es un poco difícil instalarlo en Windows. Estoy trabajando en ello, solo una advertencia justa para los recién llegados.

No sé cómo hacerlo a través de la línea de comando, pero puede usar la herramienta en

https://blockchain.info/DecryptWallet.html

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

Es básico, pero es multiplataforma y hace el trabajo. También puede guardarlo sin conexión.

Se puede guardar sin conexión, pero incluye javascript blockchain.info/Resources/wallet/bitcoinjs.js , ¿no sería necesario copiarlo localmente y editar DecryptWallet.html para poder acceder a él?
Puede eliminar esas cosas (líneas 6 y 7) y el script aún funciona. Parece que se dejó accidentalmente. Todo el código necesario para descifrar la copia de seguridad se encuentra en el propio archivo DecryptWallet.html.
Bueno, el objetivo de esta pregunta es poder restaurarlo fuera de línea en caso de que el servicio colapse, por lo que es bastante inútil requerir que el servicio mismo lo respalde. Claro, guardarlo sin conexión ayuda y funciona, pero es un archivo más que corre el riesgo de perder, además de su billetera, por lo que sería mejor tener herramientas estándar para hacerlo, si es posible.
Está bien. Escribiré un breve script de Python que pueda hacerlo.
@Lohoris: ¿Está buscando algunos comandos simples que pueda recordar? Porque no veo cómo un script de Python es más "herramienta estándar" que Javascript. De cualquier manera, tendrá que guardar ese script en algún lugar o pedirle a alguien que lo reproduzca.
@DH: se archivará... aquí ;)
@Lohoris: me estás tentando a poner el javascript en una respuesta. ;)
@DH: rofl eso serviría, en realidad
Resulta que se necesitaba el archivo bitcoinjs.js para convertir la clave privada al formato 'sipa'. Eso se ha integrado en blockchain.info/DecryptWallet.html ahora, por lo que ahora es realmente una página fuera de línea.
@ChrisMoore: ¡es bueno saberlo!
Vea mi respuesta: tomé lo anterior y lo convertí en un archivo javascript que puede ejecutar usando node.js: bitcoin.stackexchange.com/a/7865/78

Piuk acaba de realizar un parche para MultiBit que permite importar archivos 'json' y 'aes.json' de blockchain.info.

Este parche se incluyó en MultiBit 0.3.4. Aquí está el procedimiento:

Exportar billetera desde blockchain.info -> Importar a MultiBit

1) Haga una exportación de billetera desde blockchain.info

2) Importe a MultiBit usando la pantalla 'Importar claves privadas'.

2.1) En el selector de archivos, elige el sufijo del archivo blockchain.info de ".json" o ".aes.json".

2.2) Elija el archivo de exportación blockchain.info que desea importar.

2.3) Agregue la contraseña única o ambas contraseñas si tiene doble cifrado.

2.4) Pulse "Importar claves privadas".

Debido a que no hay fechas de creación de clave privada en las exportaciones de blockchain.info, desafortunadamente tengo que reproducir los bloques del bloque de génesis (esto lleva un par de horas), por lo que es más una opción de "salir de la cárcel" que algo que usaría día a día.

Tomé el código de Blockchain.info y lo convertí en un archivo javascript independiente que puede ejecutar con node.js.

Hubo algunos problemas ya que el código original no manejaba contraseñas incorrectas, y mi código ahora tiene una sola función check_password(encrypted_json, password)que devuelve verdadero si puede descifrarlo y falso si no.

Ahora, mi objetivo es tomar lo anterior y usarlo para recuperar la contraseña de un amigo. Generaré una lista de todas las combinaciones que podría haber elegido y la probaré con este script.

Aquí hay otro contenedor también hecho en node.js, similar a la respuesta anterior de ripper234. Este funciona con stdin para que pueda usar una herramienta externa para pasar valores: https://github.com/salibhai1/bitcoin-bruteforce-decrypt