Denevron
Newbie
Offline
Activity: 121
Merit: 0
|
 |
March 30, 2025, 04:25:31 PM |
|
can be called a mutagen  It's not that simple, but it speeds up the process, you've noticed it yourself) you can add it to Cyclon as a new method, and there you just don’t calculate the puzzle range, but enter the key by which the bits will change, and it’s better not in random mode, but in sequential mode, because the random mode will loop and that’s it, and you will be forever, say, chasing in 30 bits, and you won’t find it, and it will be, say, in 33 bits import time import multiprocessing import secp256k1 as ice import random from math import comb import numpy as np
# Configuration TARGET_ADDR = "1HsMJxNiV7TLxmoF6uJNkydxPFDog4NQum" # Puzzle 20 BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f" # Puzzle 19 Private Key PUZZLE_NUM = 20 WORKERS = multiprocessing.cpu_count()
# Historical flip counts FLIP_TABLE = { 20:8, 21:8, 22:9, 23:9, 24:10, 25:11, 26:12, 27:13, 28:14, 29:15, 30:16, 31:17, 32:18, 33:19, 34:20, 35:21, 36:22, 37:23, 38:24, 39:25, 40:26, 41:27, 42:28, 43:29, 44:30, 45:31, 46:32, 47:33, 48:34, 49:35, 50:36, 51:37, 52:38, 53:39, 54:40, 55:41, 56:42, 57:43, 58:44, 59:45, 60:46, 61:47, 62:48, 63:49, 64:50, 65:51, 66:52, 67:53 }
def predict_flips(puzzle_num): """Predict flip count using linear regression with bounds""" if puzzle_num in FLIP_TABLE: return FLIP_TABLE[puzzle_num] # Linear regression x = np.array(list(FLIP_TABLE.keys())) y = np.array(list(FLIP_TABLE.values())) coeffs = np.polyfit(x, y, 1) predicted = round(coeffs[0] * puzzle_num + coeffs[1]) # Apply bounds (50-60% of bits) bit_length = puzzle_num lower = max(8, int(bit_length * 0.5)) upper = min(int(bit_length * 0.6), bit_length-5) return min(max(predicted, lower), upper)
def mutate_key(base_int, flip_positions): """Ultra-fast bit flipping using XOR mask""" flip_mask = sum(1 << bit for bit in flip_positions) return base_int ^ flip_mask
def worker(base_int, bit_length, flip_count, results, stop_event): checked = 0 bit_positions = list(range(bit_length)) start_time = time.time() while not stop_event.is_set(): # Generate random flip positions flip_pos = random.sample(bit_positions, flip_count) # Create mutated key priv_int = mutate_key(base_int, flip_pos) checked += 1 # Generate address addr = ice.privatekey_to_address(0, True, priv_int) if addr == TARGET_ADDR: hex_key = "%064x" % priv_int actual_flips = bin(base_int ^ priv_int).count('1') results.put((hex_key, checked, actual_flips)) stop_event.set() return # Progress update if checked % 10000 == 0: elapsed = time.time() - start_time speed = checked/elapsed if elapsed > 0 else 0 print(f"Checked {checked:,} | {speed:,.0f} keys/sec", end='\r')
def parallel_search(): bit_length = PUZZLE_NUM base_int = int(BASE_KEY, 16) flip_count = predict_flips(PUZZLE_NUM) total_combs = comb(bit_length, flip_count) print(f"\nSearching Puzzle {PUZZLE_NUM} (256-bit)") print(f"Base Key: {BASE_KEY}") print(f"Target: {TARGET_ADDR}") print(f"Predicted Flip Count: {flip_count} bits") print(f"Total Possible Combinations: 2^{int(np.log2(total_combs)):,}") print(f"Using {WORKERS} workers...\n") manager = multiprocessing.Manager() results = manager.Queue() stop_event = manager.Event() start_time = time.time() with multiprocessing.Pool(WORKERS) as pool: for _ in range(WORKERS): pool.apply_async(worker, (base_int, bit_length, flip_count, results, stop_event)) try: hex_key, checked, actual_flips = results.get(timeout=86400) # 24h timeout stop_event.set() elapsed = time.time() - start_time print(f"\nFound in {elapsed/3600:.2f} hours") print(f"Private Key: {hex_key}") print(f"Actual Bit Flips: {actual_flips}") print(f"Keys Checked: {checked:,}") print(f"Speed: {checked/elapsed:,.0f} keys/sec") solution_file = f"puzzle_{PUZZLE_NUM}_solution.txt" with open(solution_file, "w") as f: f.write(hex_key) print(f"\nSolution saved to {solution_file}") return hex_key except: print("\nKey not found in 24 hours - try adjusting flip count ±2") return None finally: pool.terminate()
if __name__ == "__main__": flip_count = predict_flips(PUZZLE_NUM) # First calculate flip_count print(f"Predicted flip count for {PUZZLE_NUM}: {flip_count} bits") solution = parallel_search() Here is my Python version. I still think this is useless. If someone convinces me otherwise.  you don't need to use random, so you won't find a match, only if you guess the number of bits  import time import multiprocessing import secp256k1 as ice from math import comb import numpy as np from itertools import combinations # For sequential flip generation
# Configuration TARGET_ADDR = "1HsMJxNiV7TLxmoF6uJNkydxPFDog4NQum" # Puzzle 20 BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f" # Puzzle 19 Private Key PUZZLE_NUM = 20 WORKERS = multiprocessing.cpu_count()
# Historical flip counts (unchanged) FLIP_TABLE = { 20:8, 21:8, 22:9, 23:9, 24:10, 25:11, 26:12, 27:13, 28:14, 29:15, 30:16, 31:17, 32:18, 33:19, 34:20, 35:21, 36:22, 37:23, 38:24, 39:25, 40:26, 41:27, 42:28, 43:29, 44:30, 45:31, 46:32, 47:33, 48:34, 49:35, 50:36, 51:37, 52:38, 53:39, 54:40, 55:41, 56:42, 57:43, 58:44, 59:45, 60:46, 61:47, 62:48, 63:49, 64:50, 65:51, 66:52, 67:53 }
def predict_flips(puzzle_num): """Predict flip count using linear regression with bounds (unchanged)""" if puzzle_num in FLIP_TABLE: return FLIP_TABLE[puzzle_num] # Linear regression x = np.array(list(FLIP_TABLE.keys())) y = np.array(list(FLIP_TABLE.values())) coeffs = np.polyfit(x, y, 1) predicted = round(coeffs[0] * puzzle_num + coeffs[1]) # Apply bounds (50-60% of bits) bit_length = puzzle_num lower = max(8, int(bit_length * 0.5)) upper = min(int(bit_length * 0.6), bit_length-5) return min(max(predicted, lower), upper)
def mutate_key(base_int, flip_positions): """Ultra-fast bit flipping using XOR mask (unchanged)""" flip_mask = sum(1 << bit for bit in flip_positions) return base_int ^ flip_mask
def worker(base_int, bit_length, flip_count, results, stop_event, start_index, end_index): """Modified worker for sequential search""" checked = 0 bit_positions = list(range(bit_length)) start_time = time.time()
# Generate all combinations in the assigned range all_combinations = combinations(bit_positions, flip_count) # Skip to the start index (for parallelization) for _ in range(start_index): next(all_combinations, None) # Iterate through combinations sequentially for flip_pos in all_combinations: if stop_event.is_set(): return if checked >= (end_index - start_index): return priv_int = mutate_key(base_int, flip_pos) checked += 1 # Generate address addr = ice.privatekey_to_address(0, True, priv_int) if addr == TARGET_ADDR: hex_key = "%064x" % priv_int actual_flips = bin(base_int ^ priv_int).count('1') results.put((hex_key, checked, actual_flips)) stop_event.set() return # Progress update if checked % 10000 == 0: elapsed = time.time() - start_time speed = checked/elapsed if elapsed > 0 else 0 print(f"Checked {checked:,} | {speed:,.0f} keys/sec", end='\r')
def parallel_search(): bit_length = PUZZLE_NUM base_int = int(BASE_KEY, 16) flip_count = predict_flips(PUZZLE_NUM) total_combs = comb(bit_length, flip_count) print(f"\nSearching Puzzle {PUZZLE_NUM} (256-bit)") print(f"Base Key: {BASE_KEY}") print(f"Target: {TARGET_ADDR}") print(f"Predicted Flip Count: {flip_count} bits") print(f"Total Possible Combinations: 2^{int(np.log2(total_combs)):,}") print(f"Using {WORKERS} workers...\n") manager = multiprocessing.Manager() results = manager.Queue() stop_event = manager.Event() start_time = time.time() # Split work into chunks for each worker chunk_size = total_combs // WORKERS ranges = [(i * chunk_size, (i + 1) * chunk_size) for i in range(WORKERS)] with multiprocessing.Pool(WORKERS) as pool: for start, end in ranges: pool.apply_async(worker, (base_int, bit_length, flip_count, results, stop_event, start, end)) try: hex_key, checked, actual_flips = results.get(timeout=86400) # 24h timeout stop_event.set() elapsed = time.time() - start_time print(f"\nFound in {elapsed/3600:.2f} hours") print(f"Private Key: {hex_key}") print(f"Actual Bit Flips: {actual_flips}") print(f"Keys Checked: {checked:,}") print(f"Speed: {checked/elapsed:,.0f} keys/sec") solution_file = f"puzzle_{PUZZLE_NUM}_solution.txt" with open(solution_file, "w") as f: f.write(hex_key) print(f"\nSolution saved to {solution_file}") return hex_key except: print("\nKey not found in 24 hours - try adjusting flip count ±2") return None finally: pool.terminate()
if __name__ == "__main__": flip_count = predict_flips(PUZZLE_NUM) print(f"Predicted flip count for {PUZZLE_NUM}: {flip_count} bits") solution = parallel_search() Here is the script. I don't see any difference here. To solve puzzle 68 you need impossible speed. 21 is not found! For 21 you need to put the key from the 20th puzzle, set hash160 from 21 and put 9 bits - then you will find) those bits that are in the nomachine example, this is just an example, this is not the exact number of bits that need to be changed) 
|
|
|
|
|
|
nomachine
|
 |
