I wonder if keys were generated by some deterministic wallet first, and then truncated to N bits. Because in that case, it could be possible to recover the master key, and then sweep coins from all of them, while it would not mean that ECDSA is broken (because HD keys could be non-hardened).
Interesting puzzle, I checked for patterns between binary values, decimal values, floor values. Just cant find anything
I updated an excel sheet puzzle bitcoin.xlsx with allot more data of each puzzle. Like decimal, binary, floor, and allot more data per puzzle. Even multipliers of the data to the next puzzle.
Since this range is just so huge, I think a random generator would maybe work best to try and find the needle.
I attached below my python script trying the next puzzle randomly if someone might benefit to
https://github.com/negate7o4/Bitcoin-PuzzleOn my rig, I7 if I run 5 X instances, it checks about 11 500 possibilities per second per thread, but eats 80% cpu. So the code chews threw 16.5 Mil random possibilities per day
If you want to try a different puzzle, just change these values in the script :
address = '1FeexV6bAHb8ybZjqQMjJrcCrHGW9sb6uF'
start_key = '0000000000000000000000000000000000000000000000040000000000000000' stop_key = '000000000000000000000000000000000000000000000007ffffffffffffffff'
Also take note of the cpu threads the code uses, update according to your threads.
Their is also a text file in my repository of the correct pip's you need to install for the code to work
We can utilize multiprocessing instead of threading. Multiprocessing allows us to take advantage of multiple CPU cores and achieve better parallelism. Also, we can optimize the search_for_key function by reducing unnecessary calculations within the loop. There is a potential bottleneck that can be accelerated. The bottleneck lies in the line where a random integer is generated using os.urandom(32). We can generate a batch of random numbers in advance and use these numbers in the search_for_key function instead of generating a new random number for each iteration.
import os
import multiprocessing as mp
from gmpy2 import mpz, powmod
from bitcoinlib.encoding import addr_to_pubkeyhash, to_hexstring
from bitcoinlib.keys import HDKey
from ecdsa import SigningKey, SECP256k1
def save_key_to_file(private_hex: str):
with open(f"{private_hex}.txt", "w") as f:
f.write(private_hex)
def generate_random_numbers(num_numbers):
return [os.urandom(32) for _ in range(num_numbers)]
def search_for_key(start_key_int, stop_key_int, target_address, attempts_per_process, random_numbers):
for i in range(attempts_per_process):
current_key_int = mpz(powmod(int.from_bytes(random_numbers[i], 'big'), 1, stop_key_int - start_key_int)) + start_key_int
ecdsa_private_key = SigningKey.from_secret_exponent(int(current_key_int), curve=SECP256k1)
key = HDKey(key=ecdsa_private_key.to_string())
if key.address() == target_address:
save_key_to_file(key.private_hex)
print(f"Private key found: {key.private_hex}")
return key
return None
def search_in_range(start_key_int, stop_key_int, target_address, attempts_per_process, random_numbers):
process_start_key_int = mpz(powmod(int.from_bytes(random_numbers[0], 'big'), 1, stop_key_int - start_key_int)) + start_key_int
process_stop_key_int = (process_start_key_int + attempts_per_process) % stop_key_int
search_for_key(process_start_key_int, process_stop_key_int, target_address, attempts_per_process, random_numbers)
if __name__ == "__main__":
address = '1FeexV6bAHb8ybZjqQMjJrcCrHGW9sb6uF'
start_key = '0000000000000000000000000000000000000000000000040000000000000000'
stop_key = '000000000000000000000000000000000000000000000007ffffffffffffffff'
start_key_int = mpz(start_key, 16)
stop_key_int = mpz(stop_key, 16)
attempts_per_process = 2000000
num_processes = 8
random_numbers = generate_random_numbers(attempts_per_process * num_processes)
processes = []
for _ in range(num_processes):
process = mp.Process(target=search_in_range, args=(start_key_int, stop_key_int, address, attempts_per_process, random_numbers))
processes.append(process)
process.start()
for process in processes:
process.join()
print(f"Private key not found in the given range after {num_processes * attempts_per_process} attempts.")
But no matter how you turn it and perfect it, it takes a couple of million years to reach the result.