Ottimizza bruteforce con partizionamento keyspace

This commit is contained in:
2026-01-23 08:59:53 +01:00
parent 4faea99426
commit bbded38ea0

View File

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