March 30, 2025, 05:33:17 PM |
|
Maybe someone will find my idea attractive and implement it, thereby speeding up finding solutions to puzzles!
Ok...Here is simplest starting code for this. sudo apt update && sudo apt upgrade -y && sudo apt install -y build-essential libssl-dev libboost-all-dev openssl libsecp256k1-dev git cmake mutagen.cpp #include <iostream> #include <iomanip> #include <sstream> #include <vector> #include <thread> #include <atomic> #include <chrono> #include <queue> #include <mutex> #include <unordered_map> #include <cmath> #include <fstream> #include <openssl/ec.h> #include <openssl/sha.h> #include <openssl/ripemd.h> #include <openssl/bn.h> #include <openssl/obj_mac.h> #include <openssl/evp.h>
using namespace std;
// Configuration const string TARGET_HASH160 = "b907c3a2a3b27789dfb509b730dd47703c272868"; const string BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f"; const int PUZZLE_NUM = 20; const int WORKERS = thread::hardware_concurrency();
// Historical flip counts const unordered_map<int, int> FLIP_TABLE = { {20, 8}, {21, 9}, {22, 11}, {23, 12}, {24, 9}, {25, 12}, {26, 14}, {27, 13}, {28, 16}, {29, 18}, {30, 16}, {31, 13}, {32, 14}, {33, 15}, {34, 16}, {35, 19}, {36, 14}, {37, 23}, {38, 21}, {39, 23}, {40, 20}, {41, 25}, {42, 24}, {43, 19}, {44, 24}, {45, 21}, {46, 24}, {47, 27}, {48, 21}, {49, 30}, {50, 29}, {51, 25}, {52, 27}, {53, 26}, {54, 30}, {55, 31}, {56, 31}, {57, 33}, {58, 28}, {59, 30}, {60, 31}, {61, 25}, {62, 35}, {63, 34}, {64, 34}, {65, 37}, {66, 35}, {67, 31}, {68, 34} };
// Global variables atomic<bool> stop_event(false); mutex result_mutex; queue<tuple<string, size_t, int>> results;
// Predict flip count int predict_flips(int puzzle_num) { if (FLIP_TABLE.count(puzzle_num)) { return FLIP_TABLE.at(puzzle_num); }
vector<int> x, y; for (const auto& [key, value] : FLIP_TABLE) { x.push_back(key); y.push_back(value); }
double sum_x = 0, sum_y = 0, sum_xy = 0, sum_xx = 0; for (size_t i = 0; i < x.size(); ++i) { sum_x += x[i]; sum_y += y[i]; sum_xy += x[i] * y[i]; sum_xx += x[i] * x[i]; }
double slope = (x.size() * sum_xy - sum_x * sum_y) / (x.size() * sum_xx - sum_x * sum_x); double intercept = (sum_y - slope * sum_x) / x.size(); int predicted = round(slope * puzzle_num + intercept);
int bit_length = puzzle_num; int lower = max(8, static_cast<int>(bit_length * 0.5)); int upper = min(static_cast<int>(bit_length * 0.6), bit_length - 5); return min(max(predicted, lower), upper); }
// Binomial coefficient size_t combinations_count(int n, int k) { if (k > n) return 0; size_t result = 1; for (int i = 1; i <= k; ++i) { result *= (n - i + 1); result /= i; } return result; }
// Generate combinations vector<vector<int>> generate_combinations(int n, int k) { vector<vector<int>> combinations; vector<int> current(k, 0); for (int i = 0; i < k; ++i) current[i] = i;
while (true) { combinations.push_back(current);
int i = k - 1; while (i >= 0 && current[i] == n - k + i) --i; if (i < 0) break;
++current[i]; for (int j = i + 1; j < k; ++j) current[j] = current[j - 1] + 1; } return combinations; }
// Mutate key uint64_t mutate_key(uint64_t base_int, const vector<int>& flip_positions) { uint64_t flip_mask = 0; for (int pos : flip_positions) flip_mask |= (1ULL << pos); return base_int ^ flip_mask; }
// Compute HASH160 string compute_hash160(EC_KEY* ec_key) { const EC_GROUP* group = EC_KEY_get0_group(ec_key); const EC_POINT* pub_key = EC_KEY_get0_public_key(ec_key);
if (!group || !pub_key) { cerr << "Invalid EC key components" << endl; return ""; }
size_t pub_key_len = EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_COMPRESSED, nullptr, 0, nullptr); if (pub_key_len == 0) { cerr << "Failed to get public key length" << endl; return ""; }
vector<unsigned char> pub_key_bytes(pub_key_len); if (!EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_COMPRESSED, pub_key_bytes.data(), pub_key_len, nullptr)) { cerr << "Failed to serialize public key" << endl; return ""; }
unsigned char sha256_result[SHA256_DIGEST_LENGTH]; SHA256(pub_key_bytes.data(), pub_key_bytes.size(), sha256_result);
unsigned char ripemd160_result[RIPEMD160_DIGEST_LENGTH]; RIPEMD160(sha256_result, SHA256_DIGEST_LENGTH, ripemd160_result);
stringstream ss; for (int i = 0; i < RIPEMD160_DIGEST_LENGTH; ++i) { ss << hex << setw(2) << setfill('0') << static_cast<int>(ripemd160_result[i]); } return ss.str(); }
// Worker function void worker(uint64_t base_int, int bit_length, int flip_count, size_t start_index, size_t end_index) { size_t checked = 0; auto combinations = generate_combinations(bit_length, flip_count);
EC_KEY* ec_key = EC_KEY_new(); if (!ec_key) { cerr << "Failed to create EC_KEY" << endl; return; }
EC_GROUP* ec_group = EC_GROUP_new_by_curve_name(NID_secp256k1); if (!ec_group) { cerr << "Failed to create EC_GROUP (secp256k1 not available?)" << endl; EC_KEY_free(ec_key); return; }
if (!EC_KEY_set_group(ec_key, ec_group)) { cerr << "Failed to set EC group" << endl; EC_GROUP_free(ec_group); EC_KEY_free(ec_key); return; }
for (size_t i = start_index; i < end_index && i < combinations.size(); ++i) { if (stop_event.load()) break;
const auto& flip_pos = combinations[i]; uint64_t priv_int = mutate_key(base_int, flip_pos); ++checked;
BIGNUM* bn_priv = BN_new(); if (!bn_priv) { cerr << "Failed to create BIGNUM" << endl; continue; }
if (!BN_set_word(bn_priv, priv_int)) { cerr << "Failed to set private key value" << endl; BN_free(bn_priv); continue; }
if (!EC_KEY_set_private_key(ec_key, bn_priv)) { cerr << "Failed to set private key" << endl; BN_free(bn_priv); continue; }
EC_POINT* pub_key = EC_POINT_new(ec_group); if (!pub_key) { BN_free(bn_priv); continue; }
if (!EC_POINT_mul(ec_group, pub_key, bn_priv, nullptr, nullptr, nullptr)) { EC_POINT_free(pub_key); BN_free(bn_priv); continue; }
if (!EC_KEY_set_public_key(ec_key, pub_key)) { EC_POINT_free(pub_key); BN_free(bn_priv); continue; }
string hash160 = compute_hash160(ec_key); EC_POINT_free(pub_key); BN_free(bn_priv);
if (hash160.empty()) { continue; }
if (hash160 == TARGET_HASH160) { lock_guard<mutex> lock(result_mutex); results.push(make_tuple(to_string(priv_int), checked, flip_count)); stop_event.store(true); break; }
if (checked % 10000 == 0) { cout << "Checked " << checked << "\r"; cout.flush(); } }
EC_GROUP_free(ec_group); EC_KEY_free(ec_key); }
// Parallel search void parallel_search() { int bit_length = PUZZLE_NUM; uint64_t base_int = stoull(BASE_KEY, nullptr, 16); int flip_count = predict_flips(PUZZLE_NUM); size_t total_combs = combinations_count(bit_length, flip_count);
cout << "Searching Puzzle " << PUZZLE_NUM << " (256-bit)" << endl; cout << "Base Key: " << BASE_KEY << endl; cout << "Target HASH160: " << TARGET_HASH160 << endl; cout << "Predicted Flip Count: " << flip_count << " bits" << endl; cout << "Total Possible Combinations: " << total_combs << endl; cout << "Using " << WORKERS << " workers..." << endl;
vector<thread> threads; size_t chunk_size = total_combs / WORKERS;
auto start_time = chrono::high_resolution_clock::now();
for (int i = 0; i < WORKERS; ++i) { size_t start_index = i * chunk_size; size_t end_index = (i == WORKERS - 1) ? total_combs : (i + 1) * chunk_size; threads.emplace_back(worker, base_int, bit_length, flip_count, start_index, end_index); }
for (auto& t : threads) t.join();
if (!results.empty()) { auto [hex_key, checked, actual_flips] = results.front(); auto elapsed = chrono::duration_cast<chrono::seconds>(chrono::high_resolution_clock::now() - start_time).count();
cout << "\nFound in " << elapsed / 3600.0 << " hours" << endl; cout << "Private Key: " << hex_key << endl; cout << "Actual Bit Flips: " << actual_flips << endl; cout << "Keys Checked: " << checked << endl; cout << "Speed: " << checked / static_cast<double>(elapsed) << " keys/sec" << endl;
ofstream solution_file("puzzle_" + to_string(PUZZLE_NUM) + "_solution.txt"); solution_file << hex_key; cout << "\nSolution saved to puzzle_" << PUZZLE_NUM << "_solution.txt" << endl; } else { cout << "\nKey not found. Try adjusting flip count ±2" << endl; } }
int main() { // Initialize OpenSSL (modern versions don't need this, but we'll include it for compatibility) #if OPENSSL_VERSION_NUMBER < 0x10100000L OpenSSL_add_all_algorithms(); #endif
int flip_count = predict_flips(PUZZLE_NUM); cout << "Predicted flip count for " << PUZZLE_NUM << ": " << flip_count << " bits" << endl; parallel_search();
// Clean up OpenSSL (only needed for older versions) #if OPENSSL_VERSION_NUMBER < 0x10100000L EVP_cleanup(); #endif return 0; } g++ -O3 -march=native -std=c++17 mutagen.cpp -lssl -lcrypto -lpthread -o mutagen # ./mutagen Predicted flip count for 20: 8 bits Searching Puzzle 20 (256-bit) Base Key: 000000000000000000000000000000000000000000000000000000000005749f Target HASH160: b907c3a2a3b27789dfb509b730dd47703c272868 Predicted Flip Count: 8 bits Total Possible Combinations: 125970 Using 12 workers...
Found in 0.000833333 hours Private Key: 863317 Actual Bit Flips: 8 Keys Checked: 5167 Speed: 1722.33 keys/sec
Solution saved to puzzle_20_solution.txt
If you want better, you have to do everything yourself from here. 
|
BTC: bc1qdwnxr7s08xwelpjy3cc52rrxg63xsmagv50fa8
|
|
|
Denevron
Newbie
Offline
Activity: 121
Merit: 0
|
 |
March 30, 2025, 05:44:01 PM |
|
Maybe someone will find my idea attractive and implement it, thereby speeding up finding solutions to puzzles!
Ok...Here is simplest starting code for this. sudo apt update && sudo apt upgrade -y && sudo apt install -y build-essential libssl-dev libboost-all-dev openssl libsecp256k1-dev git cmake mutagen.cpp #include <iostream> #include <iomanip> #include <sstream> #include <vector> #include <thread> #include <atomic> #include <chrono> #include <queue> #include <mutex> #include <unordered_map> #include <cmath> #include <fstream> #include <openssl/ec.h> #include <openssl/sha.h> #include <openssl/ripemd.h> #include <openssl/bn.h> #include <openssl/obj_mac.h> #include <openssl/evp.h>
using namespace std;
// Configuration const string TARGET_HASH160 = "b907c3a2a3b27789dfb509b730dd47703c272868"; const string BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f"; const int PUZZLE_NUM = 20; const int WORKERS = thread::hardware_concurrency();
// Historical flip counts const unordered_map<int, int> FLIP_TABLE = { {20, 8}, {21, 9}, {22, 11}, {23, 12}, {24, 9}, {25, 12}, {26, 14}, {27, 13}, {28, 16}, {29, 18}, {30, 16}, {31, 13}, {32, 14}, {33, 15}, {34, 16}, {35, 19}, {36, 14}, {37, 23}, {38, 21}, {39, 23}, {40, 20}, {41, 25}, {42, 24}, {43, 19}, {44, 24}, {45, 21}, {46, 24}, {47, 27}, {48, 21}, {49, 30}, {50, 29}, {51, 25}, {52, 27}, {53, 26}, {54, 30}, {55, 31}, {56, 31}, {57, 33}, {58, 28}, {59, 30}, {60, 31}, {61, 25}, {62, 35}, {63, 34}, {64, 34}, {65, 37}, {66, 35}, {67, 31}, {68, 34} };
// Global variables atomic<bool> stop_event(false); mutex result_mutex; queue<tuple<string, size_t, int>> results;
// Predict flip count int predict_flips(int puzzle_num) { if (FLIP_TABLE.count(puzzle_num)) { return FLIP_TABLE.at(puzzle_num); }
vector<int> x, y; for (const auto& [key, value] : FLIP_TABLE) { x.push_back(key); y.push_back(value); }
double sum_x = 0, sum_y = 0, sum_xy = 0, sum_xx = 0; for (size_t i = 0; i < x.size(); ++i) { sum_x += x[i]; sum_y += y[i]; sum_xy += x[i] * y[i]; sum_xx += x[i] * x[i]; }
double slope = (x.size() * sum_xy - sum_x * sum_y) / (x.size() * sum_xx - sum_x * sum_x); double intercept = (sum_y - slope * sum_x) / x.size(); int predicted = round(slope * puzzle_num + intercept);
int bit_length = puzzle_num; int lower = max(8, static_cast<int>(bit_length * 0.5)); int upper = min(static_cast<int>(bit_length * 0.6), bit_length - 5); return min(max(predicted, lower), upper); }
// Binomial coefficient size_t combinations_count(int n, int k) { if (k > n) return 0; size_t result = 1; for (int i = 1; i <= k; ++i) { result *= (n - i + 1); result /= i; } return result; }
// Generate combinations vector<vector<int>> generate_combinations(int n, int k) { vector<vector<int>> combinations; vector<int> current(k, 0); for (int i = 0; i < k; ++i) current[i] = i;
while (true) { combinations.push_back(current);
int i = k - 1; while (i >= 0 && current[i] == n - k + i) --i; if (i < 0) break;
++current[i]; for (int j = i + 1; j < k; ++j) current[j] = current[j - 1] + 1; } return combinations; }
// Mutate key uint64_t mutate_key(uint64_t base_int, const vector<int>& flip_positions) { uint64_t flip_mask = 0; for (int pos : flip_positions) flip_mask |= (1ULL << pos); return base_int ^ flip_mask; }
// Compute HASH160 string compute_hash160(EC_KEY* ec_key) { const EC_GROUP* group = EC_KEY_get0_group(ec_key); const EC_POINT* pub_key = EC_KEY_get0_public_key(ec_key);
if (!group || !pub_key) { cerr << "Invalid EC key components" << endl; return ""; }
size_t pub_key_len = EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_COMPRESSED, nullptr, 0, nullptr); if (pub_key_len == 0) { cerr << "Failed to get public key length" << endl; return ""; }
vector<unsigned char> pub_key_bytes(pub_key_len); if (!EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_COMPRESSED, pub_key_bytes.data(), pub_key_len, nullptr)) { cerr << "Failed to serialize public key" << endl; return ""; }
unsigned char sha256_result[SHA256_DIGEST_LENGTH]; SHA256(pub_key_bytes.data(), pub_key_bytes.size(), sha256_result);
unsigned char ripemd160_result[RIPEMD160_DIGEST_LENGTH]; RIPEMD160(sha256_result, SHA256_DIGEST_LENGTH, ripemd160_result);
stringstream ss; for (int i = 0; i < RIPEMD160_DIGEST_LENGTH; ++i) { ss << hex << setw(2) << setfill('0') << static_cast<int>(ripemd160_result[i]); } return ss.str(); }
// Worker function void worker(uint64_t base_int, int bit_length, int flip_count, size_t start_index, size_t end_index) { size_t checked = 0; auto combinations = generate_combinations(bit_length, flip_count);
EC_KEY* ec_key = EC_KEY_new(); if (!ec_key) { cerr << "Failed to create EC_KEY" << endl; return; }
EC_GROUP* ec_group = EC_GROUP_new_by_curve_name(NID_secp256k1); if (!ec_group) { cerr << "Failed to create EC_GROUP (secp256k1 not available?)" << endl; EC_KEY_free(ec_key); return; }
if (!EC_KEY_set_group(ec_key, ec_group)) { cerr << "Failed to set EC group" << endl; EC_GROUP_free(ec_group); EC_KEY_free(ec_key); return; }
for (size_t i = start_index; i < end_index && i < combinations.size(); ++i) { if (stop_event.load()) break;
const auto& flip_pos = combinations[i]; uint64_t priv_int = mutate_key(base_int, flip_pos); ++checked;
BIGNUM* bn_priv = BN_new(); if (!bn_priv) { cerr << "Failed to create BIGNUM" << endl; continue; }
if (!BN_set_word(bn_priv, priv_int)) { cerr << "Failed to set private key value" << endl; BN_free(bn_priv); continue; }
if (!EC_KEY_set_private_key(ec_key, bn_priv)) { cerr << "Failed to set private key" << endl; BN_free(bn_priv); continue; }
EC_POINT* pub_key = EC_POINT_new(ec_group); if (!pub_key) { BN_free(bn_priv); continue; }
if (!EC_POINT_mul(ec_group, pub_key, bn_priv, nullptr, nullptr, nullptr)) { EC_POINT_free(pub_key); BN_free(bn_priv); continue; }
if (!EC_KEY_set_public_key(ec_key, pub_key)) { EC_POINT_free(pub_key); BN_free(bn_priv); continue; }
string hash160 = compute_hash160(ec_key); EC_POINT_free(pub_key); BN_free(bn_priv);
if (hash160.empty()) { continue; }
if (hash160 == TARGET_HASH160) { lock_guard<mutex> lock(result_mutex); results.push(make_tuple(to_string(priv_int), checked, flip_count)); stop_event.store(true); break; }
if (checked % 10000 == 0) { cout << "Checked " << checked << "\r"; cout.flush(); } }
EC_GROUP_free(ec_group); EC_KEY_free(ec_key); }
// Parallel search void parallel_search() { int bit_length = PUZZLE_NUM; uint64_t base_int = stoull(BASE_KEY, nullptr, 16); int flip_count = predict_flips(PUZZLE_NUM); size_t total_combs = combinations_count(bit_length, flip_count);
cout << "Searching Puzzle " << PUZZLE_NUM << " (256-bit)" << endl; cout << "Base Key: " << BASE_KEY << endl; cout << "Target HASH160: " << TARGET_HASH160 << endl; cout << "Predicted Flip Count: " << flip_count << " bits" << endl; cout << "Total Possible Combinations: " << total_combs << endl; cout << "Using " << WORKERS << " workers..." << endl;
vector<thread> threads; size_t chunk_size = total_combs / WORKERS;
auto start_time = chrono::high_resolution_clock::now();
for (int i = 0; i < WORKERS; ++i) { size_t start_index = i * chunk_size; size_t end_index = (i == WORKERS - 1) ? total_combs : (i + 1) * chunk_size; threads.emplace_back(worker, base_int, bit_length, flip_count, start_index, end_index); }
for (auto& t : threads) t.join();
if (!results.empty()) { auto [hex_key, checked, actual_flips] = results.front(); auto elapsed = chrono::duration_cast<chrono::seconds>(chrono::high_resolution_clock::now() - start_time).count();
cout << "\nFound in " << elapsed / 3600.0 << " hours" << endl; cout << "Private Key: " << hex_key << endl; cout << "Actual Bit Flips: " << actual_flips << endl; cout << "Keys Checked: " << checked << endl; cout << "Speed: " << checked / static_cast<double>(elapsed) << " keys/sec" << endl;
ofstream solution_file("puzzle_" + to_string(PUZZLE_NUM) + "_solution.txt"); solution_file << hex_key; cout << "\nSolution saved to puzzle_" << PUZZLE_NUM << "_solution.txt" << endl; } else { cout << "\nKey not found. Try adjusting flip count ±2" << endl; } }
int main() { // Initialize OpenSSL (modern versions don't need this, but we'll include it for compatibility) #if OPENSSL_VERSION_NUMBER < 0x10100000L OpenSSL_add_all_algorithms(); #endif
int flip_count = predict_flips(PUZZLE_NUM); cout << "Predicted flip count for " << PUZZLE_NUM << ": " << flip_count << " bits" << endl; parallel_search();
// Clean up OpenSSL (only needed for older versions) #if OPENSSL_VERSION_NUMBER < 0x10100000L EVP_cleanup(); #endif return 0; } g++ -O3 -march=native -std=c++17 mutagen.cpp -lssl -lcrypto -lpthread -o mutagen # ./mutagen Predicted flip count for 20: 8 bits Searching Puzzle 20 (256-bit) Base Key: 000000000000000000000000000000000000000000000000000000000005749f Target HASH160: b907c3a2a3b27789dfb509b730dd47703c272868 Predicted Flip Count: 8 bits Total Possible Combinations: 125970 Using 12 workers...
Found in 0.000833333 hours Private Key: 863317 Actual Bit Flips: 8 Keys Checked: 5167 Speed: 1722.33 keys/sec
Solution saved to puzzle_20_solution.txt
If you want better, you have to do everything yourself from here.  I understand that I need to do it myself, but still, thank you very much for the prototype)
|
|
|
|
|
|
nomachine
|
 |
