Automatice la recuperación de semillas Bip39

Hace poco me bloquearon el acceso a mi Ledger NanoS cuando olvidé el código PIN. Al intentar restablecer mi frase de recuperación, me di cuenta de que solo tengo 23 de las 24 palabras requeridas (desafortunadamente, no estoy seguro de cómo sucedió). No estoy seguro de en qué posición está la palabra, pero estoy seguro de que el orden de las otras 23 palabras es correcto. Dicho esto, tengo que probar todas las posibilidades en cualquier otra posición.

Encontré esta publicación que me da una lista de palabras para completar la palabra que falta: Perdí mi billetera de Bitcoin y solo tengo 11 de las 12 palabras de frases iniciales mnemotécnicas. ¿Cómo puedo obtener mis Bitcoins?

Estoy buscando un fragmento de código que me permita batir las soluciones sin probar manualmente las billeteras 1 por 1.

¿Tiene que necesitar un programa para generar todas las combinaciones posibles? un ejemplo un programa que guarda dentro del archivo toda la combinación posible. ¿O está buscando un programa para probar todas las combinaciones posibles directamente en el dispositivo?
Ahora he enumerado todas las posibilidades a través del código en el enlace de la publicación original. Solo quiero tener una forma automatizada de probar la lista de aproximadamente 200 entradas (creo que la lista es muy pequeña debido a la regla de suma de verificación). Descargué la billetera electrum y he estado probando algunas manualmente, pero el proceso es bastante tedioso.

Respuestas (3)

¿Conoces una de las direcciones del llavero? Ledger usa la derivación BIP44 para que pueda escribir un ciclo para verificar diferentes frases iniciales y verificar las direcciones resultantes con una dirección que sabe que debería estar en el llavero. De esta manera, puede escribir sus palabras de recuperación sin tener que estar en línea.

Por ejemplo, si fuera yo, probablemente escribiría algo usando bitcoinjs-lib . Aquí hay un comienzo escrito con bitcoinjs (NOTA, estoy usando la versión 3.3.2). Esto tomará una semilla de recuperación y una dirección y buscará en el llavero y le dirá si la dirección existe o no dentro de él.

//var words = "segment increase inch ensure corn cigar suggest fetch output proof peasant enact";
//var addr = "1c4XzQx7Uh8CnxzAN5CRrUjkbxGB1GUWp";

var searchbtn = document.getElementById("searchbtn");
searchbtn.onclick = function(){

    var words = document.getElementById("words").value;
    var addr = document.getElementById("addr").value;
    var depth = document.getElementById("depth").value;
    inkeychain(addr, words, depth);
}


function inkeychain(addr, keychain, depth){
    var isfound = false;
    for(var i=0;i<depth;i++){
        var seed = hd.bip39.mnemonicToSeed(keychain);
        var root = b.bitcoin.HDNode.fromSeedBuffer(seed)
        //const root = bitcoin.HDNode.fromSeedHex(seed.toString('hex'))
        var wallet = root.derivePath("m/44'/0'/0'/0/"+i);

        //legacy
        var address = wallet.getAddress();
        var wif = wallet.keyPair.toWIF();

        //segwit p2sh
        var pubKey = wallet.keyPair.getPublicKeyBuffer();
        var pubKeyHash = b.bitcoin.crypto.hash160(pubKey);
        var redeemScript = b.bitcoin.script.witnessPubKeyHash.output.encode(pubKeyHash);
        var redeemScriptHash = b.bitcoin.crypto.hash160(redeemScript);
        var scriptPubKey2 = b.bitcoin.script.scriptHash.output.encode(redeemScriptHash);
        var p2shsegwit = b.bitcoin.address.fromOutputScript(scriptPubKey2);

        if(address===addr){
        isfound = true;
            console.log(address, wif);
            $('#result').html('Found '+addr+' in this keychain at '+i+' position in the keychain');
            alert('Found!');
        } else if (p2shsegwit===addr){
            //check for segwit p2sh
            isfound = true; 
            console.log(p2shsegwit, wif);
            $('#result').html('Found '+addr+' in this keychain at '+i+' position in the keychain');
            alert('Found!');
        } 
    }
if(isfound===false){
    $('#result').html('No matches');
}

}

https://bitcoinfunction.com/?id=5d9ea508d9bed

