4

I recently was locked out of my Ledger NanoS when I forgot the pin code. Upon trying to reset from my recovery phrase I realized that I only have 23 of the 24 required words (not sure how it happened unfortunately). I am not positive which position the word is in but I am certain the order of the other 23 words is correct. That being said I have to try all possibilities in every other position.

I found this post giving me a list of words to populate the missing word: Lost my Bitcoin wallet and have only 11 out of 12 mnemonic seed phrase words. How can I get my Bitcoins?

I am searching for a piece of code that would allow me to churn the solutions without manually trying the wallets 1 by 1.

3
  • Do you have to need a program for generating all possible combinations? an example a program that save inside the file that all possible combination. Or you are finding an program for testing all possible combinations directly on dispositive? Oct 9, 2019 at 19:49
  • I have now listed all the possibilities through the code on the link the the original post. I just want to have an automated way to test the list of about 200 entries (I believe the list is so small due to checksum rule). I downloaded electrum wallet and have been testing a few manually but the process is quite tedious
    – Nate Gray
    Oct 9, 2019 at 20:11
  • @NateGray, hello from the future. DId you recover your wallet?
    – dhempler
    Jun 12 at 19:03

3 Answers 3

1

Do you know one of the addresses in the keychain? Ledger uses BIP44 derivation so you could write a loop to check different seed phrases and check the resulting addresses against an address you know that should be in the keychain. This way you can type in your recovery words without having to be online.

For example if it were me I'd probably write something using the bitcoinjs-lib. Here's a start written with bitcoinjs (NOTE I'm using version 3.3.2). This will take a recovery seed and an address and it will search the keychain and tell you whether or not the address exists within it.

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

From here you could take it a step further and make the words variable an array with all your different combos and then loop them all through.

1
  • I only know 23 of the 24 words and I actually just found the transaction record of me moving the bitcoin from a different wallet to the ledger nano s. Would you method work in this case? Also if I were manually testing sets of words in electrum and I selected m/84'/0'/0' instead of m/44'/0'/0' would it show me if there were coins in the wallet or not? I am slightly computer savvy but some of this is way over my head, so sorry for what may seem like stupid questions.
    – Nate Gray
    Oct 10, 2019 at 20:53
0

Expanding off of this answer (using python) from the related question you linked to we can start to narrow down the list of possibilities.

Start off with your ordered list of known words:

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',
]

First, generate a phrase pattern for each possible position of your missing word:

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

This will a list of lists yield something like the following:

{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}

Now, feed this into the code from this answer on the related question you linked to generate a list of all possible phrases:

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

At this point we have 180 valid 24 word mnemonic phrases, one of which contains your coin.

While you could manually check all of these that would be a tedious task. As discussed in m1xolyd1an's answer, if you know one of the address' previously used, we can use each of these mnemonic phrases to generate the first 5 or so deterministic addresses produced by each phrase and perform a comparisson to check for an address match.

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

If any address matches are found this will print them as key value pairs:

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

Here are two python scripts using incorporating the above logic in different ways:

-1

1 - I'm afraid, you can't find/search a bitcoin address with 23 of 24 mnemonic seed phrase words.

2 - Another disaster is not knowing the order of the words.

Going forward... My suggestion will be that you generate and save an entropy like the hex value in this sample . So that you can easily retrieve any address in cases like this.

1
  • 1
    The author mentions being certain of the order of the other 23 words
    – taky2
    Feb 28, 2020 at 5:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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