March 30, 2025, 06:00:57 PM |
|
I understand that I need to do it myself, but still, thank you very much for the prototype)
256-bit version with BIGNUM: #include <iostream> #include <iomanip> #include <sstream> #include <vector> #include <thread> #include <atomic> #include <chrono> #include <queue> #include <mutex> #include <unordered_map> #include <cmath> #include <fstream> #include <openssl/ec.h> #include <openssl/sha.h> #include <openssl/ripemd.h> #include <openssl/bn.h> #include <openssl/obj_mac.h> #include <openssl/evp.h>
using namespace std;
// Configuration const string TARGET_HASH160 = "b907c3a2a3b27789dfb509b730dd47703c272868"; const string BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f"; const int PUZZLE_NUM = 20; const int WORKERS = thread::hardware_concurrency();
// Historical flip counts const unordered_map<int, int> FLIP_TABLE = { {20, 8}, {21, 9}, {22, 11}, {23, 12}, {24, 9}, {25, 12}, {26, 14}, {27, 13}, {28, 16}, {29, 18}, {30, 16}, {31, 13}, {32, 14}, {33, 15}, {34, 16}, {35, 19}, {36, 14}, {37, 23}, {38, 21}, {39, 23}, {40, 20}, {41, 25}, {42, 24}, {43, 19}, {44, 24}, {45, 21}, {46, 24}, {47, 27}, {48, 21}, {49, 30}, {50, 29}, {51, 25}, {52, 27}, {53, 26}, {54, 30}, {55, 31}, {56, 31}, {57, 33}, {58, 28}, {59, 30}, {60, 31}, {61, 25}, {62, 35}, {63, 34}, {64, 34}, {65, 37}, {66, 35}, {67, 31}, {68, 34} };
// Global variables atomic<bool> stop_event(false); mutex result_mutex; queue<tuple<string, size_t, int>> results;
// Predict flip count int predict_flips(int puzzle_num) { if (FLIP_TABLE.count(puzzle_num)) { return FLIP_TABLE.at(puzzle_num); } return 8; // Default }
// Binomial coefficient size_t combinations_count(int n, int k) { if (k > n) return 0; if (k * 2 > n) k = n - k; if (k == 0) return 1;
size_t result = n; for(int i = 2; i <= k; ++i) { result *= (n - i + 1); result /= i; } return result; }
// Generate combinations vector<vector<int>> generate_combinations(int n, int k) { vector<vector<int>> combinations; vector<int> current(k, 0); for (int i = 0; i < k; ++i) current[i] = i;
while (true) { combinations.push_back(current);
int i = k - 1; while (i >= 0 && current[i] == n - k + i) --i; if (i < 0) break;
++current[i]; for (int j = i + 1; j < k; ++j) current[j] = current[j - 1] + 1; } return combinations; }
// Convert BIGNUM to hex string string bn_to_hex(const BIGNUM* bn) { char* hex = BN_bn2hex(bn); string result(hex); OPENSSL_free(hex); return result; }
// XOR operation for BIGNUM void bn_xor(BIGNUM* result, const BIGNUM* a, const BIGNUM* b) { BIGNUM* tmp = BN_new(); BN_copy(result, a); for (int i = 0; i < max(BN_num_bits(a), BN_num_bits(b)); ++i) { if (BN_is_bit_set(a, i) != BN_is_bit_set(b, i)) { BN_set_bit(result, i); } else { BN_clear_bit(result, i); } } BN_free(tmp); }
// Compute HASH160 from BIGNUM private key string compute_hash160(const BIGNUM* priv_key) { EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_secp256k1); if (!ec_key) return "";
if (!EC_KEY_set_private_key(ec_key, priv_key)) { EC_KEY_free(ec_key); return ""; }
const EC_GROUP* group = EC_KEY_get0_group(ec_key); EC_POINT* pub_key = EC_POINT_new(group); if (!pub_key) { EC_KEY_free(ec_key); return ""; }
if (!EC_POINT_mul(group, pub_key, priv_key, nullptr, nullptr, nullptr)) { EC_POINT_free(pub_key); EC_KEY_free(ec_key); return ""; }
unsigned char pubkey[65]; int pubkey_len = EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_COMPRESSED, pubkey, sizeof(pubkey), nullptr); EC_POINT_free(pub_key); EC_KEY_free(ec_key);
if (pubkey_len != 33) return "";
unsigned char sha256[SHA256_DIGEST_LENGTH]; SHA256(pubkey, pubkey_len, sha256);
unsigned char ripemd160[RIPEMD160_DIGEST_LENGTH]; RIPEMD160(sha256, SHA256_DIGEST_LENGTH, ripemd160);
stringstream ss; for (int i = 0; i < RIPEMD160_DIGEST_LENGTH; ++i) { ss << hex << setw(2) << setfill('0') << (int)ripemd160[i]; } return ss.str(); }
// Worker function void worker(const BIGNUM* base_bn, int bit_length, int flip_count, size_t start_index, size_t end_index) { vector<vector<int>> combinations = generate_combinations(bit_length, flip_count); BIGNUM* current_bn = BN_new(); BIGNUM* flip_mask = BN_new();
for (size_t i = start_index; i < end_index && !stop_event.load(); ++i) { BN_zero(flip_mask); for (int pos : combinations[i]) { BN_set_bit(flip_mask, pos); } bn_xor(current_bn, base_bn, flip_mask);
string hash160 = compute_hash160(current_bn); if (hash160 == TARGET_HASH160) { string hex_key = bn_to_hex(current_bn); lock_guard<mutex> lock(result_mutex); results.push(make_tuple(hex_key, i+1, flip_count)); stop_event.store(true); break; }
if ((i+1) % 10000 == 0) { cout << "Checked " << (i+1) << " combinations\r"; cout.flush(); } }
BN_free(current_bn); BN_free(flip_mask); }
// Parallel search void parallel_search() { BIGNUM* base_bn = BN_new(); BN_hex2bn(&base_bn, BASE_KEY.c_str());
int flip_count = predict_flips(PUZZLE_NUM); size_t total_combs = combinations_count(PUZZLE_NUM, flip_count);
cout << "Searching Puzzle " << PUZZLE_NUM << " (256-bit)" << endl; cout << "Base Key: " << BASE_KEY << endl; cout << "Target HASH160: " << TARGET_HASH160 << endl; cout << "Predicted Flip Count: " << flip_count << " bits" << endl; cout << "Total Possible Combinations: " << total_combs << endl; cout << "Using " << WORKERS << " workers..." << endl;
vector<thread> threads; size_t chunk_size = total_combs / WORKERS; auto start_time = chrono::high_resolution_clock::now();
for (int i = 0; i < WORKERS; ++i) { size_t start = i * chunk_size; size_t end = (i == WORKERS-1) ? total_combs : start + chunk_size; threads.emplace_back(worker, base_bn, PUZZLE_NUM, flip_count, start, end); }
for (auto& t : threads) t.join(); BN_free(base_bn);
if (!results.empty()) { auto [hex_key, checked, flips] = results.front(); auto elapsed = chrono::duration_cast<chrono::seconds>( chrono::high_resolution_clock::now() - start_time).count();
cout << "\nFound solution!" << endl; cout << "Private Key: " << hex_key << endl; cout << "Bit Flips: " << flips << endl; cout << "Checked " << checked << " combinations in " << elapsed << " seconds (" << (checked/elapsed) << " keys/sec)" << endl;
ofstream out("solution.txt"); out << hex_key; out.close(); } else { cout << "\nSolution not found. Try adjusting flip count." << endl; } }
int main() { #if OPENSSL_VERSION_NUMBER < 0x10100000L OpenSSL_add_all_algorithms(); #endif
parallel_search();
#if OPENSSL_VERSION_NUMBER < 0x10100000L EVP_cleanup(); #endif
return 0; } # ./mutagen Searching Puzzle 68 (256-bit) Base Key: 00000000000000000000000000000000000000000000000730fc235c1942c1ae Target HASH160: e0b8a2baee1b77fc703455f39d51477451fc8cfc Predicted Flip Count: 34 bits Total Possible Combinations: 47478523248093572 Using 12 workers...
Good luck searching through 47 quadrillion combinations. 
|
BTC: bc1qdwnxr7s08xwelpjy3cc52rrxg63xsmagv50fa8
|
|
|
Denevron
Newbie
Offline
Activity: 121
Merit: 0
|
 |
