From bbded38ea0f436892009b90879f05a38203a28e3 Mon Sep 17 00:00:00 2001 From: davide3011 Date: Fri, 23 Jan 2026 08:59:53 +0100 Subject: [PATCH] Ottimizza bruteforce con partizionamento keyspace --- bruteforce/p2pk_bruteforce.cpp | 102 +++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 24 deletions(-) diff --git a/bruteforce/p2pk_bruteforce.cpp b/bruteforce/p2pk_bruteforce.cpp index 35f1647..37c9dd4 100644 --- a/bruteforce/p2pk_bruteforce.cpp +++ b/bruteforce/p2pk_bruteforce.cpp @@ -52,6 +52,8 @@ static int num_threads = 0; // Numero effettivo di thread da usare struct ThreadData { int thread_id; uint64_t seed; + uint8_t range_start[32]; // Inizio range dello spazio delle chiavi + uint8_t range_end[32]; // Fine range dello spazio delle chiavi }; // Rileva numero di thread/core disponibili @@ -62,6 +64,29 @@ int get_num_threads() { return num; } +// Partiziona lo spazio delle chiavi tra i thread +void partition_keyspace(int thread_id, int total_threads, uint8_t* range_start, uint8_t* range_end) { + // Azzera entrambi gli array + memset(range_start, 0, 32); + memset(range_end, 0xFF, 32); + + // Partiziona usando i primi 8 bytes (64 bit) + // Questo dà 2^64 / total_threads chiavi per thread + uint64_t partition_size = UINT64_MAX / total_threads; + uint64_t start = partition_size * thread_id; + uint64_t end = (thread_id == total_threads - 1) ? UINT64_MAX : (partition_size * (thread_id + 1) - 1); + + // Converti in big-endian per i primi 8 bytes + for (int i = 0; i < 8; i++) { + range_start[i] = (uint8_t)(start >> (56 - i * 8)); + range_end[i] = (uint8_t)(end >> (56 - i * 8)); + } + + // I restanti 24 bytes rimangono: + // range_start[8..31] = 0x00 (minimo) + // range_end[8..31] = 0xFF (massimo) +} + // Signal handler per chiusura pulita void sigint_handler(int sig) { (void)sig; @@ -135,30 +160,36 @@ int load_target_keys(const char* filename) { return count; } -// Genera una chiave privata casuale -void generate_random_privkey(uint8_t* privkey, uint64_t* seed) { - // Usa un PRNG veloce (xorshift64) - *seed ^= *seed << 13; - *seed ^= *seed >> 7; - *seed ^= *seed << 17; - - // Riempi i 32 bytes della privkey - uint64_t* key64 = (uint64_t*)privkey; - for (int i = 0; i < 4; i++) { +// Genera una chiave privata casuale nel range assegnato al thread +void generate_random_privkey_in_range(uint8_t* privkey, uint64_t* seed, + const uint8_t* range_start, const uint8_t* range_end) { + // Usa xorshift64 per generare 32 bytes casuali + for (int i = 0; i < 32; i++) { *seed ^= *seed << 13; *seed ^= *seed >> 7; *seed ^= *seed << 17; - key64[i] = *seed; + privkey[i] = (uint8_t)(*seed & 0xFF); } - // Assicurati che la chiave sia valida (< ordine della curva) - // In pratica, quasi tutti i 256 bit casuali sono validi + // Applica il range: mappa la chiave casuale nel range [range_start, range_end] + // Usa i primi byte del range per definire il prefisso + // I byte successivi sono completamente casuali all'interno del range + for (int i = 0; i < 8; i++) { + // Copia i primi 8 bytes dal range_start per partizionare lo spazio + privkey[i] = range_start[i]; + } + // I restanti 24 bytes (192 bit) sono completamente casuali + // Questo dà ad ogni thread uno spazio di 2^192 chiavi (ancora astronomico) } -// Incrementa la chiave privata -void increment_privkey(uint8_t* privkey) { - for (int i = 31; i >= 0; i--) { - if (++privkey[i] != 0) break; +// Genera chiave completamente casuale (usata come fallback) +void generate_random_privkey(uint8_t* privkey, uint64_t* seed) { + // Usa un PRNG veloce (xorshift64) + for (int i = 0; i < 32; i++) { + *seed ^= *seed << 13; + *seed ^= *seed >> 7; + *seed ^= *seed << 17; + privkey[i] = (uint8_t)(*seed & 0xFF); } } @@ -263,8 +294,8 @@ void* worker_thread(void* arg) { while (keep_running) { // Genera batch di chiavi for (int batch = 0; batch < BATCH_SIZE && keep_running; batch++) { - // Genera chiave privata casuale - generate_random_privkey(privkey, &seed); + // Genera chiave privata casuale nel range assegnato + generate_random_privkey_in_range(privkey, &seed, data->range_start, data->range_end); // Genera chiave pubblica non compressa usando secp256k1 if (secp256k1_ec_pubkey_create(ctx, &pubkey_obj, privkey)) { @@ -280,8 +311,8 @@ void* worker_thread(void* arg) { local_attempts++; - // Incrementa la chiave privata per il prossimo tentativo - increment_privkey(privkey); + // NOTA: Rimosso increment_privkey() - ogni chiave è completamente casuale + // Questo elimina la sovrapposizione tra thread } // Aggiorna contatore globale @@ -340,22 +371,45 @@ int main(int argc, char** argv) { // Rileva numero di thread disponibili num_threads = get_num_threads(); printf("[+] CPU rilevata: %d thread disponibili\n", num_threads); + printf("[+] Partizionamento spazio chiavi in %d regioni\n", num_threads); - // Inizializza timestamp + // Inizializza timestamp e seed base robusto start_time = time(NULL); + srand(time(NULL)); // Crea threads pthread_t threads[MAX_THREADS]; ThreadData thread_data[MAX_THREADS]; - printf("[+] Avvio %d thread worker...\n\n", num_threads); + printf("[+] Avvio %d thread worker...\n", num_threads); for (int i = 0; i < num_threads; i++) { thread_data[i].thread_id = i; - thread_data[i].seed = (uint64_t)time(NULL) + i * 12345; + + // Seed molto distanziati: combina timestamp, thread_id e random + // Questo garantisce seed completamente diversi anche se lanciato rapidamente + uint64_t base_seed = (uint64_t)time(NULL); + uint64_t thread_offset = ((uint64_t)i << 48); // Usa i bit alti + uint64_t random_part = ((uint64_t)rand() << 32) | rand(); + thread_data[i].seed = base_seed ^ thread_offset ^ random_part; + + // Partiziona lo spazio delle chiavi + partition_keyspace(i, num_threads, thread_data[i].range_start, thread_data[i].range_end); + + // Mostra info del range (primi 4 bytes per brevità) + printf(" Thread %d: range 0x%02x%02x%02x%02x... - 0x%02x%02x%02x%02x... (seed: %016lx)\n", + i, + thread_data[i].range_start[0], thread_data[i].range_start[1], + thread_data[i].range_start[2], thread_data[i].range_start[3], + thread_data[i].range_end[0], thread_data[i].range_end[1], + thread_data[i].range_end[2], thread_data[i].range_end[3], + thread_data[i].seed); + pthread_create(&threads[i], NULL, worker_thread, &thread_data[i]); } + printf("\n"); + // Loop principale - mostra progresso while (keep_running) { sleep(10);