Desde aquí, puede dar un paso más y convertir la wordsvariable en una matriz con todos sus diferentes combos y luego repetirlos.

Solo sé 23 de las 24 palabras y, de hecho, acabo de encontrar el registro de mi transacción moviendo el bitcoin de una billetera diferente al ledger nano s. ¿Funcionaría usted el método en este caso? Además, si estuviera probando manualmente conjuntos de palabras en electro y seleccioné m/84'/0'/0' en lugar de m/44'/0'/0', ¿me mostraría si había monedas en la billetera o no? Soy un poco experto en informática, pero algo de esto está muy por encima de mi cabeza, así que lo siento por lo que pueden parecer preguntas estúpidas.

Ampliando esta respuesta (usando python) de la pregunta relacionada a la que se vinculó, podemos comenzar a reducir la lista de posibilidades.

Comience con su lista ordenada de palabras conocidas:

ordered_known_words = [
    'glory',
    'twice',
    'film',
    'near',
    'senior',
    'trust',
    'thunder',
    'endorse',
    'suggest',
    'scheme',
    'habit',
    'limit',
    'slow',
    'yard',
    'clog',
    'attend',
    'axis',
    'enough',
    'only',
    'magic',
    'hair',
    'rule',
    'zone',
]

Primero, genera un patrón de frase para cada posición posible de la palabra que falta:

def generate_phrase_patterns(ordered_known_words, mnemonic_length=24):
    list_of_patterns = []

    for i in range(0, mnemonic_length):
        list_template = ['{x}'] * mnemonic_length
        word_position = 0

        for position, known_word in enumerate(ordered_known_words):
            if i <= position:
                list_template[position + 1] = known_word
            else:
                list_template[position] = known_word
            word_position += 1

        list_of_patterns.append(', '.join(list_template))

    return list_of_patterns

Esta lista de listas arrojará algo como lo siguiente:

{x}, glory, twice, film, near, senior, trust, thunder, endorse, suggest, scheme, habit, limit, slow, yard, clog, attend, axis, enough, only, magic, hair, rule, zone
glory, {x}, twice, film, near, senior, trust, thunder, endorse, suggest, scheme, habit, limit, slow, yard, clog, attend, axis, enough, only, magic, hair, rule, zone
glory, twice, {x}, film, near, senior, trust, thunder, endorse, suggest, scheme, habit, limit, slow, yard, clog, attend, axis, enough, only, magic, hair, rule, zone
glory, twice, film, {x}, near, senior, trust, thunder, endorse, suggest, scheme, habit, limit, slow, yard, clog, attend, axis, enough, only, magic, hair, rule, zone
glory, twice, film, near, {x}, senior, trust, thunder, endorse, suggest, scheme, habit, limit, slow, yard, clog, attend, axis, enough, only, magic, hair, rule, zone
glory, twice, film, near, senior, {x}, trust, thunder, endorse, suggest, scheme, habit, limit, slow, yard, clog, attend, axis, enough, only, magic, hair, rule, zone
glory, twice, film, near, senior, trust, {x}, thunder, endorse, suggest, scheme, habit, limit, slow, yard, clog, attend, axis, enough, only, magic, hair, rule, zone
glory, twice, film, near, senior, trust, thunder, {x}, endorse, suggest, scheme, habit, limit, slow, yard, clog, attend, axis, enough, only, magic, hair, rule, zone
glory, twice, film, near, senior, trust, thunder, endorse, {x}, suggest, scheme, habit, limit, slow, yard, clog, attend, axis, enough, only, magic, hair, rule, zone
glory, twice, film, near, senior, trust, thunder, endorse, suggest, {x}, scheme, habit, limit, slow, yard, clog, attend, axis, enough, only, magic, hair, rule, zone
glory, twice, film, near, senior, trust, thunder, endorse, suggest, scheme, {x}, habit, limit, slow, yard, clog, attend, axis, enough, only, magic, hair, rule, zone
glory, twice, film, near, senior, trust, thunder, endorse, suggest, scheme, habit, {x}, limit, slow, yard, clog, attend, axis, enough, only, magic, hair, rule, zone
glory, twice, film, near, senior, trust, thunder, endorse, suggest, scheme, habit, limit, {x}, slow, yard, clog, attend, axis, enough, only, magic, hair, rule, zone
glory, twice, film, near, senior, trust, thunder, endorse, suggest, scheme, habit, limit, slow, {x}, yard, clog, attend, axis, enough, only, magic, hair, rule, zone
glory, twice, film, near, senior, trust, thunder, endorse, suggest, scheme, habit, limit, slow, yard, {x}, clog, attend, axis, enough, only, magic, hair, rule, zone
glory, twice, film, near, senior, trust, thunder, endorse, suggest, scheme, habit, limit, slow, yard, clog, {x}, attend, axis, enough, only, magic, hair, rule, zone
glory, twice, film, near, senior, trust, thunder, endorse, suggest, scheme, habit, limit, slow, yard, clog, attend, {x}, axis, enough, only, magic, hair, rule, zone
glory, twice, film, near, senior, trust, thunder, endorse, suggest, scheme, habit, limit, slow, yard, clog, attend, axis, {x}, enough, only, magic, hair, rule, zone
glory, twice, film, near, senior, trust, thunder, endorse, suggest, scheme, habit, limit, slow, yard, clog, attend, axis, enough, {x}, only, magic, hair, rule, zone
glory, twice, film, near, senior, trust, thunder, endorse, suggest, scheme, habit, limit, slow, yard, clog, attend, axis, enough, only, {x}, magic, hair, rule, zone
glory, twice, film, near, senior, trust, thunder, endorse, suggest, scheme, habit, limit, slow, yard, clog, attend, axis, enough, only, magic, {x}, hair, rule, zone
glory, twice, film, near, senior, trust, thunder, endorse, suggest, scheme, habit, limit, slow, yard, clog, attend, axis, enough, only, magic, hair, {x}, rule, zone
glory, twice, film, near, senior, trust, thunder, endorse, suggest, scheme, habit, limit, slow, yard, clog, attend, axis, enough, only, magic, hair, rule, {x}, zone
glory, twice, film, near, senior, trust, thunder, endorse, suggest, scheme, habit, limit, slow, yard, clog, attend, axis, enough, only, magic, hair, rule, zone, {x}