March 30, 2025, 06:07:36 PM |
|
I understand that I need to do it myself, but still, thank you very much for the prototype)
256-bit version with BIGNUM: #include <iostream> #include <iomanip> #include <sstream> #include <vector> #include <thread> #include <atomic> #include <chrono> #include <queue> #include <mutex> #include <unordered_map> #include <cmath> #include <fstream> #include <openssl/ec.h> #include <openssl/sha.h> #include <openssl/ripemd.h> #include <openssl/bn.h> #include <openssl/obj_mac.h> #include <openssl/evp.h>
using namespace std;
// Configuration const string TARGET_HASH160 = "b907c3a2a3b27789dfb509b730dd47703c272868"; const string BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f"; const int PUZZLE_NUM = 20; const int WORKERS = thread::hardware_concurrency();
// Historical flip counts const unordered_map<int, int> FLIP_TABLE = { {20, 8}, {21, 9}, {22, 11}, {23, 12}, {24, 9}, {25, 12}, {26, 14}, {27, 13}, {28, 16}, {29, 18}, {30, 16}, {31, 13}, {32, 14}, {33, 15}, {34, 16}, {35, 19}, {36, 14}, {37, 23}, {38, 21}, {39, 23}, {40, 20}, {41, 25}, {42, 24}, {43, 19}, {44, 24}, {45, 21}, {46, 24}, {47, 27}, {48, 21}, {49, 30}, {50, 29}, {51, 25}, {52, 27}, {53, 26}, {54, 30}, {55, 31}, {56, 31}, {57, 33}, {58, 28}, {59, 30}, {60, 31}, {61, 25}, {62, 35}, {63, 34}, {64, 34}, {65, 37}, {66, 35}, {67, 31}, {68, 34} };
// Global variables atomic<bool> stop_event(false); mutex result_mutex; queue<tuple<string, size_t, int>> results;
// Predict flip count int predict_flips(int puzzle_num) { if (FLIP_TABLE.count(puzzle_num)) { return FLIP_TABLE.at(puzzle_num); } return 8; // Default }
// Binomial coefficient size_t combinations_count(int n, int k) { if (k > n) return 0; if (k * 2 > n) k = n - k; if (k == 0) return 1;
size_t result = n; for(int i = 2; i <= k; ++i) { result *= (n - i + 1); result /= i; } return result; }
// Generate combinations vector<vector<int>> generate_combinations(int n, int k) { vector<vector<int>> combinations; vector<int> current(k, 0); for (int i = 0; i < k; ++i) current[i] = i;
while (true) { combinations.push_back(current);
int i = k - 1; while (i >= 0 && current[i] == n - k + i) --i; if (i < 0) break;
++current[i]; for (int j = i + 1; j < k; ++j) current[j] = current[j - 1] + 1; } return combinations; }
// Convert BIGNUM to hex string string bn_to_hex(const BIGNUM* bn) { char* hex = BN_bn2hex(bn); string result(hex); OPENSSL_free(hex); return result; }
// XOR operation for BIGNUM void bn_xor(BIGNUM* result, const BIGNUM* a, const BIGNUM* b) { BIGNUM* tmp = BN_new(); BN_copy(result, a); for (int i = 0; i < max(BN_num_bits(a), BN_num_bits(b)); ++i) { if (BN_is_bit_set(a, i) != BN_is_bit_set(b, i)) { BN_set_bit(result, i); } else { BN_clear_bit(result, i); } } BN_free(tmp); }
// Compute HASH160 from BIGNUM private key string compute_hash160(const BIGNUM* priv_key) { EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_secp256k1); if (!ec_key) return "";
if (!EC_KEY_set_private_key(ec_key, priv_key)) { EC_KEY_free(ec_key); return ""; }
const EC_GROUP* group = EC_KEY_get0_group(ec_key); EC_POINT* pub_key = EC_POINT_new(group); if (!pub_key) { EC_KEY_free(ec_key); return ""; }
if (!EC_POINT_mul(group, pub_key, priv_key, nullptr, nullptr, nullptr)) { EC_POINT_free(pub_key); EC_KEY_free(ec_key); return ""; }
unsigned char pubkey[65]; int pubkey_len = EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_COMPRESSED, pubkey, sizeof(pubkey), nullptr); EC_POINT_free(pub_key); EC_KEY_free(ec_key);
if (pubkey_len != 33) return "";
unsigned char sha256[SHA256_DIGEST_LENGTH]; SHA256(pubkey, pubkey_len, sha256);
unsigned char ripemd160[RIPEMD160_DIGEST_LENGTH]; RIPEMD160(sha256, SHA256_DIGEST_LENGTH, ripemd160);
stringstream ss; for (int i = 0; i < RIPEMD160_DIGEST_LENGTH; ++i) { ss << hex << setw(2) << setfill('0') << (int)ripemd160[i]; } return ss.str(); }
// Worker function void worker(const BIGNUM* base_bn, int bit_length, int flip_count, size_t start_index, size_t end_index) { vector<vector<int>> combinations = generate_combinations(bit_length, flip_count); BIGNUM* current_bn = BN_new(); BIGNUM* flip_mask = BN_new();
for (size_t i = start_index; i < end_index && !stop_event.load(); ++i) { BN_zero(flip_mask); for (int pos : combinations[i]) { BN_set_bit(flip_mask, pos); } bn_xor(current_bn, base_bn, flip_mask);
string hash160 = compute_hash160(current_bn); if (hash160 == TARGET_HASH160) { string hex_key = bn_to_hex(current_bn); lock_guard<mutex> lock(result_mutex); results.push(make_tuple(hex_key, i+1, flip_count)); stop_event.store(true); break; }
if ((i+1) % 10000 == 0) { cout << "Checked " << (i+1) << " combinations\r"; cout.flush(); } }
BN_free(current_bn); BN_free(flip_mask); }
// Parallel search void parallel_search() { BIGNUM* base_bn = BN_new(); BN_hex2bn(&base_bn, BASE_KEY.c_str());
int flip_count = predict_flips(PUZZLE_NUM); size_t total_combs = combinations_count(PUZZLE_NUM, flip_count);
cout << "Searching Puzzle " << PUZZLE_NUM << " (256-bit)" << endl; cout << "Base Key: " << BASE_KEY << endl; cout << "Target HASH160: " << TARGET_HASH160 << endl; cout << "Predicted Flip Count: " << flip_count << " bits" << endl; cout << "Total Possible Combinations: " << total_combs << endl; cout << "Using " << WORKERS << " workers..." << endl;
vector<thread> threads; size_t chunk_size = total_combs / WORKERS; auto start_time = chrono::high_resolution_clock::now();
for (int i = 0; i < WORKERS; ++i) { size_t start = i * chunk_size; size_t end = (i == WORKERS-1) ? total_combs : start + chunk_size; threads.emplace_back(worker, base_bn, PUZZLE_NUM, flip_count, start, end); }
for (auto& t : threads) t.join(); BN_free(base_bn);
if (!results.empty()) { auto [hex_key, checked, flips] = results.front(); auto elapsed = chrono::duration_cast<chrono::seconds>( chrono::high_resolution_clock::now() - start_time).count();
cout << "\nFound solution!" << endl; cout << "Private Key: " << hex_key << endl; cout << "Bit Flips: " << flips << endl; cout << "Checked " << checked << " combinations in " << elapsed << " seconds (" << (checked/elapsed) << " keys/sec)" << endl;
ofstream out("solution.txt"); out << hex_key; out.close(); } else { cout << "\nSolution not found. Try adjusting flip count." << endl; } }
int main() { #if OPENSSL_VERSION_NUMBER < 0x10100000L OpenSSL_add_all_algorithms(); #endif
parallel_search();
#if OPENSSL_VERSION_NUMBER < 0x10100000L EVP_cleanup(); #endif
return 0; }  I'll try to improve it myself, and then I'll show you what I got 
|
|
|
|
|
|
nomachine
|
 |
