Post
Topic
Board Development & Technical Discussion
Merits 4 from 1 user
Re: I have address and BIP32 root key, How to brute force to find derived pathway?
by
mcdouglasx
on 10/12/2024, 17:19:03 UTC
⭐ Merited by vapourminer (4)
I had created a mnemonic seed and address using MMGEN wallet but forgot to store the mnemonic seed, but did store the bip 32 root key by using the mnemonic seed on Ian colmen

Now I want to derive the same address using a derivation path and bip 32 root key. can you please tell me what would be the derivation path, since it is mentioned in the wiki, that the wallet is deterministically deriving its keys, but uses a non-hierarchical scheme differing from the BIP32.

Please help me if anyone has any idea which derivation path they are using.

According to Mmgen's github repository, apart from the standard:

BIP44 (P2PKH): m/44 '/0'/0 '/0

BIP49 (P2SH-P2WPKH): m/49 '/0'/0 '/0

BIP84 (P2WPKH): m/84 '/0'/0 '/0

BIP86 (P2TR): M/86 '/0'/0 '/0

This could be the path in their derivations.

Taking as an example Bech32

Code:
import hashlib
import bip32utils

def sha256(data):
    return hashlib.sha256(data).digest()

def ripemd160(data):
    h = hashlib.new('ripemd160')
    h.update(data)
    return h.digest()

def bech32_polymod(values):
    generator = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3]
    chk = 1
    for v in values:
        b = (chk >> 25)
        chk = (chk & 0x1ffffff) << 5 ^ v
        for i in range(5):
            chk ^= generator[i] if ((b >> i) & 1) else 0
    return chk

def bech_expand(hrp):
    return [ord(x) >> 5 for x in hrp] + [0] + [ord(x) & 31 for x in hrp]

def bech_checksum(hrp, data):
    values = bech_expand(hrp) + data
    polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ 1
    return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)]

def bech32_encode(hrp, data):
    combined = data + bech_checksum(hrp, data)
    BECH_CHRS = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l'
    return hrp + '1' + ''.join([BECH_CHRS[d] for d in combined])

def cbits(data, frombits, tobits, pad=True):
    acc = 0
    bits = 0
    ret = []
    maxv = (1 << tobits) - 1
    for value in data:
        if value < 0 or (value >> frombits):
            raise ValueError("Invalid value")
        acc = (acc << frombits) | value
        bits += frombits
        while bits >= tobits:
            bits -= tobits
            ret.append((acc >> bits) & maxv)
    if pad:
        if bits:
            ret.append((acc << (tobits - bits)) & maxv)
    elif bits >= frombits or ((acc << (tobits - bits)) & maxv):
        raise ValueError("Invalid bits")
    return ret

def bech_address(pubkey):
    sha256_r = sha256(pubkey)
    ripemdr = ripemd160(sha256_r)
    data = cbits(ripemdr, 8, 5)
    data = [0] + data
    hrp = 'bc'  # for MainNet
    address = bech32_encode(hrp, data)
    return address

xprv = "XPRV here"
bip32_root_key_obj = bip32utils.BIP32Key.fromExtendedKey(xprv)


with open("derived_addresses.txt", "w") as file:

    # Derive keys using the path m/0'/0'/0'
    for i in range(1001):
        derived_key = bip32_root_key_obj.ChildKey(0 + 0x80000000).ChildKey(0 + 0x80000000).ChildKey(i + 0x80000000)
        priv_key = derived_key.WalletImportFormat()
        pubkey = derived_key.PublicKey().hex()
        pubkey_bytes = bytes.fromhex(pubkey)
        bech32_address = bech_address(pubkey_bytes)
        file.write(f"Private Key: {priv_key}\nPublic Key: {pubkey}\nSegWit (Bech32) Address: {bech32_address}\n\n")

    # Derive keys using the path m/0'/1'/0'
    for z in range(1001):
        derived_key = bip32_root_key_obj.ChildKey(0 + 0x80000000).ChildKey(1 + 0x80000000).ChildKey(z + 0x80000000)
        priv_key = derived_key.WalletImportFormat()
        pubkey = derived_key.PublicKey().hex()
        pubkey_bytes = bytes.fromhex(pubkey)
        bech32_address = bech_address(pubkey_bytes)
        file.write(f"Private Key: {priv_key}\nPublic Key: {pubkey}\nSegWit (Bech32) Address: {bech32_address}\n\n")

    # Derive keys using the path m/84'/2'/0'
    for x in range(1001):
        derived_key = bip32_root_key_obj.ChildKey(84 + 0x80000000).ChildKey(2 + 0x80000000).ChildKey(x + 0x80000000)
        priv_key = derived_key.WalletImportFormat()
        pubkey = derived_key.PublicKey().hex()
        pubkey_bytes = bytes.fromhex(pubkey)
        bech32_address = bech_address(pubkey_bytes)
        file.write(f"Private Key: {priv_key}\nPublic Key: {pubkey}\nSegWit (Bech32) Address: {bech32_address}\n\n")

print("Derivation completed. The results are saved in 'derived_addresses.txt'.")