Ahora, ingrese esto en el código de esta respuesta en la pregunta relacionada que vinculó para generar una lista de todas las frases posibles:

def generate_all_valid_phrases(phrase_patterns):
    from btctools.HD import check, WORDS
    total_phrases = []
    for pattern in phrase_patterns:
        for word in WORDS:
            mnemonic = pattern.format(x=word)
            if check(mnemonic):
                total_phrases.append(mnemonic)
    return total_phrases

En este punto tenemos 180 frases mnemotécnicas válidas de 24 palabras, una de las cuales contiene su moneda.

Si bien podría verificar manualmente todos estos, sería una tarea tediosa. Como se discutió en la respuesta de m1xolyd1an , si conoce una de las direcciones utilizadas anteriormente, podemos usar cada una de estas frases mnemotécnicas para generar las primeras 5 o más direcciones deterministas producidas por cada frase y realizar una comparación para verificar si hay una coincidencia de dirección.

from btctools import Xprv
import json

master_address_list = []

for phrase in total_phrases:

    m = Xprv.from_mnemonic(phrase)

    # check first few address spaces for a known match
    for i in range(0, 5):
        addr = (m/44./0./0./0/i).address('P2PKH')
        if addr == '1C26mdyEsNpe4fpkYtuHzH4Y378wez8mxP':
            master_address_list.append({addr: phrase})
        elif addr == '1BjoCJhvRCx9nVLPaKhg4qQ2YYps8mDgY4':
            master_address_list.append({addr: phrase})


print(f'Address match(s) found: ', len(master_address_list))
print(json.dumps(master_address_list, indent=4, sort_keys=True))

Si se encuentran coincidencias de direcciones, se imprimirán como pares de valores clave:

{
    "<address>": "<mnemonic phrase>"
}

Aquí hay dos scripts de python que incorporan la lógica anterior de diferentes maneras:

1 - Me temo que no puede encontrar/buscar una dirección de bitcoin con 23 de 24 palabras de frase semilla mnemotécnicas.

2 - Otro desastre es no saber el orden de las palabras.

En el futuro... Mi sugerencia será que genere y guarde un valor entropysimilar hexal de esta muestra . Para que pueda recuperar fácilmente cualquier dirección en casos como este.

El autor menciona estar seguro del orden de las otras 23 palabras