March 30, 2025, 06:31:20 PM Last edit: March 30, 2025, 07:01:46 PM by nomachine |
|
 I'll try to improve it myself, and then I'll show you what I got  The script is not polished; it was just cloned from Python in a hurry. You probably have a memory handling issue, as it crashes on large puzzles. I've encountered this before with similar scripts.  P.S. A little advice: Upload the script as your own on GitHub and improve it. This is your idea.
|
BTC: bc1qdwnxr7s08xwelpjy3cc52rrxg63xsmagv50fa8
|
|
|
Denevron
Newbie
Offline
Activity: 121
Merit: 0
|
 |
March 30, 2025, 06:43:51 PM |
|
 I'll try to improve it myself, and then I'll show you what I got  The script is not polished; it was just cloned from Python in a hurry. You probably have a memory handling issue, as it crashes on large puzzles. I've encountered this before with similar scripts.  well there are problems, but there is something to work with) here you can also use other libraries, faster ones) I will try) I would even make such a blank, it would take a long time) 
|
|
|
|
|
b0dre
Jr. Member
Offline
Activity: 61
Merit: 1
|
 |
March 30, 2025, 07:00:43 PM |
|
can be called a mutagen  It's not that simple, but it speeds up the process, you've noticed it yourself) you can add it to Cyclon as a new method, and there you just don’t calculate the puzzle range, but enter the key by which the bits will change, and it’s better not in random mode, but in sequential mode, because the random mode will loop and that’s it, and you will be forever, say, chasing in 30 bits, and you won’t find it, and it will be, say, in 33 bits import time import multiprocessing import secp256k1 as ice import random from math import comb import numpy as np
# Configuration TARGET_ADDR = "1HsMJxNiV7TLxmoF6uJNkydxPFDog4NQum" # Puzzle 20 BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f" # Puzzle 19 Private Key PUZZLE_NUM = 20 WORKERS = multiprocessing.cpu_count()
# Historical flip counts FLIP_TABLE = { 20:8, 21:8, 22:9, 23:9, 24:10, 25:11, 26:12, 27:13, 28:14, 29:15, 30:16, 31:17, 32:18, 33:19, 34:20, 35:21, 36:22, 37:23, 38:24, 39:25, 40:26, 41:27, 42:28, 43:29, 44:30, 45:31, 46:32, 47:33, 48:34, 49:35, 50:36, 51:37, 52:38, 53:39, 54:40, 55:41, 56:42, 57:43, 58:44, 59:45, 60:46, 61:47, 62:48, 63:49, 64:50, 65:51, 66:52, 67:53 }
def predict_flips(puzzle_num): """Predict flip count using linear regression with bounds""" if puzzle_num in FLIP_TABLE: return FLIP_TABLE[puzzle_num] # Linear regression x = np.array(list(FLIP_TABLE.keys())) y = np.array(list(FLIP_TABLE.values())) coeffs = np.polyfit(x, y, 1) predicted = round(coeffs[0] * puzzle_num + coeffs[1]) # Apply bounds (50-60% of bits) bit_length = puzzle_num lower = max(8, int(bit_length * 0.5)) upper = min(int(bit_length * 0.6), bit_length-5) return min(max(predicted, lower), upper)
def mutate_key(base_int, flip_positions): """Ultra-fast bit flipping using XOR mask""" flip_mask = sum(1 << bit for bit in flip_positions) return base_int ^ flip_mask
def worker(base_int, bit_length, flip_count, results, stop_event): checked = 0 bit_positions = list(range(bit_length)) start_time = time.time() while not stop_event.is_set(): # Generate random flip positions flip_pos = random.sample(bit_positions, flip_count) # Create mutated key priv_int = mutate_key(base_int, flip_pos) checked += 1 # Generate address addr = ice.privatekey_to_address(0, True, priv_int) if addr == TARGET_ADDR: hex_key = "%064x" % priv_int actual_flips = bin(base_int ^ priv_int).count('1') results.put((hex_key, checked, actual_flips)) stop_event.set() return # Progress update if checked % 10000 == 0: elapsed = time.time() - start_time speed = checked/elapsed if elapsed > 0 else 0 print(f"Checked {checked:,} | {speed:,.0f} keys/sec", end='\r')
def parallel_search(): bit_length = PUZZLE_NUM base_int = int(BASE_KEY, 16) flip_count = predict_flips(PUZZLE_NUM) total_combs = comb(bit_length, flip_count) print(f"\nSearching Puzzle {PUZZLE_NUM} (256-bit)") print(f"Base Key: {BASE_KEY}") print(f"Target: {TARGET_ADDR}") print(f"Predicted Flip Count: {flip_count} bits") print(f"Total Possible Combinations: 2^{int(np.log2(total_combs)):,}") print(f"Using {WORKERS} workers...\n") manager = multiprocessing.Manager() results = manager.Queue() stop_event = manager.Event() start_time = time.time() with multiprocessing.Pool(WORKERS) as pool: for _ in range(WORKERS): pool.apply_async(worker, (base_int, bit_length, flip_count, results, stop_event)) try: hex_key, checked, actual_flips = results.get(timeout=86400) # 24h timeout stop_event.set() elapsed = time.time() - start_time print(f"\nFound in {elapsed/3600:.2f} hours") print(f"Private Key: {hex_key}") print(f"Actual Bit Flips: {actual_flips}") print(f"Keys Checked: {checked:,}") print(f"Speed: {checked/elapsed:,.0f} keys/sec") solution_file = f"puzzle_{PUZZLE_NUM}_solution.txt" with open(solution_file, "w") as f: f.write(hex_key) print(f"\nSolution saved to {solution_file}") return hex_key except: print("\nKey not found in 24 hours - try adjusting flip count ±2") return None finally: pool.terminate()
if __name__ == "__main__": flip_count = predict_flips(PUZZLE_NUM) # First calculate flip_count print(f"Predicted flip count for {PUZZLE_NUM}: {flip_count} bits") solution = parallel_search() Here is my Python version. I still think this is useless. If someone convinces me otherwise.  you don't need to use random, so you won't find a match, only if you guess the number of bits  import time import multiprocessing import secp256k1 as ice from math import comb import numpy as np from itertools import combinations # For sequential flip generation
# Configuration TARGET_ADDR = "1HsMJxNiV7TLxmoF6uJNkydxPFDog4NQum" # Puzzle 20 BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f" # Puzzle 19 Private Key PUZZLE_NUM = 20 WORKERS = multiprocessing.cpu_count()
# Historical flip counts (unchanged) FLIP_TABLE = { 20:8, 21:8, 22:9, 23:9, 24:10, 25:11, 26:12, 27:13, 28:14, 29:15, 30:16, 31:17, 32:18, 33:19, 34:20, 35:21, 36:22, 37:23, 38:24, 39:25, 40:26, 41:27, 42:28, 43:29, 44:30, 45:31, 46:32, 47:33, 48:34, 49:35, 50:36, 51:37, 52:38, 53:39, 54:40, 55:41, 56:42, 57:43, 58:44, 59:45, 60:46, 61:47, 62:48, 63:49, 64:50, 65:51, 66:52, 67:53 }
def predict_flips(puzzle_num): """Predict flip count using linear regression with bounds (unchanged)""" if puzzle_num in FLIP_TABLE: return FLIP_TABLE[puzzle_num] # Linear regression x = np.array(list(FLIP_TABLE.keys())) y = np.array(list(FLIP_TABLE.values())) coeffs = np.polyfit(x, y, 1) predicted = round(coeffs[0] * puzzle_num + coeffs[1]) # Apply bounds (50-60% of bits) bit_length = puzzle_num lower = max(8, int(bit_length * 0.5)) upper = min(int(bit_length * 0.6), bit_length-5) return min(max(predicted, lower), upper)
def mutate_key(base_int, flip_positions): """Ultra-fast bit flipping using XOR mask (unchanged)""" flip_mask = sum(1 << bit for bit in flip_positions) return base_int ^ flip_mask
def worker(base_int, bit_length, flip_count, results, stop_event, start_index, end_index): """Modified worker for sequential search""" checked = 0 bit_positions = list(range(bit_length)) start_time = time.time()
# Generate all combinations in the assigned range all_combinations = combinations(bit_positions, flip_count) # Skip to the start index (for parallelization) for _ in range(start_index): next(all_combinations, None) # Iterate through combinations sequentially for flip_pos in all_combinations: if stop_event.is_set(): return if checked >= (end_index - start_index): return priv_int = mutate_key(base_int, flip_pos) checked += 1 # Generate address addr = ice.privatekey_to_address(0, True, priv_int) if addr == TARGET_ADDR: hex_key = "%064x" % priv_int actual_flips = bin(base_int ^ priv_int).count('1') results.put((hex_key, checked, actual_flips)) stop_event.set() return # Progress update if checked % 10000 == 0: elapsed = time.time() - start_time speed = checked/elapsed if elapsed > 0 else 0 print(f"Checked {checked:,} | {speed:,.0f} keys/sec", end='\r')
def parallel_search(): bit_length = PUZZLE_NUM base_int = int(BASE_KEY, 16) flip_count = predict_flips(PUZZLE_NUM) total_combs = comb(bit_length, flip_count) print(f"\nSearching Puzzle {PUZZLE_NUM} (256-bit)") print(f"Base Key: {BASE_KEY}") print(f"Target: {TARGET_ADDR}") print(f"Predicted Flip Count: {flip_count} bits") print(f"Total Possible Combinations: 2^{int(np.log2(total_combs)):,}") print(f"Using {WORKERS} workers...\n") manager = multiprocessing.Manager() results = manager.Queue() stop_event = manager.Event() start_time = time.time() # Split work into chunks for each worker chunk_size = total_combs // WORKERS ranges = [(i * chunk_size, (i + 1) * chunk_size) for i in range(WORKERS)] with multiprocessing.Pool(WORKERS) as pool: for start, end in ranges: pool.apply_async(worker, (base_int, bit_length, flip_count, results, stop_event, start, end)) try: hex_key, checked, actual_flips = results.get(timeout=86400) # 24h timeout stop_event.set() elapsed = time.time() - start_time print(f"\nFound in {elapsed/3600:.2f} hours") print(f"Private Key: {hex_key}") print(f"Actual Bit Flips: {actual_flips}") print(f"Keys Checked: {checked:,}") print(f"Speed: {checked/elapsed:,.0f} keys/sec") solution_file = f"puzzle_{PUZZLE_NUM}_solution.txt" with open(solution_file, "w") as f: f.write(hex_key) print(f"\nSolution saved to {solution_file}") return hex_key except: print("\nKey not found in 24 hours - try adjusting flip count ±2") return None finally: pool.terminate()
if __name__ == "__main__": flip_count = predict_flips(PUZZLE_NUM) print(f"Predicted flip count for {PUZZLE_NUM}: {flip_count} bits") solution = parallel_search() Here is the script. I don't see any difference here. To solve puzzle 68 you need impossible speed. 21 is not found! For 21 you need to put the key from the 20th puzzle, set hash160 from 21 and put 9 bits - then you will find) those bits that are in the nomachine example, this is just an example, this is not the exact number of bits that need to be changed)  Found, but now 22 is not.
|
|
|
|
|
|
nomachine
|
 |
