Ottimizza bruteforce con partizionamento keyspace
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user