March 30, 2025, 07:13:35 PM |
|
Found, but now 22 is not.
# Historical flip counts FLIP_TABLE = { 20:8, 21:9, 22:11, 23:12, 24:9, 25:12, 26:14, 27:13, 28:16, 29:18, 30:16, 31:13, 32:14, 33:15, 34:16, 35:19, 36:14, 37:23, 38:21, 39:23, 40:20, 41:25, 42:24, 43:19, 44:24, 45:21, 46:24, 47:27, 48:21, 49:30, 50:9, 51:25, 52:27, 53:26, 54:30, 55:31, 56:31, 57:33, 5:28, 59:30, 60:31, 61:25, 62:35, 63:34, 64:34, 65:37, 66:35, 67:31, 68:34 } Puzzle 68 is guessed to be 34. Maybe it is 35, 33, 37 etc.
|
BTC: bc1qdwnxr7s08xwelpjy3cc52rrxg63xsmagv50fa8
|
|
|
Denevron
Newbie
Offline
Activity: 121
Merit: 0
|
 |
March 30, 2025, 07:43:53 PM |
|
Found, but now 22 is not.
# Historical flip counts FLIP_TABLE = { 20:8, 21:9, 22:11, 23:12, 24:9, 25:12, 26:14, 27:13, 28:16, 29:18, 30:16, 31:13, 32:14, 33:15, 34:16, 35:19, 36:14, 37:23, 38:21, 39:23, 40:20, 41:25, 42:24, 43:19, 44:24, 45:21, 46:24, 47:27, 48:21, 49:30, 50:9, 51:25, 52:27, 53:26, 54:30, 55:31, 56:31, 57:33, 5:28, 59:30, 60:31, 61:25, 62:35, 63:34, 64:34, 65:37, 66:35, 67:31, 68:34 } Puzzle 68 is guessed to be 34. Maybe it is 35, 33, 37 etc. but it could also be 11 or 13 for example 
|
|
|
|
|
MrGPBit
Jr. Member
Offline
Activity: 52
Merit: 1
|
 |
March 30, 2025, 08:22:55 PM |
|
I understand that I need to do it myself, but still, thank you very much for the prototype)
256-bit version with BIGNUM: #include <iostream> #include <iomanip> #include <sstream> #include <vector> #include <thread> #include <atomic> #include <chrono> #include <queue> #include <mutex> #include <unordered_map> #include <cmath> #include <fstream> #include <openssl/ec.h> #include <openssl/sha.h> #include <openssl/ripemd.h> #include <openssl/bn.h> #include <openssl/obj_mac.h> #include <openssl/evp.h>
using namespace std;
// Configuration const string TARGET_HASH160 = "b907c3a2a3b27789dfb509b730dd47703c272868"; const string BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f"; const int PUZZLE_NUM = 20; const int WORKERS = thread::hardware_concurrency();
// Historical flip counts const unordered_map<int, int> FLIP_TABLE = { {20, 8}, {21, 9}, {22, 11}, {23, 12}, {24, 9}, {25, 12}, {26, 14}, {27, 13}, {28, 16}, {29, 18}, {30, 16}, {31, 13}, {32, 14}, {33, 15}, {34, 16}, {35, 19}, {36, 14}, {37, 23}, {38, 21}, {39, 23}, {40, 20}, {41, 25}, {42, 24}, {43, 19}, {44, 24}, {45, 21}, {46, 24}, {47, 27}, {48, 21}, {49, 30}, {50, 29}, {51, 25}, {52, 27}, {53, 26}, {54, 30}, {55, 31}, {56, 31}, {57, 33}, {58, 28}, {59, 30}, {60, 31}, {61, 25}, {62, 35}, {63, 34}, {64, 34}, {65, 37}, {66, 35}, {67, 31}, {68, 34} };
// Global variables atomic<bool> stop_event(false); mutex result_mutex; queue<tuple<string, size_t, int>> results;
// Predict flip count int predict_flips(int puzzle_num) { if (FLIP_TABLE.count(puzzle_num)) { return FLIP_TABLE.at(puzzle_num); } return 8; // Default }
// Binomial coefficient size_t combinations_count(int n, int k) { if (k > n) return 0; if (k * 2 > n) k = n - k; if (k == 0) return 1;
size_t result = n; for(int i = 2; i <= k; ++i) { result *= (n - i + 1); result /= i; } return result; }
// Generate combinations vector<vector<int>> generate_combinations(int n, int k) { vector<vector<int>> combinations; vector<int> current(k, 0); for (int i = 0; i < k; ++i) current[i] = i;
while (true) { combinations.push_back(current);
int i = k - 1; while (i >= 0 && current[i] == n - k + i) --i; if (i < 0) break;
++current[i]; for (int j = i + 1; j < k; ++j) current[j] = current[j - 1] + 1; } return combinations; }
// Convert BIGNUM to hex string string bn_to_hex(const BIGNUM* bn) { char* hex = BN_bn2hex(bn); string result(hex); OPENSSL_free(hex); return result; }
// XOR operation for BIGNUM void bn_xor(BIGNUM* result, const BIGNUM* a, const BIGNUM* b) { BIGNUM* tmp = BN_new(); BN_copy(result, a); for (int i = 0; i < max(BN_num_bits(a), BN_num_bits(b)); ++i) { if (BN_is_bit_set(a, i) != BN_is_bit_set(b, i)) { BN_set_bit(result, i); } else { BN_clear_bit(result, i); } } BN_free(tmp); }
// Compute HASH160 from BIGNUM private key string compute_hash160(const BIGNUM* priv_key) { EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_secp256k1); if (!ec_key) return "";
if (!EC_KEY_set_private_key(ec_key, priv_key)) { EC_KEY_free(ec_key); return ""; }
const EC_GROUP* group = EC_KEY_get0_group(ec_key); EC_POINT* pub_key = EC_POINT_new(group); if (!pub_key) { EC_KEY_free(ec_key); return ""; }
if (!EC_POINT_mul(group, pub_key, priv_key, nullptr, nullptr, nullptr)) { EC_POINT_free(pub_key); EC_KEY_free(ec_key); return ""; }
unsigned char pubkey[65]; int pubkey_len = EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_COMPRESSED, pubkey, sizeof(pubkey), nullptr); EC_POINT_free(pub_key); EC_KEY_free(ec_key);
if (pubkey_len != 33) return "";
unsigned char sha256[SHA256_DIGEST_LENGTH]; SHA256(pubkey, pubkey_len, sha256);
unsigned char ripemd160[RIPEMD160_DIGEST_LENGTH]; RIPEMD160(sha256, SHA256_DIGEST_LENGTH, ripemd160);
stringstream ss; for (int i = 0; i < RIPEMD160_DIGEST_LENGTH; ++i) { ss << hex << setw(2) << setfill('0') << (int)ripemd160[i]; } return ss.str(); }
// Worker function void worker(const BIGNUM* base_bn, int bit_length, int flip_count, size_t start_index, size_t end_index) { vector<vector<int>> combinations = generate_combinations(bit_length, flip_count); BIGNUM* current_bn = BN_new(); BIGNUM* flip_mask = BN_new();
for (size_t i = start_index; i < end_index && !stop_event.load(); ++i) { BN_zero(flip_mask); for (int pos : combinations[i]) { BN_set_bit(flip_mask, pos); } bn_xor(current_bn, base_bn, flip_mask);
string hash160 = compute_hash160(current_bn); if (hash160 == TARGET_HASH160) { string hex_key = bn_to_hex(current_bn); lock_guard<mutex> lock(result_mutex); results.push(make_tuple(hex_key, i+1, flip_count)); stop_event.store(true); break; }
if ((i+1) % 10000 == 0) { cout << "Checked " << (i+1) << " combinations\r"; cout.flush(); } }
BN_free(current_bn); BN_free(flip_mask); }
// Parallel search void parallel_search() { BIGNUM* base_bn = BN_new(); BN_hex2bn(&base_bn, BASE_KEY.c_str());
int flip_count = predict_flips(PUZZLE_NUM); size_t total_combs = combinations_count(PUZZLE_NUM, flip_count);
cout << "Searching Puzzle " << PUZZLE_NUM << " (256-bit)" << endl; cout << "Base Key: " << BASE_KEY << endl; cout << "Target HASH160: " << TARGET_HASH160 << endl; cout << "Predicted Flip Count: " << flip_count << " bits" << endl; cout << "Total Possible Combinations: " << total_combs << endl; cout << "Using " << WORKERS << " workers..." << endl;
vector<thread> threads; size_t chunk_size = total_combs / WORKERS; auto start_time = chrono::high_resolution_clock::now();
for (int i = 0; i < WORKERS; ++i) { size_t start = i * chunk_size; size_t end = (i == WORKERS-1) ? total_combs : start + chunk_size; threads.emplace_back(worker, base_bn, PUZZLE_NUM, flip_count, start, end); }
for (auto& t : threads) t.join(); BN_free(base_bn);
if (!results.empty()) { auto [hex_key, checked, flips] = results.front(); auto elapsed = chrono::duration_cast<chrono::seconds>( chrono::high_resolution_clock::now() - start_time).count();
cout << "\nFound solution!" << endl; cout << "Private Key: " << hex_key << endl; cout << "Bit Flips: " << flips << endl; cout << "Checked " << checked << " combinations in " << elapsed << " seconds (" << (checked/elapsed) << " keys/sec)" << endl;
ofstream out("solution.txt"); out << hex_key; out.close(); } else { cout << "\nSolution not found. Try adjusting flip count." << endl; } }
int main() { #if OPENSSL_VERSION_NUMBER < 0x10100000L OpenSSL_add_all_algorithms(); #endif
parallel_search();
#if OPENSSL_VERSION_NUMBER < 0x10100000L EVP_cleanup(); #endif
return 0; } # ./mutagen Searching Puzzle 68 (256-bit) Base Key: 00000000000000000000000000000000000000000000000730fc235c1942c1ae Target HASH160: e0b8a2baee1b77fc703455f39d51477451fc8cfc Predicted Flip Count: 34 bits Total Possible Combinations: 47478523248093572 Using 12 workers...
Good luck searching through 47 quadrillion combinations.  In Puzzle 68, the source code causes a ram usage of 100% and it can also cause a system crash
|
|
|
|
|
Tepan
Jr. Member
Offline
Activity: 84
Merit: 1
|
 |
March 30, 2025, 08:23:26 PM |
|
tepan@MacBook-Pro %
result :
RANGE 49
1000000000000:1ffffffffffff
start = 281474976710656 end = 562949953421311
k = 79985852346388
319943409385552 = 122FCA143C050 #1 337535595429968 = 132FCA143C050 #2
399929261731940 = 16BBBC994B064 #1 417521447776356 = 17BBBC994B064 #2
479915114078328 = 1B47AF1E5A078 #1 497507300122744 = 1C47AF1E5A078 #2
key = 174176B015F4D <- answer
RANGE 53
10000000000000:1fffffffffffff
start = 4503599627370496 end = 9007199254740991
k = 1636475620130100
5190901837100956 = 1271190410779C #1 6827377457231056 = 184176B015F4D0 #2
8463853077361156 = 1E11D45C1B7204 #1 8745328054071812 = 1F11D45C1B7204 #2
key = 180788E47E326C <- answer
i just play around with math, by using simple decimal multiplications combined with logarithmic insights, you can systematically determine key values within a numerical range.
fun fact the unique thing is that the key is indeed located right in the area that has been measured using mathematics, I am using 2 pieces of evidence for now.
for now i'm just doing this thing work, thanks for read and respect my post about puzzle.
|
|
|
|
|
Denevron
Newbie
Offline
Activity: 121
Merit: 0
|
 |
March 30, 2025, 08:24:36 PM |
|
I understand that I need to do it myself, but still, thank you very much for the prototype)
256-bit version with BIGNUM: #include <iostream> #include <iomanip> #include <sstream> #include <vector> #include <thread> #include <atomic> #include <chrono> #include <queue> #include <mutex> #include <unordered_map> #include <cmath> #include <fstream> #include <openssl/ec.h> #include <openssl/sha.h> #include <openssl/ripemd.h> #include <openssl/bn.h> #include <openssl/obj_mac.h> #include <openssl/evp.h>
using namespace std;
// Configuration const string TARGET_HASH160 = "b907c3a2a3b27789dfb509b730dd47703c272868"; const string BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f"; const int PUZZLE_NUM = 20; const int WORKERS = thread::hardware_concurrency();
// Historical flip counts const unordered_map<int, int> FLIP_TABLE = { {20, 8}, {21, 9}, {22, 11}, {23, 12}, {24, 9}, {25, 12}, {26, 14}, {27, 13}, {28, 16}, {29, 18}, {30, 16}, {31, 13}, {32, 14}, {33, 15}, {34, 16}, {35, 19}, {36, 14}, {37, 23}, {38, 21}, {39, 23}, {40, 20}, {41, 25}, {42, 24}, {43, 19}, {44, 24}, {45, 21}, {46, 24}, {47, 27}, {48, 21}, {49, 30}, {50, 29}, {51, 25}, {52, 27}, {53, 26}, {54, 30}, {55, 31}, {56, 31}, {57, 33}, {58, 28}, {59, 30}, {60, 31}, {61, 25}, {62, 35}, {63, 34}, {64, 34}, {65, 37}, {66, 35}, {67, 31}, {68, 34} };
// Global variables atomic<bool> stop_event(false); mutex result_mutex; queue<tuple<string, size_t, int>> results;
// Predict flip count int predict_flips(int puzzle_num) { if (FLIP_TABLE.count(puzzle_num)) { return FLIP_TABLE.at(puzzle_num); } return 8; // Default }
// Binomial coefficient size_t combinations_count(int n, int k) { if (k > n) return 0; if (k * 2 > n) k = n - k; if (k == 0) return 1;
size_t result = n; for(int i = 2; i <= k; ++i) { result *= (n - i + 1); result /= i; } return result; }
// Generate combinations vector<vector<int>> generate_combinations(int n, int k) { vector<vector<int>> combinations; vector<int> current(k, 0); for (int i = 0; i < k; ++i) current[i] = i;
while (true) { combinations.push_back(current);
int i = k - 1; while (i >= 0 && current[i] == n - k + i) --i; if (i < 0) break;
++current[i]; for (int j = i + 1; j < k; ++j) current[j] = current[j - 1] + 1; } return combinations; }
// Convert BIGNUM to hex string string bn_to_hex(const BIGNUM* bn) { char* hex = BN_bn2hex(bn); string result(hex); OPENSSL_free(hex); return result; }
// XOR operation for BIGNUM void bn_xor(BIGNUM* result, const BIGNUM* a, const BIGNUM* b) { BIGNUM* tmp = BN_new(); BN_copy(result, a); for (int i = 0; i < max(BN_num_bits(a), BN_num_bits(b)); ++i) { if (BN_is_bit_set(a, i) != BN_is_bit_set(b, i)) { BN_set_bit(result, i); } else { BN_clear_bit(result, i); } } BN_free(tmp); }
// Compute HASH160 from BIGNUM private key string compute_hash160(const BIGNUM* priv_key) { EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_secp256k1); if (!ec_key) return "";
if (!EC_KEY_set_private_key(ec_key, priv_key)) { EC_KEY_free(ec_key); return ""; }
const EC_GROUP* group = EC_KEY_get0_group(ec_key); EC_POINT* pub_key = EC_POINT_new(group); if (!pub_key) { EC_KEY_free(ec_key); return ""; }
if (!EC_POINT_mul(group, pub_key, priv_key, nullptr, nullptr, nullptr)) { EC_POINT_free(pub_key); EC_KEY_free(ec_key); return ""; }
unsigned char pubkey[65]; int pubkey_len = EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_COMPRESSED, pubkey, sizeof(pubkey), nullptr); EC_POINT_free(pub_key); EC_KEY_free(ec_key);
if (pubkey_len != 33) return "";
unsigned char sha256[SHA256_DIGEST_LENGTH]; SHA256(pubkey, pubkey_len, sha256);
unsigned char ripemd160[RIPEMD160_DIGEST_LENGTH]; RIPEMD160(sha256, SHA256_DIGEST_LENGTH, ripemd160);
stringstream ss; for (int i = 0; i < RIPEMD160_DIGEST_LENGTH; ++i) { ss << hex << setw(2) << setfill('0') << (int)ripemd160[i]; } return ss.str(); }
// Worker function void worker(const BIGNUM* base_bn, int bit_length, int flip_count, size_t start_index, size_t end_index) { vector<vector<int>> combinations = generate_combinations(bit_length, flip_count); BIGNUM* current_bn = BN_new(); BIGNUM* flip_mask = BN_new();
for (size_t i = start_index; i < end_index && !stop_event.load(); ++i) { BN_zero(flip_mask); for (int pos : combinations[i]) { BN_set_bit(flip_mask, pos); } bn_xor(current_bn, base_bn, flip_mask);
string hash160 = compute_hash160(current_bn); if (hash160 == TARGET_HASH160) { string hex_key = bn_to_hex(current_bn); lock_guard<mutex> lock(result_mutex); results.push(make_tuple(hex_key, i+1, flip_count)); stop_event.store(true); break; }
if ((i+1) % 10000 == 0) { cout << "Checked " << (i+1) << " combinations\r"; cout.flush(); } }
BN_free(current_bn); BN_free(flip_mask); }
// Parallel search void parallel_search() { BIGNUM* base_bn = BN_new(); BN_hex2bn(&base_bn, BASE_KEY.c_str());
int flip_count = predict_flips(PUZZLE_NUM); size_t total_combs = combinations_count(PUZZLE_NUM, flip_count);
cout << "Searching Puzzle " << PUZZLE_NUM << " (256-bit)" << endl; cout << "Base Key: " << BASE_KEY << endl; cout << "Target HASH160: " << TARGET_HASH160 << endl; cout << "Predicted Flip Count: " << flip_count << " bits" << endl; cout << "Total Possible Combinations: " << total_combs << endl; cout << "Using " << WORKERS << " workers..." << endl;
vector<thread> threads; size_t chunk_size = total_combs / WORKERS; auto start_time = chrono::high_resolution_clock::now();
for (int i = 0; i < WORKERS; ++i) { size_t start = i * chunk_size; size_t end = (i == WORKERS-1) ? total_combs : start + chunk_size; threads.emplace_back(worker, base_bn, PUZZLE_NUM, flip_count, start, end); }
for (auto& t : threads) t.join(); BN_free(base_bn);
if (!results.empty()) { auto [hex_key, checked, flips] = results.front(); auto elapsed = chrono::duration_cast<chrono::seconds>( chrono::high_resolution_clock::now() - start_time).count();
cout << "\nFound solution!" << endl; cout << "Private Key: " << hex_key << endl; cout << "Bit Flips: " << flips << endl; cout << "Checked " << checked << " combinations in " << elapsed << " seconds (" << (checked/elapsed) << " keys/sec)" << endl;
ofstream out("solution.txt"); out << hex_key; out.close(); } else { cout << "\nSolution not found. Try adjusting flip count." << endl; } }
int main() { #if OPENSSL_VERSION_NUMBER < 0x10100000L OpenSSL_add_all_algorithms(); #endif
parallel_search();
#if OPENSSL_VERSION_NUMBER < 0x10100000L EVP_cleanup(); #endif
return 0; } # ./mutagen Searching Puzzle 68 (256-bit) Base Key: 00000000000000000000000000000000000000000000000730fc235c1942c1ae Target HASH160: e0b8a2baee1b77fc703455f39d51477451fc8cfc Predicted Flip Count: 34 bits Total Possible Combinations: 47478523248093572 Using 12 workers...
Good luck searching through 47 quadrillion combinations.  In Puzzle 68, the source code causes a ram usage of 100% and it can also cause a system crash because this is a code example, it is not a fully functional program) to avoid this, you don't just need to generate all the options at once) there is still a lot of work to do)
|
|
|
|
|
Denevron
Newbie
Offline
Activity: 121
Merit: 0
|
 |
March 30, 2025, 08:39:01 PM |
|
The program is on my github, it is at the initial stage of development) There is also a Python version there. https://github.com/MikeWazovksy/MutagenThank you for your help @nomachine
|
|
|
|
|
|
kTimesG
|
 |
March 30, 2025, 10:36:15 PM |
|
deep seek comments for cyclone:
Expected Performance: Optimization Speed Multiplier Base AVX2 1x AVX-512 2x GPU Acceleration 1000x Precomputation 10x Memory Optimization 1.5x Assembly Tuning 1.2x Total Potential 36,000x
For maximum speed, focus first on GPU implementation (biggest gain) while maintaining the AVX2 path as fallback. The combination of all optimizations can theoretically achieve over 30,000x speed improvement over the original single-threaded version.
Loads of bullshit. That's not how things work in the GPU world, buddy. GPU acceleration is already tuned to maximum performance, and there are very little things that can be tweaked to make it a little bit faster than the current records (~7 GH / Joule, or ~7 GH/s/Watt, however you wanna look at it). And even so, it is already hundreds of times faster than any CPU you can think of, or hundreds of times more efficient, again however you wanna look at it. CPU bullshits like AVX, SSE, memory whatever crap, assembler optimizations - these DO NOT EXIST when programming for a GPU. There are VERY VERY different problems to work with, when building a GPU kernel / app. All the optimizations for Cyclone in the last 20 pages of this forum are just to make a very inefficient CPU software work a little less painfully slower, for people that are living in a lie ("I can't afford a GPU, but I prefer to fry my motherboard instead of renting on vast.ai and compute tons of hashes more than the ones my PC can produce, at the same price"), that's all. The Cyclone hype DOES NOT APPLY AT ALL to GPU acceleration, no matter what deepseek or ChatGPT nonsense BS may lead you to believe. I am astonished by how people continue to believe that adding all sorts of slowdowns actually think would makes things faster. Probabilities, skips, jumps, random selections, combinations, bit flips, base58 voodoos - guys, the slightest attempt to use ANY of these stuff just creates GAPS and SLOWDOWNS in the processing pipeline, so the performance gain factor is somewhere between zero and one (e.g. - your expected time to solve multiplies, not shortens). The net result is a loss of hash time and loss of precious computing cycles. There is no mathematical proof about any magical method to shorten a brute force attempt on a uniform distribution, so anything that interferes with the actual search process is just a guaranteed way to find the key much later rather than much sooner.
|
Off the grid, training pigeons to broadcast signed messages.
|
|
|
AlanJohnson
Member

Offline
Activity: 185
Merit: 11
|
 |
March 31, 2025, 05:45:43 AM |
|
All the optimizations for Cyclone in the last 20 pages of this forum are just to make a very inefficient CPU software work a little less painfully slower, for people that are living in a lie ("I can't afford a GPU, but I prefer to fry my motherboard instead of renting on vast.ai and compute tons of hashes more than the ones my PC can produce, at the same price"), that's all. The Cyclone hype DOES NOT APPLY AT ALL to GPU acceleration, no matter what deepseek or ChatGPT nonsense BS may lead you to believe.
I am astonished by how people continue to believe that adding all sorts of slowdowns actually think would makes things faster. Probabilities, skips, jumps, random selections, combinations, bit flips, base58 voodoos - guys, the slightest attempt to use ANY of these stuff just creates GAPS and SLOWDOWNS in the processing pipeline, so the performance gain factor is somewhere between zero and one (e.g. - your expected time to solve multiplies, not shortens). The net result is a loss of hash time and loss of precious computing cycles. There is no mathematical proof about any magical method to shorten a brute force attempt on a uniform distribution, so anything that interferes with the actual search process is just a guaranteed way to find the key much later rather than much sooner.
But this is how the things are going on this forum... At this point we need a MASSIVE computing power to resolve any of the remaining puzzles. If anybody counts on "luck" and "what if" - trying to search on home desktop it doesn't really matter what program are you using (cyclone, keyhunt, bitcrack or some random python script) cause your chances are so small that being a bit faster or slower doesn't change anything. It would be better to make a an app for smartphone that uses ONLY ONE core (to not drain battery or overheat too much) to search for a puzzles and make millions of people all over the world installing it. I guess it could be solved pretty quick then. But from the other hand i doubt there is so many people interested in this madness.
|
|
|
|
|
|
nomachine
|
 |
March 31, 2025, 05:45:56 AM |
|
Probabilities, skips, jumps, random selections, combinations, bit flips, base58 voodoos - guys
People need something to do in their free time if they have it to spare. It's better than doing drugs, joining a local gang, or staring at their phones, waging troll wars to ruin others' smiles out of pure spite.  #include <iostream> #include <iomanip> #include <fstream> #include <sstream> #include <vector> #include <thread> #include <atomic> #include <chrono> #include <queue> #include <mutex> #include <cstring> #include <unordered_map> #include <cmath> #include <openssl/ec.h> #include <openssl/sha.h> #include <openssl/ripemd.h> #include <openssl/bn.h> #include <openssl/obj_mac.h> #include <openssl/evp.h>
using namespace std;
// Configuration const string TARGET_HASH160 = "b907c3a2a3b27789dfb509b730dd47703c272868"; const string BASE_KEY = "000000000000000000000000000000000000000000000000000000000005749f"; const int PUZZLE_NUM = 20; const int WORKERS = thread::hardware_concurrency(); const size_t REPORT_INTERVAL = 10000;
// Historical flip counts const unordered_map<int, int> FLIP_TABLE = { {20, 8}, {21, 9}, {22, 11}, {23, 12}, {24, 9}, {25, 12}, {26, 14}, {27, 13}, {28, 16}, {29, 18}, {30, 16}, {31, 13}, {32, 14}, {33, 15}, {34, 16}, {35, 19}, {36, 14}, {37, 23}, {38, 21}, {39, 23}, {40, 20}, {41, 25}, {42, 24}, {43, 19}, {44, 24}, {45, 21}, {46, 24}, {47, 27}, {48, 21}, {49, 30}, {50, 29}, {51, 25}, {52, 27}, {53, 26}, {54, 30}, {55, 31}, {56, 31}, {57, 33}, {58, 28}, {59, 30}, {60, 31}, {61, 25}, {62, 35}, {63, 34}, {64, 34}, {65, 37}, {66, 35}, {67, 31}, {68, 34} };
// Global variables vector<unsigned char> TARGET_HASH160_RAW(20); atomic<bool> stop_event(false); mutex result_mutex; queue<tuple<string, size_t, int>> results; atomic<size_t> total_checked(0); size_t total_combinations = 0;
// Convert hex string to raw bytes vector<unsigned char> hex_to_bytes(const string& hex) { vector<unsigned char> bytes; for (size_t i = 0; i < hex.length(); i += 2) { string byteString = hex.substr(i, 2); unsigned char byte = static_cast<unsigned char>(strtoul(byteString.c_str(), nullptr, 16)); bytes.push_back(byte); } return bytes; }
// Get only the last n bits of a BIGNUM BIGNUM* get_last_n_bits(BIGNUM* num, int n) { BIGNUM* result = BN_new(); BN_zero(result); for (int i = 0; i < n; ++i) { if (BN_is_bit_set(num, i)) { BN_set_bit(result, i); } } return result; }
// Predict flip count int predict_flips(int puzzle_num) { if (FLIP_TABLE.count(puzzle_num)) { return FLIP_TABLE.at(puzzle_num); } return 34; // Default for puzzle 68 }
// Binomial coefficient calculation size_t combinations_count(int n, int k) { if (k > n) return 0; if (k * 2 > n) k = n - k; if (k == 0) return 1;
size_t result = n; for(int i = 2; i <= k; ++i) { result *= (n - i + 1); result /= i; } return result; }
// Memory-efficient combination generator class CombinationGenerator { int n, k; vector<int> current; public: CombinationGenerator(int n, int k) : n(n), k(k), current(k) { for (int i = 0; i < k; ++i) current[i] = i; } bool next() { int i = k - 1; while (i >= 0 && current[i] == n - k + i) --i; if (i < 0) return false; ++current[i]; for (int j = i + 1; j < k; ++j) current[j] = current[j-1] + 1; return true; } const vector<int>& get() const { return current; } };
// Fast BIGNUM XOR for n bits void bn_xor_nbits(BIGNUM* r, const BIGNUM* a, const BIGNUM* b, int n) { BN_copy(r, a); for (int i = 0; i < n; ++i) { if (BN_is_bit_set(a, i) != BN_is_bit_set(b, i)) BN_set_bit(r, i); else BN_clear_bit(r, i); } }
// Worker function void worker(BIGNUM* base_bn, int bit_length, int flip_count, size_t start, size_t end) { // One-time allocations BIGNUM* trimmed_base = get_last_n_bits(base_bn, bit_length); BIGNUM* current = BN_new(); BIGNUM* mask = BN_new(); EC_KEY* key = EC_KEY_new_by_curve_name(NID_secp256k1); const EC_GROUP* group = EC_KEY_get0_group(key); EC_POINT* pub = EC_POINT_new(group); unsigned char pubkey[33]; unsigned char sha256[SHA256_DIGEST_LENGTH]; unsigned char ripemd160[RIPEMD160_DIGEST_LENGTH]; CombinationGenerator gen(bit_length, flip_count); for (size_t i = 0; i < start && gen.next(); ++i);
size_t count = 0; do { // 1. Build mask BN_zero(mask); for (int pos : gen.get()) BN_set_bit(mask, pos);
// 2. XOR operation bn_xor_nbits(current, trimmed_base, mask, bit_length);
// 3. Set private key if (!EC_KEY_set_private_key(key, current)) continue;
// 4. Generate public key if (!EC_POINT_mul(group, pub, current, nullptr, nullptr, nullptr)) continue;
// 5. Get compressed pubkey if (EC_POINT_point2oct(group, pub, POINT_CONVERSION_COMPRESSED, pubkey, 33, nullptr) != 33) continue;
// 6. Compute hashes SHA256(pubkey, 33, sha256); RIPEMD160(sha256, SHA256_DIGEST_LENGTH, ripemd160);
// 7. Compare raw bytes if (memcmp(ripemd160, TARGET_HASH160_RAW.data(), 20) == 0) { char* hex_key = BN_bn2hex(current); lock_guard<mutex> lock(result_mutex); results.push(make_tuple(hex_key, total_checked.load(), flip_count)); OPENSSL_free(hex_key); stop_event.store(true); break; }
if (++total_checked % REPORT_INTERVAL == 0) { double progress = (double)total_checked / total_combinations * 100; cout << "Progress: " << fixed << setprecision(6) << progress << "% ("; cout << total_checked << "/" << total_combinations << ")\r"; cout.flush(); } } while (gen.next() && (count++ < (end-start)) && !stop_event.load());
// Cleanup EC_POINT_free(pub); EC_KEY_free(key); BN_free(mask); BN_free(current); BN_free(trimmed_base); }
int main() { // Convert target hash to raw bytes TARGET_HASH160_RAW = hex_to_bytes(TARGET_HASH160);
cout << "=======================================\n"; cout << "== Mutagen Puzzle Solver by Denevron ==\n"; cout << "=======================================\n"; BIGNUM* base_bn = BN_new(); BN_hex2bn(&base_bn, BASE_KEY.c_str()); const int bit_length = PUZZLE_NUM; const int flip_count = predict_flips(PUZZLE_NUM); total_combinations = combinations_count(bit_length, flip_count); cout << "Searching Puzzle " << PUZZLE_NUM << " (" << bit_length << "-bit)\n"; cout << "Base Key: " << BASE_KEY.substr(0, 10) << "..." << BASE_KEY.substr(BASE_KEY.length()-10) << "\n"; cout << "Target HASH160: " << TARGET_HASH160.substr(0, 10) << "..." << TARGET_HASH160.substr(TARGET_HASH160.length()-10) << "\n"; cout << "Predicted Flip Count: " << flip_count << " bits\n"; cout << "Total Combinations: " << total_combinations << "\n"; cout << "Using " << WORKERS << " workers...\n"; auto start_time = chrono::high_resolution_clock::now(); vector<thread> threads; size_t chunk = total_combinations / WORKERS; for (int i = 0; i < WORKERS; ++i) { size_t start = i * chunk; size_t end = (i == WORKERS-1) ? total_combinations : start + chunk; threads.emplace_back(worker, base_bn, bit_length, flip_count, start, end); } for (auto& t : threads) t.join(); BN_free(base_bn); if (!results.empty()) { auto [hex_key, checked, flips] = results.front(); auto elapsed = chrono::duration_cast<chrono::seconds>( chrono::high_resolution_clock::now() - start_time).count(); cout << "\n=======================================\n"; cout << "=========== SOLUTION FOUND ============\n"; cout << "=======================================\n"; cout << "Private Key: " << hex_key << "\n"; cout << "Search Time: " << elapsed << " seconds\n"; cout << "Keys Checked: " << checked << "\n"; cout << "Bit Flips: " << flips << endl; ofstream out("puzzle_" + to_string(PUZZLE_NUM) + "_solution.txt"); out << hex_key; out.close(); cout << "Solution saved to puzzle_" << PUZZLE_NUM << "_solution.txt\n"; } else { cout << "\nSolution not found. Checked " << total_checked << " combinations\n"; } return 0; } # ./mutagen ======================================= == Mutagen Puzzle Solver by Denevron == ======================================= Searching Puzzle 20 (20-bit) Base Key: 0000000000...000005749f Target HASH160: b907c3a2a3...703c272868 Predicted Flip Count: 8 bits Total Combinations: 125970 Using 12 workers... Progress: 47.630388% (60000/125970) ======================================= =========== SOLUTION FOUND ============ ======================================= Private Key: 0D2C55 Search Time: 3 seconds Keys Checked: 63547 Bit Flips: 8 Solution saved to puzzle_20_solution.txt And so on, it can be improved infinitely. But the main question here is the number of possible combinations, which grow exponentially. But we love useless scripts—I’m even a collector 
|
BTC: bc1qdwnxr7s08xwelpjy3cc52rrxg63xsmagv50fa8
|
|
|
AlanJohnson
Member

Offline
Activity: 185
Merit: 11
|
 |
March 31, 2025, 05:56:15 AM |
|
People need something to do in their free time if they have it to spare. It's better than doing drugs, joining a local gang, or staring at their phones, waging troll wars to ruin others' smiles out of pure spite.  But when they finally realize they were throwed into delusion and it was a waste of time and electricity (or maybe money spent on hardware that they don't really need) the can start : "doing drugs, joining a local gang, or staring at their phones, waging troll wars to ruin others' smiles out of pure spite." 
|
|
|
|
|
|
nomachine
|
 |
March 31, 2025, 06:04:18 AM |
|
But when they finally realize they were throwed into delusion ....
I go fishing when I reach that stage, without a phone or internet. When I forget everything, I sit down at the PC again. In between, I grill fish or read books. 
|
BTC: bc1qdwnxr7s08xwelpjy3cc52rrxg63xsmagv50fa8
|
|
|
AlanJohnson
Member

Offline
Activity: 185
Merit: 11
|
 |
March 31, 2025, 06:08:13 AM |
|
But when they finally realize they were throwed into delusion ....
I go fishing when I reach that stage, without a phone or internet. When I forget everything, I sit down at the PC again. In between, I grill fish or read books.  That's the right attitude ! But i guess some people expect they have big chance to win in this lottery and this is their chance to improve life financially ... i guess they can be very dissapointed at some point.
|
|
|
|
|
|