mirror of
https://github.com/albertobsd/keyhunt.git
synced 2025-03-17 13:21:46 +01:00
6929 lines
216 KiB
C++
6929 lines
216 KiB
C++
/*
|
|
Develop by Alberto
|
|
email: albertobsd@gmail.com
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
#include <vector>
|
|
#include <inttypes.h>
|
|
#include "base58/libbase58.h"
|
|
#include "oldbloom/oldbloom.h"
|
|
#include "bloom/bloom.h"
|
|
#include "util.h"
|
|
#include "hashing.h"
|
|
|
|
#include "gmp256k1/GMP256K1.h"
|
|
#include "gmp256k1/Point.h"
|
|
#include "gmp256k1/Int.h"
|
|
#include "gmp256k1/IntGroup.h"
|
|
#include "gmp256k1/Random.h"
|
|
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
#include "getopt.h"
|
|
#include <windows.h>
|
|
#else
|
|
#include <unistd.h>
|
|
#include <pthread.h>
|
|
#include <sys/random.h>
|
|
#endif
|
|
|
|
#ifdef __unix__
|
|
#ifdef __CYGWIN__
|
|
#else
|
|
#include <linux/random.h>
|
|
#endif
|
|
#endif
|
|
|
|
#define CRYPTO_NONE 0
|
|
#define CRYPTO_BTC 1
|
|
#define CRYPTO_ETH 2
|
|
#define CRYPTO_ALL 3
|
|
|
|
#define MODE_XPOINT 0
|
|
#define MODE_ADDRESS 1
|
|
#define MODE_BSGS 2
|
|
#define MODE_RMD160 3
|
|
#define MODE_PUB2RMD 4
|
|
#define MODE_MINIKEYS 5
|
|
#define MODE_VANITY 6
|
|
|
|
#define SEARCH_UNCOMPRESS 0
|
|
#define SEARCH_COMPRESS 1
|
|
#define SEARCH_BOTH 2
|
|
|
|
uint32_t THREADBPWORKLOAD = 1048576;
|
|
|
|
struct checksumsha256 {
|
|
char data[32];
|
|
char backup[32];
|
|
};
|
|
|
|
struct bsgs_xvalue {
|
|
uint8_t value[6];
|
|
uint64_t index;
|
|
};
|
|
|
|
struct address_value {
|
|
uint8_t value[20];
|
|
};
|
|
|
|
struct tothread {
|
|
int nt; //Number thread
|
|
char *rs; //range start
|
|
char *rpt; //rng per thread
|
|
};
|
|
|
|
struct bPload {
|
|
uint32_t threadid;
|
|
uint64_t from;
|
|
uint64_t to;
|
|
uint64_t counter;
|
|
uint64_t workload;
|
|
uint32_t aux;
|
|
uint32_t finished;
|
|
};
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop))
|
|
PACK(struct publickey
|
|
{
|
|
uint8_t parity;
|
|
union {
|
|
uint8_t data8[32];
|
|
uint32_t data32[8];
|
|
uint64_t data64[4];
|
|
} X;
|
|
});
|
|
#else
|
|
struct __attribute__((__packed__)) publickey {
|
|
uint8_t parity;
|
|
union {
|
|
uint8_t data8[32];
|
|
uint32_t data32[8];
|
|
uint64_t data64[4];
|
|
} X;
|
|
};
|
|
#endif
|
|
|
|
const char *Ccoinbuffer_default = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
|
|
char *Ccoinbuffer = (char*) Ccoinbuffer_default;
|
|
char *str_baseminikey = NULL;
|
|
char *raw_baseminikey = NULL;
|
|
char *minikeyN = NULL;
|
|
int minikey_n_limit;
|
|
|
|
const char *version = "0.2.230519 Satoshi Quest (legacy)";
|
|
|
|
#define CPU_GRP_SIZE 1024
|
|
//reserve
|
|
std::vector<Point> Gn;
|
|
Point _2Gn;
|
|
|
|
std::vector<Point> GSn;
|
|
Point _2GSn;
|
|
|
|
void menu();
|
|
void init_generator();
|
|
|
|
int searchbinary(struct address_value *buffer,char *data,int64_t array_length);
|
|
void sleep_ms(int milliseconds);
|
|
|
|
void _sort(struct address_value *arr,int64_t N);
|
|
void _insertionsort(struct address_value *arr, int64_t n);
|
|
void _introsort(struct address_value *arr,uint32_t depthLimit, int64_t n);
|
|
void _swap(struct address_value *a,struct address_value *b);
|
|
int64_t _partition(struct address_value *arr, int64_t n);
|
|
void _myheapsort(struct address_value *arr, int64_t n);
|
|
void _heapify(struct address_value *arr, int64_t n, int64_t i);
|
|
|
|
void bsgs_sort(struct bsgs_xvalue *arr,int64_t n);
|
|
void bsgs_myheapsort(struct bsgs_xvalue *arr, int64_t n);
|
|
void bsgs_insertionsort(struct bsgs_xvalue *arr, int64_t n);
|
|
void bsgs_introsort(struct bsgs_xvalue *arr,uint32_t depthLimit, int64_t n);
|
|
void bsgs_swap(struct bsgs_xvalue *a,struct bsgs_xvalue *b);
|
|
void bsgs_heapify(struct bsgs_xvalue *arr, int64_t n, int64_t i);
|
|
int64_t bsgs_partition(struct bsgs_xvalue *arr, int64_t n);
|
|
|
|
int bsgs_searchbinary(struct bsgs_xvalue *arr,char *data,int64_t array_length,uint64_t *r_value);
|
|
int bsgs_secondcheck(Int *start_range,uint32_t a,uint32_t k_index,Int *privatekey);
|
|
int bsgs_thirdcheck(Int *start_range,uint32_t a,uint32_t k_index,Int *privatekey);
|
|
|
|
void sha256sse_22(uint8_t *src0, uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *dst0, uint8_t *dst1, uint8_t *dst2, uint8_t *dst3);
|
|
void sha256sse_23(uint8_t *src0, uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *dst0, uint8_t *dst1, uint8_t *dst2, uint8_t *dst3);
|
|
|
|
bool vanityrmdmatch(unsigned char *rmdhash);
|
|
void writevanitykey(bool compress,Int *key);
|
|
int addvanity(char *target);
|
|
int minimum_same_bytes(unsigned char* A,unsigned char* B, int length);
|
|
|
|
void writekey(bool compressed,Int *key);
|
|
void writekeyeth(Int *key);
|
|
|
|
void checkpointer(void *ptr,const char *file,const char *function,const char *name,int line);
|
|
|
|
bool isBase58(char c);
|
|
bool isValidBase58String(char *str);
|
|
|
|
bool readFileAddress(char *fileName);
|
|
bool readFileVanity(char *fileName);
|
|
bool forceReadFileAddress(char *fileName);
|
|
bool forceReadFileAddressEth(char *fileName);
|
|
bool forceReadFileXPoint(char *fileName);
|
|
bool processOneVanity();
|
|
|
|
bool initBloomFilter(struct bloom *bloom_arg,uint64_t items_bloom);
|
|
|
|
void writeFileIfNeeded(const char *fileName);
|
|
|
|
void calcualteindex(int i,Int *key);
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
DWORD WINAPI thread_process_vanity(LPVOID vargp);
|
|
DWORD WINAPI thread_process_minikeys(LPVOID vargp);
|
|
DWORD WINAPI thread_process(LPVOID vargp);
|
|
DWORD WINAPI thread_process_bsgs(LPVOID vargp);
|
|
DWORD WINAPI thread_process_bsgs_backward(LPVOID vargp);
|
|
DWORD WINAPI thread_process_bsgs_both(LPVOID vargp);
|
|
DWORD WINAPI thread_process_bsgs_random(LPVOID vargp);
|
|
DWORD WINAPI thread_process_bsgs_dance(LPVOID vargp);
|
|
DWORD WINAPI thread_bPload(LPVOID vargp);
|
|
DWORD WINAPI thread_bPload_2blooms(LPVOID vargp);
|
|
DWORD WINAPI thread_pub2rmd(LPVOID vargp);
|
|
#else
|
|
void *thread_process_vanity(void *vargp);
|
|
void *thread_process_minikeys(void *vargp);
|
|
void *thread_process(void *vargp);
|
|
void *thread_process_bsgs(void *vargp);
|
|
void *thread_process_bsgs_backward(void *vargp);
|
|
void *thread_process_bsgs_both(void *vargp);
|
|
void *thread_process_bsgs_random(void *vargp);
|
|
void *thread_process_bsgs_dance(void *vargp);
|
|
void *thread_bPload(void *vargp);
|
|
void *thread_bPload_2blooms(void *vargp);
|
|
void *thread_pub2rmd(void *vargp);
|
|
#endif
|
|
|
|
char *pubkeytopubaddress(char *pkey,int length);
|
|
void pubkeytopubaddress_dst(char *pkey,int length,char *dst);
|
|
void rmd160toaddress_dst(char *rmd,char *dst);
|
|
void set_minikey(char *buffer,char *rawbuffer,int length);
|
|
bool increment_minikey_index(char *buffer,char *rawbuffer,int index);
|
|
void increment_minikey_N(char *rawbuffer);
|
|
|
|
|
|
void generate_binaddress_eth(Point &publickey,unsigned char *dst_address);
|
|
|
|
int THREADOUTPUT = 0;
|
|
char *bit_range_str_min;
|
|
char *bit_range_str_max;
|
|
|
|
const char *bsgs_modes[5] = {"sequential","backward","both","random","dance"};
|
|
const char *modes[7] = {"xpoint","address","bsgs","rmd160","pub2rmd","minikeys","vanity"};
|
|
const char *cryptos[3] = {"btc","eth","all"};
|
|
const char *publicsearch[3] = {"uncompress","compress","both"};
|
|
const char *default_fileName = "addresses.txt";
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
HANDLE* tid = NULL;
|
|
HANDLE write_keys;
|
|
HANDLE write_random;
|
|
HANDLE bsgs_thread;
|
|
HANDLE *bPload_mutex;
|
|
#else
|
|
pthread_t *tid = NULL;
|
|
pthread_mutex_t write_keys;
|
|
pthread_mutex_t write_random;
|
|
pthread_mutex_t bsgs_thread;
|
|
pthread_mutex_t *bPload_mutex;
|
|
#endif
|
|
|
|
uint64_t FINISHED_THREADS_COUNTER = 0;
|
|
uint64_t FINISHED_THREADS_BP = 0;
|
|
uint64_t THREADCYCLES = 0;
|
|
uint64_t THREADCOUNTER = 0;
|
|
uint64_t FINISHED_ITEMS = 0;
|
|
uint64_t OLDFINISHED_ITEMS = -1;
|
|
|
|
uint8_t byte_encode_crypto = 0x00; /* Bitcoin */
|
|
|
|
|
|
int vanity_rmd_targets = 0;
|
|
int vanity_rmd_total = 0;
|
|
int *vanity_rmd_limits = NULL;
|
|
uint8_t ***vanity_rmd_limit_values_A = NULL,***vanity_rmd_limit_values_B = NULL;
|
|
int vanity_rmd_minimun_bytes_check_length = 999999;
|
|
char **vanity_address_targets = NULL;
|
|
struct bloom *vanity_bloom = NULL;
|
|
|
|
struct bloom bloom;
|
|
|
|
uint64_t *steps = NULL;
|
|
unsigned int *ends = NULL;
|
|
uint64_t N = 0;
|
|
|
|
uint64_t N_SEQUENTIAL_MAX = 0x100000000;
|
|
uint64_t DEBUGCOUNT = 0x400;
|
|
uint64_t u64range;
|
|
|
|
Int OUTPUTSECONDS;
|
|
|
|
int FLAGSKIPCHECKSUM = 0;
|
|
int FLAGENDOMORPHISM = 0;
|
|
|
|
int FLAGBLOOMMULTIPLIER = 1;
|
|
int FLAGVANITY = 0;
|
|
int FLAGBASEMINIKEY = 0;
|
|
int FLAGBSGSMODE = 0;
|
|
int FLAGDEBUG = 0;
|
|
int FLAGQUIET = 0;
|
|
int FLAGMATRIX = 0;
|
|
int KFACTOR = 1;
|
|
int MAXLENGTHADDRESS = -1;
|
|
int NTHREADS = 1;
|
|
|
|
int FLAGSAVEREADFILE = 0;
|
|
int FLAGREADEDFILE1 = 0;
|
|
int FLAGREADEDFILE2 = 0;
|
|
int FLAGREADEDFILE3 = 0;
|
|
int FLAGREADEDFILE4 = 0;
|
|
int FLAGUPDATEFILE1 = 0;
|
|
|
|
|
|
int FLAGSTRIDE = 0;
|
|
int FLAGSEARCH = 2;
|
|
int FLAGBITRANGE = 0;
|
|
int FLAGRANGE = 0;
|
|
int FLAGFILE = 0;
|
|
int FLAGMODE = MODE_ADDRESS;
|
|
int FLAGCRYPTO = 0;
|
|
int FLAGRAWDATA = 0;
|
|
int FLAGRANDOM = 0;
|
|
int FLAG_N = 0;
|
|
int FLAGPRECALCUTED_P_FILE = 0;
|
|
|
|
int bitrange;
|
|
char *str_N;
|
|
char *range_start;
|
|
char *range_end;
|
|
char *str_stride;
|
|
Int stride;
|
|
|
|
uint64_t BSGS_XVALUE_RAM = 6;
|
|
uint64_t BSGS_BUFFERXPOINTLENGTH = 32;
|
|
uint64_t BSGS_BUFFERREGISTERLENGTH = 36;
|
|
|
|
/*
|
|
BSGS Variables
|
|
*/
|
|
int *bsgs_found;
|
|
std::vector<Point> OriginalPointsBSGS;
|
|
bool *OriginalPointsBSGScompressed;
|
|
|
|
uint64_t bytes;
|
|
char checksum[32],checksum_backup[32];
|
|
char buffer_bloom_file[1024];
|
|
struct bsgs_xvalue *bPtable;
|
|
struct address_value *addressTable;
|
|
|
|
struct oldbloom oldbloom_bP;
|
|
|
|
struct bloom *bloom_bP;
|
|
struct bloom *bloom_bPx2nd; //2nd Bloom filter check
|
|
struct bloom *bloom_bPx3rd; //3rd Bloom filter check
|
|
|
|
struct checksumsha256 *bloom_bP_checksums;
|
|
struct checksumsha256 *bloom_bPx2nd_checksums;
|
|
struct checksumsha256 *bloom_bPx3rd_checksums;
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
std::vector<HANDLE> bloom_bP_mutex;
|
|
std::vector<HANDLE> bloom_bPx2nd_mutex;
|
|
std::vector<HANDLE> bloom_bPx3rd_mutex;
|
|
#else
|
|
pthread_mutex_t *bloom_bP_mutex;
|
|
pthread_mutex_t *bloom_bPx2nd_mutex;
|
|
pthread_mutex_t *bloom_bPx3rd_mutex;
|
|
#endif
|
|
|
|
|
|
|
|
|
|
uint64_t bloom_bP_totalbytes = 0;
|
|
uint64_t bloom_bP2_totalbytes = 0;
|
|
uint64_t bloom_bP3_totalbytes = 0;
|
|
uint64_t bsgs_m = 4194304;
|
|
uint64_t bsgs_m2;
|
|
uint64_t bsgs_m3;
|
|
unsigned long int bsgs_aux;
|
|
uint32_t bsgs_point_number;
|
|
|
|
const char *str_limits_prefixs[7] = {"Mkeys/s","Gkeys/s","Tkeys/s","Pkeys/s","Ekeys/s","Zkeys/s","Ykeys/s"};
|
|
const char *str_limits[7] = {"1000000","1000000000","1000000000000","1000000000000000","1000000000000000000","1000000000000000000000","1000000000000000000000000"};
|
|
Int int_limits[7];
|
|
|
|
|
|
|
|
|
|
Int BSGS_GROUP_SIZE;
|
|
Int BSGS_CURRENT;
|
|
Int BSGS_R;
|
|
Int BSGS_AUX;
|
|
Int BSGS_N;
|
|
Int BSGS_N_double;
|
|
Int BSGS_M; //M is squareroot(N)
|
|
Int BSGS_M_double;
|
|
Int BSGS_M2; //M2 is M/32
|
|
Int BSGS_M2_double; //M2_double is M2 * 2
|
|
Int BSGS_M3; //M3 is M2/32
|
|
Int BSGS_M3_double; //M3_double is M3 * 2
|
|
|
|
Int ONE;
|
|
Int ZERO;
|
|
Int MPZAUX;
|
|
|
|
Point BSGS_P; //Original P is actually G, but this P value change over time for calculations
|
|
Point BSGS_MP; //MP values this is m * P
|
|
Point BSGS_MP2; //MP2 values this is m2 * P
|
|
Point BSGS_MP3; //MP3 values this is m3 * P
|
|
|
|
Point BSGS_MP_double; //MP2 values this is m2 * P * 2
|
|
Point BSGS_MP2_double; //MP2 values this is m2 * P * 2
|
|
Point BSGS_MP3_double; //MP3 values this is m3 * P * 2
|
|
|
|
|
|
|
|
std::vector<Point> BSGS_AMP2;
|
|
std::vector<Point> BSGS_AMP3;
|
|
|
|
Point point_temp,point_temp2; //Temp value for some process
|
|
|
|
Int n_range_start;
|
|
Int n_range_end;
|
|
Int n_range_diff;
|
|
Int n_range_aux;
|
|
|
|
Int lambda,lambda2,beta,beta2;
|
|
|
|
Secp256K1 *secp;
|
|
|
|
int main(int argc, char **argv) {
|
|
char buffer[2048];
|
|
char rawvalue[32];
|
|
struct tothread *tt; //tothread
|
|
Tokenizer t,tokenizerbsgs; //tokenizer
|
|
char *fileName = NULL;
|
|
char *hextemp = NULL;
|
|
char *aux = NULL;
|
|
char *aux2 = NULL;
|
|
char *pointx_str = NULL;
|
|
char *pointy_str = NULL;
|
|
char *str_seconds = NULL;
|
|
char *str_total = NULL;
|
|
char *str_pretotal = NULL;
|
|
char *str_divpretotal = NULL;
|
|
char *bf_ptr = NULL;
|
|
char *bPload_threads_available;
|
|
FILE *fd,*fd_aux1,*fd_aux2,*fd_aux3;
|
|
uint64_t BASE,PERTHREAD_R,itemsbloom,itemsbloom2,itemsbloom3;
|
|
uint32_t finished;
|
|
int i,readed,continue_flag,check_flag,c,salir,index_value;
|
|
Int total,pretotal,debugcount_mpz,seconds,div_pretotal,int_aux,int_r,int_q,int58;
|
|
struct bPload *bPload_temp_ptr;
|
|
size_t rsize;
|
|
//if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); }
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
DWORD s;
|
|
write_keys = CreateMutex(NULL, FALSE, NULL);
|
|
write_random = CreateMutex(NULL, FALSE, NULL);
|
|
bsgs_thread = CreateMutex(NULL, FALSE, NULL);
|
|
#else
|
|
pthread_mutex_init(&write_keys,NULL);
|
|
pthread_mutex_init(&write_random,NULL);
|
|
pthread_mutex_init(&bsgs_thread,NULL);
|
|
int s;
|
|
#endif
|
|
//if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); }
|
|
srand(time(NULL));
|
|
|
|
secp = new Secp256K1();
|
|
secp->Init();
|
|
OUTPUTSECONDS.SetInt32(30);
|
|
ZERO.SetInt32(0);
|
|
ONE.SetInt32(1);
|
|
BSGS_GROUP_SIZE.SetInt32(CPU_GRP_SIZE);
|
|
|
|
int_randominit();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
printf("[+] Version %s, developed by AlbertoBSD\n",version);
|
|
|
|
while ((c = getopt(argc, argv, "deh6MqRSB:b:c:C:E:f:I:k:l:m:N:n:p:r:s:t:v:G:8:z:")) != -1) {
|
|
switch(c) {
|
|
case 'h':
|
|
menu();
|
|
break;
|
|
case '6':
|
|
FLAGSKIPCHECKSUM = 1;
|
|
fprintf(stderr,"[W] Skipping checksums on files\n");
|
|
break;
|
|
case 'B':
|
|
index_value = indexOf(optarg,bsgs_modes,5);
|
|
if(index_value >= 0 && index_value <= 4) {
|
|
FLAGBSGSMODE = index_value;
|
|
//printf("[+] BSGS mode %s\n",optarg);
|
|
}
|
|
else {
|
|
fprintf(stderr,"[W] Ignoring unknow bsgs mode %s\n",optarg);
|
|
}
|
|
break;
|
|
case 'b':
|
|
bitrange = strtol(optarg,NULL,10);
|
|
if(bitrange > 0 && bitrange <=256 ) {
|
|
MPZAUX.Set(&ONE);
|
|
MPZAUX.ShiftL(bitrange-1);
|
|
bit_range_str_min = MPZAUX.GetBase16();
|
|
checkpointer((void *)bit_range_str_min,__FILE__,"malloc","bit_range_str_min" ,__LINE__ -1);
|
|
MPZAUX.Set(&ONE);
|
|
MPZAUX.ShiftL(bitrange);
|
|
if(MPZAUX.IsGreater(&secp->order)) {
|
|
MPZAUX.Set(&secp->order);
|
|
}
|
|
bit_range_str_max = MPZAUX.GetBase16();
|
|
checkpointer((void *)bit_range_str_max,__FILE__,"malloc","bit_range_str_min" ,__LINE__ -1);
|
|
FLAGBITRANGE = 1;
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] invalid bits param: %s.\n",optarg);
|
|
}
|
|
break;
|
|
case 'c':
|
|
index_value = indexOf(optarg,cryptos,3);
|
|
switch(index_value) {
|
|
case 0: //btc
|
|
FLAGCRYPTO = CRYPTO_BTC;
|
|
break;
|
|
case 1: //eth
|
|
FLAGCRYPTO = CRYPTO_ETH;
|
|
printf("[+] Setting search for ETH adddress.\n");
|
|
break;
|
|
/*
|
|
case 2: //all
|
|
FLAGCRYPTO = CRYPTO_ALL;
|
|
break;
|
|
*/
|
|
default:
|
|
FLAGCRYPTO = CRYPTO_NONE;
|
|
fprintf(stderr,"[E] Unknow crypto value %s\n",optarg);
|
|
exit(EXIT_FAILURE);
|
|
break;
|
|
}
|
|
break;
|
|
case 'C':
|
|
if(strlen(optarg) == 22) {
|
|
FLAGBASEMINIKEY = 1;
|
|
str_baseminikey = (char*) malloc(23);
|
|
checkpointer((void *)str_baseminikey,__FILE__,"malloc","str_baseminikey" ,__LINE__ - 1);
|
|
raw_baseminikey = (char*) malloc(23);
|
|
checkpointer((void *)raw_baseminikey,__FILE__,"malloc","raw_baseminikey" ,__LINE__ - 1);
|
|
strncpy(str_baseminikey,optarg,22);
|
|
for(i = 0; i< 21; i++) {
|
|
if(strchr(Ccoinbuffer,str_baseminikey[i+1]) != NULL) {
|
|
raw_baseminikey[i] = (int)(strchr(Ccoinbuffer,str_baseminikey[i+1]) - Ccoinbuffer) % 58;
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] invalid character in minikey\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
}
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] Invalid Minikey length %li : %s\n",strlen(optarg),optarg);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
break;
|
|
case 'd':
|
|
FLAGDEBUG = 1;
|
|
printf("[+] Flag DEBUG enabled\n");
|
|
break;
|
|
case 'e':
|
|
FLAGENDOMORPHISM = 1;
|
|
printf("[+] Endomorphism enabled\n");
|
|
lambda.SetBase16("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72");
|
|
lambda2.SetBase16("ac9c52b33fa3cf1f5ad9e3fd77ed9ba4a880b9fc8ec739c2e0cfc810b51283ce");
|
|
beta.SetBase16("7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee");
|
|
beta2.SetBase16("851695d49a83f8ef919bb86153cbcb16630fb68aed0a766a3ec693d68e6afa40");
|
|
break;
|
|
case 'f':
|
|
FLAGFILE = 1;
|
|
fileName = optarg;
|
|
break;
|
|
case 'I':
|
|
FLAGSTRIDE = 1;
|
|
str_stride = optarg;
|
|
break;
|
|
case 'k':
|
|
KFACTOR = (int)strtol(optarg,NULL,10);
|
|
if(KFACTOR <= 0) {
|
|
KFACTOR = 1;
|
|
}
|
|
printf("[+] K factor %i\n",KFACTOR);
|
|
break;
|
|
|
|
case 'l':
|
|
switch(indexOf(optarg,publicsearch,3)) {
|
|
case SEARCH_UNCOMPRESS:
|
|
FLAGSEARCH = SEARCH_UNCOMPRESS;
|
|
printf("[+] Search uncompress only\n");
|
|
break;
|
|
case SEARCH_COMPRESS:
|
|
FLAGSEARCH = SEARCH_COMPRESS;
|
|
printf("[+] Search compress only\n");
|
|
break;
|
|
case SEARCH_BOTH:
|
|
FLAGSEARCH = SEARCH_BOTH;
|
|
printf("[+] Search both compress and uncompress\n");
|
|
break;
|
|
}
|
|
break;
|
|
case 'M':
|
|
FLAGMATRIX = 1;
|
|
printf("[+] Matrix screen\n");
|
|
break;
|
|
case 'm':
|
|
switch(indexOf(optarg,modes,7)) {
|
|
case MODE_XPOINT: //xpoint
|
|
FLAGMODE = MODE_XPOINT;
|
|
printf("[+] Mode xpoint\n");
|
|
break;
|
|
case MODE_ADDRESS: //address
|
|
FLAGMODE = MODE_ADDRESS;
|
|
printf("[+] Mode address\n");
|
|
break;
|
|
case MODE_BSGS:
|
|
FLAGMODE = MODE_BSGS;
|
|
//printf("[+] Mode BSGS\n");
|
|
break;
|
|
case MODE_RMD160:
|
|
FLAGMODE = MODE_RMD160;
|
|
FLAGCRYPTO = CRYPTO_BTC;
|
|
printf("[+] Mode rmd160\n");
|
|
break;
|
|
case MODE_PUB2RMD:
|
|
FLAGMODE = MODE_PUB2RMD;
|
|
printf("[+] Mode pub2rmd\n");
|
|
break;
|
|
case MODE_MINIKEYS:
|
|
FLAGMODE = MODE_MINIKEYS;
|
|
printf("[+] Mode minikeys\n");
|
|
break;
|
|
case MODE_VANITY:
|
|
FLAGMODE = MODE_VANITY;
|
|
printf("[+] Mode vanity\n");
|
|
if(vanity_bloom == NULL){
|
|
vanity_bloom = (struct bloom*) calloc(1,sizeof(struct bloom));
|
|
checkpointer((void *)vanity_bloom,__FILE__,"calloc","vanity_bloom" ,__LINE__ -1);
|
|
}
|
|
break;
|
|
default:
|
|
fprintf(stderr,"[E] Unknow mode value %s\n",optarg);
|
|
exit(EXIT_FAILURE);
|
|
break;
|
|
}
|
|
break;
|
|
case 'n':
|
|
FLAG_N = 1;
|
|
str_N = optarg;
|
|
break;
|
|
case 'q':
|
|
FLAGQUIET = 1;
|
|
printf("[+] Quiet thread output\n");
|
|
break;
|
|
case 'R':
|
|
printf("[+] Random mode\n");
|
|
FLAGRANDOM = 1;
|
|
FLAGBSGSMODE = 3;
|
|
break;
|
|
case 'r':
|
|
if(optarg != NULL) {
|
|
stringtokenizer(optarg,&t);
|
|
switch(t.n) {
|
|
case 1:
|
|
range_start = nextToken(&t);
|
|
if(isValidHex(range_start)) {
|
|
FLAGRANGE = 1;
|
|
range_end = secp->order.GetBase16();
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] Invalid hexstring : %s.\n",range_start);
|
|
}
|
|
break;
|
|
case 2:
|
|
range_start = nextToken(&t);
|
|
range_end = nextToken(&t);
|
|
if(isValidHex(range_start) && isValidHex(range_end)) {
|
|
FLAGRANGE = 1;
|
|
}
|
|
else {
|
|
if(isValidHex(range_start)) {
|
|
fprintf(stderr,"[E] Invalid hexstring : %s\n",range_start);
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] Invalid hexstring : %s\n",range_end);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
printf("[E] Unknow number of Range Params: %i\n",t.n);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case 's':
|
|
OUTPUTSECONDS.SetBase10(optarg);
|
|
if(OUTPUTSECONDS.IsLower(&ZERO)) {
|
|
OUTPUTSECONDS.SetInt32(30);
|
|
}
|
|
if(OUTPUTSECONDS.IsZero()) {
|
|
printf("[+] Turn off stats output\n");
|
|
}
|
|
else {
|
|
hextemp = OUTPUTSECONDS.GetBase10();
|
|
printf("[+] Stats output every %s seconds\n",hextemp);
|
|
free(hextemp);
|
|
}
|
|
break;
|
|
case 'S':
|
|
FLAGSAVEREADFILE = 1;
|
|
break;
|
|
case 't':
|
|
NTHREADS = strtol(optarg,NULL,10);
|
|
if(NTHREADS <= 0) {
|
|
NTHREADS = 1;
|
|
}
|
|
printf((NTHREADS > 1) ? "[+] Threads : %u\n": "[+] Thread : %u\n",NTHREADS);
|
|
break;
|
|
case 'v':
|
|
FLAGVANITY = 1;
|
|
if(vanity_bloom == NULL){
|
|
vanity_bloom = (struct bloom*) calloc(1,sizeof(struct bloom));
|
|
checkpointer((void *)vanity_bloom,__FILE__,"calloc","vanity_bloom" ,__LINE__ -1);
|
|
}
|
|
if(isValidBase58String(optarg)) {
|
|
if(addvanity(optarg) > 0) {
|
|
printf("[+] Added Vanity search : %s\n",optarg);
|
|
}
|
|
else {
|
|
printf("[+] Vanity search \"%s\" was NOT Added\n",optarg);
|
|
}
|
|
}
|
|
else {
|
|
fprintf(stderr,"[+] The string \"%s\" is not Valid Base58\n",optarg);
|
|
}
|
|
|
|
break;
|
|
case '8':
|
|
if(strlen(optarg) == 58) {
|
|
Ccoinbuffer = optarg;
|
|
printf("[+] Base58 for Minikeys %s\n",Ccoinbuffer);
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] The base58 alphabet must be 58 characters long.\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
break;
|
|
case 'z':
|
|
FLAGBLOOMMULTIPLIER= strtol(optarg,NULL,10);
|
|
if(FLAGBLOOMMULTIPLIER <= 0) {
|
|
FLAGBLOOMMULTIPLIER = 1;
|
|
}
|
|
printf("[+] Bloom Size Multiplier %i\n",FLAGBLOOMMULTIPLIER);
|
|
break;
|
|
default:
|
|
fprintf(stderr,"[E] Unknow opcion -%c\n",c);
|
|
exit(EXIT_FAILURE);
|
|
break;
|
|
}
|
|
}
|
|
//if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); }
|
|
if( FLAGBSGSMODE == MODE_BSGS && FLAGENDOMORPHISM) {
|
|
fprintf(stderr,"[E] Endomorphism doesn't work with BSGS\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
//if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); }
|
|
if( ( FLAGBSGSMODE == MODE_BSGS || FLAGBSGSMODE == MODE_PUB2RMD ) && FLAGSTRIDE) {
|
|
fprintf(stderr,"[E] Stride doesn't work with BSGS, pub2rmd\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if(FLAGSTRIDE) {
|
|
if(str_stride[0] == '0' && str_stride[1] == 'x') {
|
|
stride.SetBase16(str_stride+2);
|
|
}
|
|
else{
|
|
stride.SetBase10(str_stride);
|
|
}
|
|
printf("[+] Stride : %s\n",stride.GetBase10());
|
|
}
|
|
else {
|
|
FLAGSTRIDE = 1;
|
|
stride.Set(&ONE);
|
|
}
|
|
//if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); }
|
|
init_generator();
|
|
//if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); }
|
|
if(FLAGMODE == MODE_BSGS ) {
|
|
printf("[+] Mode BSGS %s\n",bsgs_modes[FLAGBSGSMODE]);
|
|
}
|
|
|
|
if(FLAGFILE == 0) {
|
|
fileName =(char*) default_fileName;
|
|
}
|
|
//if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); }
|
|
if(FLAGMODE == MODE_ADDRESS && FLAGCRYPTO == CRYPTO_NONE) { //When none crypto is defined the default search is for Bitcoin
|
|
FLAGCRYPTO = CRYPTO_BTC;
|
|
printf("[+] Setting search for btc adddress\n");
|
|
}
|
|
if(FLAGRANGE) {
|
|
n_range_start.SetBase16(range_start);
|
|
if(n_range_start.IsZero()) {
|
|
n_range_start.AddOne();
|
|
}
|
|
n_range_end.SetBase16(range_end);
|
|
if(n_range_start.IsEqual(&n_range_end) == false ) {
|
|
if( n_range_start.IsLower(&secp->order) && n_range_end.IsLowerOrEqual(&secp->order) ) {
|
|
if( n_range_start.IsGreater(&n_range_end)) {
|
|
fprintf(stderr,"[W] Opps, start range can't be great than end range. Swapping them\n");
|
|
n_range_aux.Set(&n_range_start);
|
|
n_range_start.Set(&n_range_end);
|
|
n_range_end.Set(&n_range_aux);
|
|
}
|
|
n_range_diff.Set(&n_range_end);
|
|
n_range_diff.Sub(&n_range_start);
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] Start and End range can't be great than N\nFallback to random mode!\n");
|
|
FLAGRANGE = 0;
|
|
}
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] Start and End range can't be the same\nFallback to random mode!\n");
|
|
FLAGRANGE = 0;
|
|
}
|
|
}
|
|
//if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); }
|
|
if(FLAGMODE != MODE_BSGS && FLAGMODE != MODE_MINIKEYS) {
|
|
BSGS_N.SetInt32(DEBUGCOUNT);
|
|
if(FLAGRANGE == 0 && FLAGBITRANGE == 0) {
|
|
n_range_start.SetInt32(1);
|
|
n_range_end.Set(&secp->order);
|
|
n_range_diff.Set(&n_range_end);
|
|
n_range_diff.Sub(&n_range_start);
|
|
}
|
|
else {
|
|
if(FLAGBITRANGE) {
|
|
n_range_start.SetBase16(bit_range_str_min);
|
|
n_range_end.SetBase16(bit_range_str_max);
|
|
n_range_diff.Set(&n_range_end);
|
|
n_range_diff.Sub(&n_range_start);
|
|
}
|
|
else {
|
|
if(FLAGRANGE == 0) {
|
|
fprintf(stderr,"[W] WTF!\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
N = 0;
|
|
//if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); }
|
|
if(FLAGMODE != MODE_BSGS ) {
|
|
if(FLAG_N){
|
|
if(str_N[0] == '0' && str_N[1] == 'x') {
|
|
N_SEQUENTIAL_MAX =strtol(str_N,NULL,16);
|
|
}
|
|
else {
|
|
N_SEQUENTIAL_MAX =strtol(str_N,NULL,10);
|
|
}
|
|
|
|
if(N_SEQUENTIAL_MAX < 1024) {
|
|
fprintf(stderr,"[I] n value need to be equal or great than 1024, back to defaults\n");
|
|
FLAG_N = 0;
|
|
N_SEQUENTIAL_MAX = 0x100000000;
|
|
}
|
|
if(N_SEQUENTIAL_MAX % 1024 != 0) {
|
|
fprintf(stderr,"[I] n value need to be multiplier of 1024\n");
|
|
FLAG_N = 0;
|
|
N_SEQUENTIAL_MAX = 0x100000000;
|
|
}
|
|
}
|
|
printf("[+] N = %p\n",(void*)N_SEQUENTIAL_MAX);
|
|
if(FLAGMODE == MODE_MINIKEYS) {
|
|
BSGS_N.SetInt32(DEBUGCOUNT);
|
|
if(FLAGBASEMINIKEY) {
|
|
printf("[+] Base Minikey : %s\n",str_baseminikey);
|
|
}
|
|
minikeyN = (char*) malloc(22);
|
|
checkpointer((void *)minikeyN,__FILE__,"malloc","minikeyN" ,__LINE__ -1);
|
|
i =0;
|
|
int58.SetInt32(58);
|
|
int_aux.SetInt64(N_SEQUENTIAL_MAX);
|
|
int_aux.Mult(253);
|
|
/* We get approximately one valid mini key for each 256 candidates mini keys since this is only statistics we multiply N_SEQUENTIAL_MAX by 253 to ensure not missed one one candidate minikey between threads... in this approach we repeat from 1 to 3 candidates in each N_SEQUENTIAL_MAX cycle IF YOU FOUND some other workaround please let me know */
|
|
i = 20;
|
|
salir = 0;
|
|
do {
|
|
if(!int_aux.IsZero()) {
|
|
int_r.Set(&int_aux);
|
|
int_r.Mod(&int58);
|
|
int_q.Set(&int_aux);
|
|
minikeyN[i] = (uint8_t)int_r.GetInt64();
|
|
int_q.Sub(&int_r);
|
|
int_q.Div(&int58);
|
|
int_aux.Set(&int_q);
|
|
i--;
|
|
}
|
|
else {
|
|
salir =1;
|
|
}
|
|
}while(!salir && i > 0);
|
|
minikey_n_limit = 21 -i;
|
|
}
|
|
else {
|
|
if(FLAGBITRANGE) { // Bit Range
|
|
printf("[+] Bit Range %i\n",bitrange);
|
|
}
|
|
else {
|
|
printf("[+] Range \n");
|
|
}
|
|
}
|
|
if(FLAGMODE != MODE_MINIKEYS) {
|
|
hextemp = n_range_start.GetBase16();
|
|
printf("[+] -- from : 0x%s\n",hextemp);
|
|
free(hextemp);
|
|
hextemp = n_range_end.GetBase16();
|
|
printf("[+] -- to : 0x%s\n",hextemp);
|
|
free(hextemp);
|
|
}
|
|
|
|
switch(FLAGMODE) {
|
|
case MODE_MINIKEYS:
|
|
case MODE_PUB2RMD:
|
|
case MODE_RMD160:
|
|
case MODE_ADDRESS:
|
|
case MODE_XPOINT:
|
|
if(!readFileAddress(fileName)) {
|
|
fprintf(stderr,"[E] Unenexpected error\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
break;
|
|
case MODE_VANITY:
|
|
if(!readFileVanity(fileName)) {
|
|
fprintf(stderr,"[E] Unenexpected error\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
break;
|
|
}
|
|
//if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); }
|
|
if(FLAGMODE != MODE_VANITY && !FLAGREADEDFILE1) {
|
|
printf("[+] Sorting data ...");
|
|
_sort(addressTable,N);
|
|
printf(" done! %" PRIu64 " values were loaded and sorted\n",N);
|
|
writeFileIfNeeded(fileName);
|
|
}
|
|
}
|
|
//if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); }
|
|
if(FLAGMODE == MODE_BSGS ) {
|
|
printf("[+] Opening file %s\n",fileName);
|
|
fd = fopen(fileName,"rb");
|
|
if(fd == NULL) {
|
|
fprintf(stderr,"[E] Can't open file %s\n",fileName);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
aux = (char*) malloc(1024);
|
|
checkpointer((void *)aux,__FILE__,"malloc","aux" ,__LINE__ - 1);
|
|
while(!feof(fd)) {
|
|
if(fgets(aux,1022,fd) == aux) {
|
|
trim(aux," \t\n\r");
|
|
if(strlen(aux) >= 128) { //Length of a full address in hexadecimal without 04
|
|
N++;
|
|
}else {
|
|
if(strlen(aux) >= 66) {
|
|
N++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(N == 0) {
|
|
fprintf(stderr,"[E] There is no valid data in the file\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
bsgs_found = (int*) calloc(N,sizeof(int));
|
|
checkpointer((void *)bsgs_found,__FILE__,"calloc","bsgs_found" ,__LINE__ -1 );
|
|
OriginalPointsBSGS.resize(N,secp->G);
|
|
OriginalPointsBSGScompressed = (bool*) malloc(N*sizeof(bool));
|
|
checkpointer((void *)OriginalPointsBSGScompressed,__FILE__,"malloc","OriginalPointsBSGScompressed" ,__LINE__ -1 );
|
|
pointx_str = (char*) malloc(65);
|
|
checkpointer((void *)pointx_str,__FILE__,"malloc","pointx_str" ,__LINE__ -1 );
|
|
pointy_str = (char*) malloc(65);
|
|
checkpointer((void *)pointy_str,__FILE__,"malloc","pointy_str" ,__LINE__ -1 );
|
|
fseek(fd,0,SEEK_SET);
|
|
i = 0;
|
|
while(!feof(fd)) {
|
|
if(fgets(aux,1022,fd) == aux) {
|
|
trim(aux," \t\n\r");
|
|
if(strlen(aux) >= 66) {
|
|
stringtokenizer(aux,&tokenizerbsgs);
|
|
aux2 = nextToken(&tokenizerbsgs);
|
|
memset(pointx_str,0,65);
|
|
memset(pointy_str,0,65);
|
|
switch(strlen(aux2)) {
|
|
case 66: //Compress
|
|
if(secp->ParsePublicKeyHex(aux2,OriginalPointsBSGS[i],OriginalPointsBSGScompressed[i])) {
|
|
i++;
|
|
}
|
|
else {
|
|
N--;
|
|
}
|
|
|
|
break;
|
|
case 130: //With the 04
|
|
|
|
if(secp->ParsePublicKeyHex(aux2,OriginalPointsBSGS[i],OriginalPointsBSGScompressed[i])) {
|
|
i++;
|
|
}
|
|
else {
|
|
N--;
|
|
}
|
|
|
|
break;
|
|
default:
|
|
printf("Invalid length: %s\n",aux2);
|
|
N--;
|
|
break;
|
|
}
|
|
freetokenizer(&tokenizerbsgs);
|
|
}
|
|
}
|
|
}
|
|
fclose(fd);
|
|
bsgs_point_number = N;
|
|
if(bsgs_point_number > 0) {
|
|
printf("[+] Added %u points from file\n",bsgs_point_number);
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] The file don't have any valid publickeys\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
BSGS_N.SetInt32(0);
|
|
BSGS_M.SetInt32(0);
|
|
|
|
|
|
BSGS_M.SetInt64(bsgs_m);
|
|
|
|
|
|
if(FLAG_N) { //Custom N by the -n param
|
|
|
|
/* Here we need to validate if the given string is a valid hexadecimal number or a base 10 number*/
|
|
|
|
/* Now the conversion*/
|
|
if(str_N[0] == '0' && str_N[1] == 'x' ) { /*We expected a hexadecimal value after 0x -> str_N +2 */
|
|
BSGS_N.SetBase16((char*)(str_N+2));
|
|
}
|
|
else {
|
|
BSGS_N.SetBase10(str_N);
|
|
}
|
|
|
|
}
|
|
else { //Default N
|
|
BSGS_N.SetInt64((uint64_t)0x100000000000);
|
|
}
|
|
|
|
if(BSGS_N.HasSqrt()) { //If the root is exact
|
|
BSGS_M.Set(&BSGS_N);
|
|
BSGS_M.ModSqrt();
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] -n param doesn't have exact square root\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
BSGS_AUX.Set(&BSGS_M);
|
|
BSGS_AUX.Mod(&BSGS_GROUP_SIZE);
|
|
|
|
if(!BSGS_AUX.IsZero()){ //If M is not divisible by BSGS_GROUP_SIZE (1024)
|
|
hextemp = BSGS_GROUP_SIZE.GetBase10();
|
|
fprintf(stderr,"[E] M value is not divisible by %s\n",hextemp);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
bsgs_m = BSGS_M.GetInt64();
|
|
|
|
if(FLAGRANGE || FLAGBITRANGE) {
|
|
if(FLAGBITRANGE) { // Bit Range
|
|
n_range_start.SetBase16(bit_range_str_min);
|
|
n_range_end.SetBase16(bit_range_str_max);
|
|
|
|
n_range_diff.Set(&n_range_end);
|
|
n_range_diff.Sub(&n_range_start);
|
|
printf("[+] Bit Range %i\n",bitrange);
|
|
printf("[+] -- from : 0x%s\n",bit_range_str_min);
|
|
printf("[+] -- to : 0x%s\n",bit_range_str_max);
|
|
}
|
|
else {
|
|
printf("[+] Range \n");
|
|
printf("[+] -- from : 0x%s\n",range_start);
|
|
printf("[+] -- to : 0x%s\n",range_end);
|
|
}
|
|
}
|
|
else { //Random start
|
|
|
|
n_range_start.SetInt32(1);
|
|
n_range_end.Set(&secp->order);
|
|
n_range_diff.Rand(&n_range_start,&n_range_end);
|
|
n_range_start.Set(&n_range_diff);
|
|
}
|
|
BSGS_CURRENT.Set(&n_range_start);
|
|
|
|
|
|
if(n_range_diff.IsLower(&BSGS_N) ) {
|
|
fprintf(stderr,"[E] the given range is small\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
/*
|
|
M 2199023255552
|
|
109951162777.6
|
|
M2 109951162778
|
|
5497558138.9
|
|
M3 5497558139
|
|
*/
|
|
|
|
BSGS_M.Mult((uint64_t)KFACTOR);
|
|
BSGS_AUX.SetInt32(32);
|
|
BSGS_R.Set(&BSGS_M);
|
|
BSGS_R.Mod(&BSGS_AUX);
|
|
BSGS_M2.Set(&BSGS_M);
|
|
BSGS_M2.Div(&BSGS_AUX);
|
|
|
|
if(!BSGS_R.IsZero()) { /* If BSGS_M modulo 32 is not 0*/
|
|
BSGS_M2.AddOne();
|
|
}
|
|
|
|
|
|
BSGS_M_double.SetInt32(2);
|
|
BSGS_M_double.Mult(&BSGS_M);
|
|
|
|
|
|
BSGS_M2_double.SetInt32(2);
|
|
BSGS_M2_double.Mult(&BSGS_M2);
|
|
|
|
BSGS_R.Set(&BSGS_M2);
|
|
BSGS_R.Mod(&BSGS_AUX);
|
|
|
|
BSGS_M3.Set(&BSGS_M2);
|
|
BSGS_M3.Div(&BSGS_AUX);
|
|
|
|
if(!BSGS_R.IsZero()) { /* If BSGS_M2 modulo 32 is not 0*/
|
|
BSGS_M3.AddOne();
|
|
}
|
|
|
|
BSGS_M3_double.SetInt32(2);
|
|
BSGS_M3_double.Mult(&BSGS_M3);
|
|
|
|
bsgs_m2 = BSGS_M2.GetInt64();
|
|
bsgs_m3 = BSGS_M3.GetInt64();
|
|
|
|
BSGS_AUX.Set(&BSGS_N);
|
|
BSGS_AUX.Div(&BSGS_M);
|
|
|
|
BSGS_R.Set(&BSGS_N);
|
|
BSGS_R.Mod(&BSGS_M);
|
|
|
|
if(!BSGS_R.IsZero()) { /* if BSGS_N modulo BSGS_M is not 0*/
|
|
BSGS_N.Set(&BSGS_M);
|
|
BSGS_N.Mult(&BSGS_AUX);
|
|
}
|
|
|
|
bsgs_m = BSGS_M.GetInt64();
|
|
bsgs_aux = BSGS_AUX.GetInt64();
|
|
|
|
BSGS_N_double.SetInt32(2);
|
|
BSGS_N_double.Mult(&BSGS_N);
|
|
|
|
hextemp = BSGS_N.GetBase16();
|
|
printf("[+] N = 0x%s\n",hextemp);
|
|
free(hextemp);
|
|
if(((uint64_t)(bsgs_m/256)) > 10000) {
|
|
itemsbloom = (uint64_t)(bsgs_m / 256);
|
|
if(bsgs_m % 256 != 0 ) {
|
|
itemsbloom++;
|
|
}
|
|
}
|
|
else{
|
|
itemsbloom = 1000;
|
|
}
|
|
|
|
if(((uint64_t)(bsgs_m2/256)) > 1000) {
|
|
itemsbloom2 = (uint64_t)(bsgs_m2 / 256);
|
|
if(bsgs_m2 % 256 != 0) {
|
|
itemsbloom2++;
|
|
}
|
|
}
|
|
else {
|
|
itemsbloom2 = 1000;
|
|
}
|
|
|
|
if(((uint64_t)(bsgs_m3/256)) > 1000) {
|
|
itemsbloom3 = (uint64_t)(bsgs_m3/256);
|
|
if(bsgs_m3 % 256 != 0 ) {
|
|
itemsbloom3++;
|
|
}
|
|
}
|
|
else {
|
|
itemsbloom3 = 1000;
|
|
}
|
|
|
|
printf("[+] Bloom filter for %" PRIu64 " elements ",bsgs_m);
|
|
bloom_bP = (struct bloom*)calloc(256,sizeof(struct bloom));
|
|
checkpointer((void *)bloom_bP,__FILE__,"calloc","bloom_bP" ,__LINE__ -1 );
|
|
bloom_bP_checksums = (struct checksumsha256*)calloc(256,sizeof(struct checksumsha256));
|
|
checkpointer((void *)bloom_bP_checksums,__FILE__,"calloc","bloom_bP_checksums" ,__LINE__ -1 );
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
bloom_bP_mutex = (HANDLE*) calloc(256,sizeof(HANDLE));
|
|
|
|
#else
|
|
bloom_bP_mutex = (pthread_mutex_t*) calloc(256,sizeof(pthread_mutex_t));
|
|
#endif
|
|
checkpointer((void *)bloom_bP_mutex,__FILE__,"calloc","bloom_bP_mutex" ,__LINE__ -1 );
|
|
|
|
|
|
fflush(stdout);
|
|
bloom_bP_totalbytes = 0;
|
|
for(i=0; i< 256; i++) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
bloom_bP_mutex[i] = CreateMutex(NULL, FALSE, NULL);
|
|
#else
|
|
pthread_mutex_init(&bloom_bP_mutex[i],NULL);
|
|
#endif
|
|
if(bloom_init2(&bloom_bP[i],itemsbloom,0.000001) == 1){
|
|
fprintf(stderr,"[E] error bloom_init _ [%i]\n",i);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
bloom_bP_totalbytes += bloom_bP[i].bytes;
|
|
//if(FLAGDEBUG) bloom_print(&bloom_bP[i]);
|
|
}
|
|
printf(": %.2f MB\n",(float)((float)(uint64_t)bloom_bP_totalbytes/(float)(uint64_t)1048576));
|
|
|
|
|
|
printf("[+] Bloom filter for %" PRIu64 " elements ",bsgs_m2);
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
bloom_bPx2nd_mutex = (HANDLE*) calloc(256,sizeof(HANDLE));
|
|
#else
|
|
bloom_bPx2nd_mutex = (pthread_mutex_t*) calloc(256,sizeof(pthread_mutex_t));
|
|
#endif
|
|
checkpointer((void *)bloom_bPx2nd_mutex,__FILE__,"calloc","bloom_bPx2nd_mutex" ,__LINE__ -1 );
|
|
bloom_bPx2nd = (struct bloom*)calloc(256,sizeof(struct bloom));
|
|
checkpointer((void *)bloom_bPx2nd,__FILE__,"calloc","bloom_bPx2nd" ,__LINE__ -1 );
|
|
bloom_bPx2nd_checksums = (struct checksumsha256*) calloc(256,sizeof(struct checksumsha256));
|
|
checkpointer((void *)bloom_bPx2nd_checksums,__FILE__,"calloc","bloom_bPx2nd_checksums" ,__LINE__ -1 );
|
|
bloom_bP2_totalbytes = 0;
|
|
for(i=0; i< 256; i++) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
bloom_bPx2nd_mutex[i] = CreateMutex(NULL, FALSE, NULL);
|
|
#else
|
|
pthread_mutex_init(&bloom_bPx2nd_mutex[i],NULL);
|
|
#endif
|
|
if(bloom_init2(&bloom_bPx2nd[i],itemsbloom2,0.000001) == 1){
|
|
fprintf(stderr,"[E] error bloom_init _ [%i]\n",i);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
bloom_bP2_totalbytes += bloom_bPx2nd[i].bytes;
|
|
//if(FLAGDEBUG) bloom_print(&bloom_bPx2nd[i]);
|
|
}
|
|
printf(": %.2f MB\n",(float)((float)(uint64_t)bloom_bP2_totalbytes/(float)(uint64_t)1048576));
|
|
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
bloom_bPx3rd_mutex = (HANDLE*) calloc(256,sizeof(HANDLE));
|
|
#else
|
|
bloom_bPx3rd_mutex = (pthread_mutex_t*) calloc(256,sizeof(pthread_mutex_t));
|
|
#endif
|
|
checkpointer((void *)bloom_bPx3rd_mutex,__FILE__,"calloc","bloom_bPx3rd_mutex" ,__LINE__ -1 );
|
|
bloom_bPx3rd = (struct bloom*)calloc(256,sizeof(struct bloom));
|
|
checkpointer((void *)bloom_bPx3rd,__FILE__,"calloc","bloom_bPx3rd" ,__LINE__ -1 );
|
|
bloom_bPx3rd_checksums = (struct checksumsha256*) calloc(256,sizeof(struct checksumsha256));
|
|
checkpointer((void *)bloom_bPx3rd_checksums,__FILE__,"calloc","bloom_bPx3rd_checksums" ,__LINE__ -1 );
|
|
|
|
printf("[+] Bloom filter for %" PRIu64 " elements ",bsgs_m3);
|
|
bloom_bP3_totalbytes = 0;
|
|
for(i=0; i< 256; i++) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
bloom_bPx3rd_mutex[i] = CreateMutex(NULL, FALSE, NULL);
|
|
#else
|
|
pthread_mutex_init(&bloom_bPx3rd_mutex[i],NULL);
|
|
#endif
|
|
if(bloom_init2(&bloom_bPx3rd[i],itemsbloom3,0.000001) == 1){
|
|
fprintf(stderr,"[E] error bloom_init [%i]\n",i);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
bloom_bP3_totalbytes += bloom_bPx3rd[i].bytes;
|
|
//if(FLAGDEBUG) bloom_print(&bloom_bPx3rd[i]);
|
|
}
|
|
printf(": %.2f MB\n",(float)((float)(uint64_t)bloom_bP3_totalbytes/(float)(uint64_t)1048576));
|
|
//if(FLAGDEBUG) printf("[D] bloom_bP3_totalbytes : %" PRIu64 "\n",bloom_bP3_totalbytes);
|
|
|
|
BSGS_MP = secp->ComputePublicKey(&BSGS_M);
|
|
BSGS_MP_double = secp->ComputePublicKey(&BSGS_M_double);
|
|
BSGS_MP2 = secp->ComputePublicKey(&BSGS_M2);
|
|
BSGS_MP2_double = secp->ComputePublicKey(&BSGS_M2_double);
|
|
BSGS_MP3 = secp->ComputePublicKey(&BSGS_M3);
|
|
BSGS_MP3_double = secp->ComputePublicKey(&BSGS_M3_double);
|
|
|
|
i= 0;
|
|
|
|
/* New aMP table just to keep the same code of JLP */
|
|
/* Auxiliar Points to speed up calculations for the main bloom filter check */
|
|
Point bsP = secp->Negation(BSGS_MP_double);
|
|
Point g = bsP;
|
|
GSn.resize(CPU_GRP_SIZE/2,g);
|
|
BSGS_AMP2.resize(32,g);
|
|
BSGS_AMP3.resize(32,g);
|
|
|
|
GSn[0] = g;
|
|
|
|
g = secp->DoubleDirect(g);
|
|
GSn[1] = g;
|
|
|
|
for(int i = 2; i < CPU_GRP_SIZE / 2; i++) {
|
|
g = secp->AddDirect(g,bsP);
|
|
GSn[i] = g;
|
|
}
|
|
|
|
/* For next center point */
|
|
_2GSn = secp->DoubleDirect(GSn[CPU_GRP_SIZE / 2 - 1]);
|
|
|
|
i = 0;
|
|
point_temp.Set(BSGS_MP2);
|
|
BSGS_AMP2[0] = secp->Negation(point_temp);
|
|
BSGS_AMP2[0].Reduce();
|
|
point_temp.Set(BSGS_MP2_double);
|
|
point_temp = secp->Negation(point_temp);
|
|
point_temp.Reduce();
|
|
|
|
for(i = 1; i < 32; i++) {
|
|
BSGS_AMP2[i] = secp->AddDirect(BSGS_AMP2[i-1],point_temp);
|
|
BSGS_AMP2[i].Reduce();
|
|
}
|
|
|
|
i = 0;
|
|
point_temp.Set(BSGS_MP3);
|
|
BSGS_AMP3[0] = secp->Negation(point_temp);
|
|
BSGS_AMP3[0].Reduce();
|
|
point_temp.Set(BSGS_MP3_double);
|
|
point_temp = secp->Negation(point_temp);
|
|
point_temp.Reduce();
|
|
|
|
for(i = 1; i < 32; i++) {
|
|
BSGS_AMP3[i] = secp->AddDirect(BSGS_AMP3[i-1],point_temp);
|
|
BSGS_AMP3[i].Reduce();
|
|
}
|
|
|
|
bytes = (uint64_t)bsgs_m3 * (uint64_t) sizeof(struct bsgs_xvalue);
|
|
printf("[+] Allocating %.2f MB for %" PRIu64 " bP Points\n",(double)(bytes/1048576),bsgs_m3);
|
|
|
|
bPtable = (struct bsgs_xvalue*) malloc(bytes);
|
|
checkpointer((void *)bPtable,__FILE__,"malloc","bPtable" ,__LINE__ -1 );
|
|
memset(bPtable,0,bytes);
|
|
|
|
if(FLAGSAVEREADFILE) {
|
|
/*Reading file for 1st bloom filter */
|
|
|
|
snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_4_%" PRIu64 ".blm",bsgs_m);
|
|
fd_aux1 = fopen(buffer_bloom_file,"rb");
|
|
if(fd_aux1 != NULL) {
|
|
printf("[+] Reading bloom filter from file %s ",buffer_bloom_file);
|
|
fflush(stdout);
|
|
for(i = 0; i < 256;i++) {
|
|
bf_ptr = (char*) bloom_bP[i].bf; /*We need to save the current bf pointer*/
|
|
readed = fread(&bloom_bP[i],sizeof(struct bloom),1,fd_aux1);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
bloom_bP[i].bf = (uint8_t*)bf_ptr; /* Restoring the bf pointer*/
|
|
readed = fread(bloom_bP[i].bf,bloom_bP[i].bytes,1,fd_aux1);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
readed = fread(&bloom_bP_checksums[i],sizeof(struct checksumsha256),1,fd_aux1);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if(FLAGSKIPCHECKSUM == 0) {
|
|
sha256((uint8_t*)bloom_bP[i].bf,bloom_bP[i].bytes,(uint8_t*)rawvalue);
|
|
if(memcmp(bloom_bP_checksums[i].data,rawvalue,32) != 0 || memcmp(bloom_bP_checksums[i].backup,rawvalue,32) != 0 ) { /* Verification */
|
|
fprintf(stderr,"[E] Error checksum file mismatch! %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
if(i % 64 == 0 ) {
|
|
printf(".");
|
|
fflush(stdout);
|
|
}
|
|
}
|
|
printf(" Done!\n");
|
|
fclose(fd_aux1);
|
|
memset(buffer_bloom_file,0,1024);
|
|
snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_3_%" PRIu64 ".blm",bsgs_m);
|
|
fd_aux1 = fopen(buffer_bloom_file,"rb");
|
|
if(fd_aux1 != NULL) {
|
|
printf("[W] Unused file detected %s you can delete it without worry\n",buffer_bloom_file);
|
|
fclose(fd_aux1);
|
|
}
|
|
FLAGREADEDFILE1 = 1;
|
|
}
|
|
else { /*Checking for old file keyhunt_bsgs_3_ */
|
|
snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_3_%" PRIu64 ".blm",bsgs_m);
|
|
fd_aux1 = fopen(buffer_bloom_file,"rb");
|
|
if(fd_aux1 != NULL) {
|
|
printf("[+] Reading bloom filter from file %s ",buffer_bloom_file);
|
|
fflush(stdout);
|
|
for(i = 0; i < 256;i++) {
|
|
bf_ptr = (char*) bloom_bP[i].bf; /*We need to save the current bf pointer*/
|
|
readed = fread(&oldbloom_bP,sizeof(struct oldbloom),1,fd_aux1);
|
|
|
|
/*
|
|
if(FLAGDEBUG) {
|
|
printf("old Bloom filter %i\n",i);
|
|
oldbloom_print(&oldbloom_bP);
|
|
}
|
|
*/
|
|
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
memcpy(&bloom_bP[i],&oldbloom_bP,sizeof(struct bloom));//We only need to copy the part data to the new bloom size, not from the old size
|
|
bloom_bP[i].bf = (uint8_t*)bf_ptr; /* Restoring the bf pointer*/
|
|
|
|
readed = fread(bloom_bP[i].bf,bloom_bP[i].bytes,1,fd_aux1);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
memcpy(bloom_bP_checksums[i].data,oldbloom_bP.checksum,32);
|
|
memcpy(bloom_bP_checksums[i].backup,oldbloom_bP.checksum_backup,32);
|
|
memset(rawvalue,0,32);
|
|
if(FLAGSKIPCHECKSUM == 0) {
|
|
sha256((uint8_t*)bloom_bP[i].bf,bloom_bP[i].bytes,(uint8_t*)rawvalue);
|
|
if(memcmp(bloom_bP_checksums[i].data,rawvalue,32) != 0 || memcmp(bloom_bP_checksums[i].backup,rawvalue,32) != 0 ) { /* Verification */
|
|
fprintf(stderr,"[E] Error checksum file mismatch! %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
if(i % 32 == 0 ) {
|
|
printf(".");
|
|
fflush(stdout);
|
|
}
|
|
}
|
|
printf(" Done!\n");
|
|
fclose(fd_aux1);
|
|
FLAGUPDATEFILE1 = 1; /* Flag to migrate the data to the new File keyhunt_bsgs_4_ */
|
|
FLAGREADEDFILE1 = 1;
|
|
|
|
}
|
|
else {
|
|
FLAGREADEDFILE1 = 0;
|
|
//Flag to make the new file
|
|
}
|
|
}
|
|
|
|
/*Reading file for 2nd bloom filter */
|
|
snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_6_%" PRIu64 ".blm",bsgs_m2);
|
|
fd_aux2 = fopen(buffer_bloom_file,"rb");
|
|
if(fd_aux2 != NULL) {
|
|
printf("[+] Reading bloom filter from file %s ",buffer_bloom_file);
|
|
fflush(stdout);
|
|
for(i = 0; i < 256;i++) {
|
|
bf_ptr = (char*) bloom_bPx2nd[i].bf; /*We need to save the current bf pointer*/
|
|
readed = fread(&bloom_bPx2nd[i],sizeof(struct bloom),1,fd_aux2);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
bloom_bPx2nd[i].bf = (uint8_t*)bf_ptr; /* Restoring the bf pointer*/
|
|
readed = fread(bloom_bPx2nd[i].bf,bloom_bPx2nd[i].bytes,1,fd_aux2);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
readed = fread(&bloom_bPx2nd_checksums[i],sizeof(struct checksumsha256),1,fd_aux2);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
memset(rawvalue,0,32);
|
|
if(FLAGSKIPCHECKSUM == 0) {
|
|
sha256((uint8_t*)bloom_bPx2nd[i].bf,bloom_bPx2nd[i].bytes,(uint8_t*)rawvalue);
|
|
if(memcmp(bloom_bPx2nd_checksums[i].data,rawvalue,32) != 0 || memcmp(bloom_bPx2nd_checksums[i].backup,rawvalue,32) != 0 ) { /* Verification */
|
|
fprintf(stderr,"[E] Error checksum file mismatch! %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
if(i % 64 == 0) {
|
|
printf(".");
|
|
fflush(stdout);
|
|
}
|
|
}
|
|
fclose(fd_aux2);
|
|
printf(" Done!\n");
|
|
memset(buffer_bloom_file,0,1024);
|
|
snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_5_%" PRIu64 ".blm",bsgs_m2);
|
|
fd_aux2 = fopen(buffer_bloom_file,"rb");
|
|
if(fd_aux2 != NULL) {
|
|
printf("[W] Unused file detected %s you can delete it without worry\n",buffer_bloom_file);
|
|
fclose(fd_aux2);
|
|
}
|
|
memset(buffer_bloom_file,0,1024);
|
|
snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_1_%" PRIu64 ".blm",bsgs_m2);
|
|
fd_aux2 = fopen(buffer_bloom_file,"rb");
|
|
if(fd_aux2 != NULL) {
|
|
printf("[W] Unused file detected %s you can delete it without worry\n",buffer_bloom_file);
|
|
fclose(fd_aux2);
|
|
}
|
|
FLAGREADEDFILE2 = 1;
|
|
}
|
|
else {
|
|
FLAGREADEDFILE2 = 0;
|
|
}
|
|
|
|
/*Reading file for bPtable */
|
|
snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_2_%" PRIu64 ".tbl",bsgs_m3);
|
|
fd_aux3 = fopen(buffer_bloom_file,"rb");
|
|
if(fd_aux3 != NULL) {
|
|
printf("[+] Reading bP Table from file %s .",buffer_bloom_file);
|
|
fflush(stdout);
|
|
rsize = fread(bPtable,bytes,1,fd_aux3);
|
|
if(rsize != 1) {
|
|
fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
rsize = fread(checksum,32,1,fd_aux3);
|
|
if(rsize != 1) {
|
|
fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if(FLAGSKIPCHECKSUM == 0) {
|
|
sha256((uint8_t*)bPtable,bytes,(uint8_t*)checksum_backup);
|
|
if(memcmp(checksum,checksum_backup,32) != 0) {
|
|
fprintf(stderr,"[E] Error checksum file mismatch! %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
printf("... Done!\n");
|
|
fclose(fd_aux3);
|
|
FLAGREADEDFILE3 = 1;
|
|
}
|
|
else {
|
|
FLAGREADEDFILE3 = 0;
|
|
}
|
|
|
|
/*Reading file for 3rd bloom filter */
|
|
snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_7_%" PRIu64 ".blm",bsgs_m3);
|
|
fd_aux2 = fopen(buffer_bloom_file,"rb");
|
|
if(fd_aux2 != NULL) {
|
|
printf("[+] Reading bloom filter from file %s ",buffer_bloom_file);
|
|
fflush(stdout);
|
|
for(i = 0; i < 256;i++) {
|
|
bf_ptr = (char*) bloom_bPx3rd[i].bf; /*We need to save the current bf pointer*/
|
|
readed = fread(&bloom_bPx3rd[i],sizeof(struct bloom),1,fd_aux2);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
bloom_bPx3rd[i].bf = (uint8_t*)bf_ptr; /* Restoring the bf pointer*/
|
|
readed = fread(bloom_bPx3rd[i].bf,bloom_bPx3rd[i].bytes,1,fd_aux2);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
readed = fread(&bloom_bPx3rd_checksums[i],sizeof(struct checksumsha256),1,fd_aux2);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
memset(rawvalue,0,32);
|
|
if(FLAGSKIPCHECKSUM == 0) {
|
|
sha256((uint8_t*)bloom_bPx3rd[i].bf,bloom_bPx3rd[i].bytes,(uint8_t*)rawvalue);
|
|
if(memcmp(bloom_bPx3rd_checksums[i].data,rawvalue,32) != 0 || memcmp(bloom_bPx3rd_checksums[i].backup,rawvalue,32) != 0 ) { /* Verification */
|
|
fprintf(stderr,"[E] Error checksum file mismatch! %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
if(i % 64 == 0) {
|
|
printf(".");
|
|
fflush(stdout);
|
|
}
|
|
}
|
|
fclose(fd_aux2);
|
|
printf(" Done!\n");
|
|
FLAGREADEDFILE4 = 1;
|
|
}
|
|
else {
|
|
FLAGREADEDFILE4 = 0;
|
|
}
|
|
|
|
}
|
|
|
|
if(!FLAGREADEDFILE1 || !FLAGREADEDFILE2 || !FLAGREADEDFILE3 || !FLAGREADEDFILE4) {
|
|
if(FLAGREADEDFILE1 == 1) {
|
|
/*
|
|
We need just to make File 2 to File 4 this is
|
|
- Second bloom filter 5%
|
|
- third bloom fitler 0.25 %
|
|
- bp Table 0.25 %
|
|
*/
|
|
printf("[I] We need to recalculate some files, don't worry this is only 3%% of the previous work\n");
|
|
FINISHED_THREADS_COUNTER = 0;
|
|
FINISHED_THREADS_BP = 0;
|
|
FINISHED_ITEMS = 0;
|
|
salir = 0;
|
|
BASE = 0;
|
|
THREADCOUNTER = 0;
|
|
if(THREADBPWORKLOAD >= bsgs_m2) {
|
|
THREADBPWORKLOAD = bsgs_m2;
|
|
}
|
|
THREADCYCLES = bsgs_m2 / THREADBPWORKLOAD;
|
|
PERTHREAD_R = bsgs_m2 % THREADBPWORKLOAD;
|
|
if(PERTHREAD_R != 0) {
|
|
THREADCYCLES++;
|
|
}
|
|
|
|
printf("\r[+] processing %lu/%lu bP points : %i%%\r",FINISHED_ITEMS,bsgs_m,(int) (((double)FINISHED_ITEMS/(double)bsgs_m)*100));
|
|
fflush(stdout);
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
tid = (HANDLE*)calloc(NTHREADS, sizeof(HANDLE));
|
|
checkpointer((void *)tid,__FILE__,"calloc","tid" ,__LINE__ -1 );
|
|
bPload_mutex = (HANDLE*) calloc(NTHREADS,sizeof(HANDLE));
|
|
#else
|
|
tid = (pthread_t *) calloc(NTHREADS,sizeof(pthread_t));
|
|
bPload_mutex = (pthread_mutex_t*) calloc(NTHREADS,sizeof(pthread_mutex_t));
|
|
#endif
|
|
checkpointer((void *)bPload_mutex,__FILE__,"calloc","bPload_mutex" ,__LINE__ -1 );
|
|
bPload_temp_ptr = (struct bPload*) calloc(NTHREADS,sizeof(struct bPload));
|
|
checkpointer((void *)bPload_temp_ptr,__FILE__,"calloc","bPload_temp_ptr" ,__LINE__ -1 );
|
|
bPload_threads_available = (char*) calloc(NTHREADS,sizeof(char));
|
|
checkpointer((void *)bPload_threads_available,__FILE__,"calloc","bPload_threads_available" ,__LINE__ -1 );
|
|
|
|
memset(bPload_threads_available,1,NTHREADS);
|
|
|
|
for(i = 0; i < NTHREADS; i++) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
bPload_mutex[i] = CreateMutex(NULL, FALSE, NULL);
|
|
#else
|
|
pthread_mutex_init(&bPload_mutex[i],NULL);
|
|
#endif
|
|
}
|
|
|
|
do {
|
|
for(i = 0; i < NTHREADS && !salir; i++) {
|
|
|
|
if(bPload_threads_available[i] && !salir) {
|
|
bPload_threads_available[i] = 0;
|
|
bPload_temp_ptr[i].from = BASE;
|
|
bPload_temp_ptr[i].threadid = i;
|
|
bPload_temp_ptr[i].finished = 0;
|
|
if( THREADCOUNTER < THREADCYCLES-1) {
|
|
bPload_temp_ptr[i].to = BASE + THREADBPWORKLOAD;
|
|
bPload_temp_ptr[i].workload = THREADBPWORKLOAD;
|
|
}
|
|
else {
|
|
bPload_temp_ptr[i].to = BASE + THREADBPWORKLOAD + PERTHREAD_R;
|
|
bPload_temp_ptr[i].workload = THREADBPWORKLOAD + PERTHREAD_R;
|
|
salir = 1;
|
|
//if(FLAGDEBUG) printf("[D] Salir OK\n");
|
|
}
|
|
//if(FLAGDEBUG) printf("[I] %lu to %lu\n",bPload_temp_ptr[i].from,bPload_temp_ptr[i].to);
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
tid[i] = CreateThread(NULL, 0, thread_bPload_2blooms, (void*) &bPload_temp_ptr[i], 0, &s);
|
|
#else
|
|
s = pthread_create(&tid[i],NULL,thread_bPload_2blooms,(void*) &bPload_temp_ptr[i]);
|
|
pthread_detach(tid[i]);
|
|
#endif
|
|
BASE+=THREADBPWORKLOAD;
|
|
THREADCOUNTER++;
|
|
}
|
|
}
|
|
|
|
if(OLDFINISHED_ITEMS != FINISHED_ITEMS) {
|
|
printf("\r[+] processing %lu/%lu bP points : %i%%\r",FINISHED_ITEMS,bsgs_m2,(int) (((double)FINISHED_ITEMS/(double)bsgs_m2)*100));
|
|
fflush(stdout);
|
|
OLDFINISHED_ITEMS = FINISHED_ITEMS;
|
|
}
|
|
|
|
for(i = 0 ; i < NTHREADS ; i++) {
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(bPload_mutex[i], INFINITE);
|
|
finished = bPload_temp_ptr[i].finished;
|
|
ReleaseMutex(bPload_mutex[i]);
|
|
#else
|
|
pthread_mutex_lock(&bPload_mutex[i]);
|
|
finished = bPload_temp_ptr[i].finished;
|
|
pthread_mutex_unlock(&bPload_mutex[i]);
|
|
#endif
|
|
if(finished) {
|
|
bPload_temp_ptr[i].finished = 0;
|
|
bPload_threads_available[i] = 1;
|
|
FINISHED_ITEMS += bPload_temp_ptr[i].workload;
|
|
FINISHED_THREADS_COUNTER++;
|
|
}
|
|
}
|
|
|
|
}while(FINISHED_THREADS_COUNTER < THREADCYCLES);
|
|
printf("\r[+] processing %lu/%lu bP points : 100%% \n",bsgs_m2,bsgs_m2);
|
|
|
|
free(tid);
|
|
free(bPload_mutex);
|
|
free(bPload_temp_ptr);
|
|
free(bPload_threads_available);
|
|
}
|
|
else{
|
|
/* We need just to do all the files
|
|
- first bllom filter 100%
|
|
- Second bloom filter 5%
|
|
- third bloom fitler 0.25 %
|
|
- bp Table 0.25 %
|
|
*/
|
|
FINISHED_THREADS_COUNTER = 0;
|
|
FINISHED_THREADS_BP = 0;
|
|
FINISHED_ITEMS = 0;
|
|
salir = 0;
|
|
BASE = 0;
|
|
THREADCOUNTER = 0;
|
|
if(THREADBPWORKLOAD >= bsgs_m) {
|
|
THREADBPWORKLOAD = bsgs_m;
|
|
}
|
|
THREADCYCLES = bsgs_m / THREADBPWORKLOAD;
|
|
PERTHREAD_R = bsgs_m % THREADBPWORKLOAD;
|
|
//if(FLAGDEBUG) printf("[D] THREADCYCLES: %lu\n",THREADCYCLES);
|
|
if(PERTHREAD_R != 0) {
|
|
THREADCYCLES++;
|
|
//if(FLAGDEBUG) printf("[D] PERTHREAD_R: %lu\n",PERTHREAD_R);
|
|
}
|
|
|
|
printf("\r[+] processing %lu/%lu bP points : %i%%\r",FINISHED_ITEMS,bsgs_m,(int) (((double)FINISHED_ITEMS/(double)bsgs_m)*100));
|
|
fflush(stdout);
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
tid = (HANDLE*)calloc(NTHREADS, sizeof(HANDLE));
|
|
bPload_mutex = (HANDLE*) calloc(NTHREADS,sizeof(HANDLE));
|
|
#else
|
|
tid = (pthread_t *) calloc(NTHREADS,sizeof(pthread_t));
|
|
bPload_mutex = (pthread_mutex_t*) calloc(NTHREADS,sizeof(pthread_mutex_t));
|
|
#endif
|
|
checkpointer((void *)tid,__FILE__,"calloc","tid" ,__LINE__ -1 );
|
|
checkpointer((void *)bPload_mutex,__FILE__,"calloc","bPload_mutex" ,__LINE__ -1 );
|
|
|
|
bPload_temp_ptr = (struct bPload*) calloc(NTHREADS,sizeof(struct bPload));
|
|
checkpointer((void *)bPload_temp_ptr,__FILE__,"calloc","bPload_temp_ptr" ,__LINE__ -1 );
|
|
bPload_threads_available = (char*) calloc(NTHREADS,sizeof(char));
|
|
checkpointer((void *)bPload_threads_available,__FILE__,"calloc","bPload_threads_available" ,__LINE__ -1 );
|
|
|
|
|
|
memset(bPload_threads_available,1,NTHREADS);
|
|
|
|
for(i = 0; i < NTHREADS; i++) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
bPload_mutex = CreateMutex(NULL, FALSE, NULL);
|
|
#else
|
|
pthread_mutex_init(&bPload_mutex[i],NULL);
|
|
#endif
|
|
}
|
|
|
|
do {
|
|
for(i = 0; i < NTHREADS && !salir; i++) {
|
|
|
|
if(bPload_threads_available[i] && !salir) {
|
|
bPload_threads_available[i] = 0;
|
|
bPload_temp_ptr[i].from = BASE;
|
|
bPload_temp_ptr[i].threadid = i;
|
|
bPload_temp_ptr[i].finished = 0;
|
|
if( THREADCOUNTER < THREADCYCLES-1) {
|
|
bPload_temp_ptr[i].to = BASE + THREADBPWORKLOAD;
|
|
bPload_temp_ptr[i].workload = THREADBPWORKLOAD;
|
|
}
|
|
else {
|
|
bPload_temp_ptr[i].to = BASE + THREADBPWORKLOAD + PERTHREAD_R;
|
|
bPload_temp_ptr[i].workload = THREADBPWORKLOAD + PERTHREAD_R;
|
|
salir = 1;
|
|
//if(FLAGDEBUG) printf("[D] Salir OK\n");
|
|
}
|
|
//if(FLAGDEBUG) printf("[I] %lu to %lu\n",bPload_temp_ptr[i].from,bPload_temp_ptr[i].to);
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
tid[i] = CreateThread(NULL, 0, thread_bPload, (void*) &bPload_temp_ptr[i], 0, &s);
|
|
#else
|
|
s = pthread_create(&tid[i],NULL,thread_bPload,(void*) &bPload_temp_ptr[i]);
|
|
pthread_detach(tid[i]);
|
|
#endif
|
|
BASE+=THREADBPWORKLOAD;
|
|
THREADCOUNTER++;
|
|
}
|
|
}
|
|
if(OLDFINISHED_ITEMS != FINISHED_ITEMS) {
|
|
printf("\r[+] processing %lu/%lu bP points : %i%%\r",FINISHED_ITEMS,bsgs_m,(int) (((double)FINISHED_ITEMS/(double)bsgs_m)*100));
|
|
fflush(stdout);
|
|
OLDFINISHED_ITEMS = FINISHED_ITEMS;
|
|
}
|
|
|
|
for(i = 0 ; i < NTHREADS ; i++) {
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(bPload_mutex[i], INFINITE);
|
|
finished = bPload_temp_ptr[i].finished;
|
|
ReleaseMutex(bPload_mutex[i]);
|
|
#else
|
|
pthread_mutex_lock(&bPload_mutex[i]);
|
|
finished = bPload_temp_ptr[i].finished;
|
|
pthread_mutex_unlock(&bPload_mutex[i]);
|
|
#endif
|
|
if(finished) {
|
|
bPload_temp_ptr[i].finished = 0;
|
|
bPload_threads_available[i] = 1;
|
|
FINISHED_ITEMS += bPload_temp_ptr[i].workload;
|
|
FINISHED_THREADS_COUNTER++;
|
|
}
|
|
}
|
|
|
|
}while(FINISHED_THREADS_COUNTER < THREADCYCLES);
|
|
printf("\r[+] processing %lu/%lu bP points : 100%% \n",bsgs_m,bsgs_m);
|
|
|
|
free(tid);
|
|
free(bPload_mutex);
|
|
free(bPload_temp_ptr);
|
|
free(bPload_threads_available);
|
|
}
|
|
}
|
|
|
|
if(!FLAGREADEDFILE1 || !FLAGREADEDFILE2 || !FLAGREADEDFILE4) {
|
|
printf("[+] Making checkums .. ");
|
|
fflush(stdout);
|
|
}
|
|
if(!FLAGREADEDFILE1) {
|
|
for(i = 0; i < 256 ; i++) {
|
|
sha256((uint8_t*)bloom_bP[i].bf, bloom_bP[i].bytes,(uint8_t*) bloom_bP_checksums[i].data);
|
|
memcpy(bloom_bP_checksums[i].backup,bloom_bP_checksums[i].data,32);
|
|
}
|
|
printf(".");
|
|
}
|
|
if(!FLAGREADEDFILE2) {
|
|
for(i = 0; i < 256 ; i++) {
|
|
sha256((uint8_t*)bloom_bPx2nd[i].bf, bloom_bPx2nd[i].bytes,(uint8_t*) bloom_bPx2nd_checksums[i].data);
|
|
memcpy(bloom_bPx2nd_checksums[i].backup,bloom_bPx2nd_checksums[i].data,32);
|
|
}
|
|
printf(".");
|
|
}
|
|
if(!FLAGREADEDFILE4) {
|
|
for(i = 0; i < 256 ; i++) {
|
|
sha256((uint8_t*)bloom_bPx3rd[i].bf, bloom_bPx3rd[i].bytes,(uint8_t*) bloom_bPx3rd_checksums[i].data);
|
|
memcpy(bloom_bPx3rd_checksums[i].backup,bloom_bPx3rd_checksums[i].data,32);
|
|
}
|
|
printf(".");
|
|
}
|
|
if(!FLAGREADEDFILE1 || !FLAGREADEDFILE2 || !FLAGREADEDFILE4) {
|
|
printf(" done\n");
|
|
fflush(stdout);
|
|
}
|
|
if(!FLAGREADEDFILE3) {
|
|
printf("[+] Sorting %lu elements... ",bsgs_m3);
|
|
fflush(stdout);
|
|
bsgs_sort(bPtable,bsgs_m3);
|
|
sha256((uint8_t*)bPtable, bytes,(uint8_t*) checksum);
|
|
memcpy(checksum_backup,checksum,32);
|
|
printf("Done!\n");
|
|
fflush(stdout);
|
|
}
|
|
if(FLAGSAVEREADFILE || FLAGUPDATEFILE1 ) {
|
|
if(!FLAGREADEDFILE1 || FLAGUPDATEFILE1) {
|
|
snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_4_%" PRIu64 ".blm",bsgs_m);
|
|
|
|
if(FLAGUPDATEFILE1) {
|
|
printf("[W] Updating old file into a new one\n");
|
|
}
|
|
|
|
/* Writing file for 1st bloom filter */
|
|
|
|
fd_aux1 = fopen(buffer_bloom_file,"wb");
|
|
if(fd_aux1 != NULL) {
|
|
printf("[+] Writing bloom filter to file %s ",buffer_bloom_file);
|
|
fflush(stdout);
|
|
for(i = 0; i < 256;i++) {
|
|
readed = fwrite(&bloom_bP[i],sizeof(struct bloom),1,fd_aux1);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error writing the file %s please delete it\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
readed = fwrite(bloom_bP[i].bf,bloom_bP[i].bytes,1,fd_aux1);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error writing the file %s please delete it\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
readed = fwrite(&bloom_bP_checksums[i],sizeof(struct checksumsha256),1,fd_aux1);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error writing the file %s please delete it\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if(i % 64 == 0) {
|
|
printf(".");
|
|
fflush(stdout);
|
|
}
|
|
}
|
|
printf(" Done!\n");
|
|
fclose(fd_aux1);
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] Error can't create the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
if(!FLAGREADEDFILE2 ) {
|
|
|
|
snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_6_%" PRIu64 ".blm",bsgs_m2);
|
|
|
|
/* Writing file for 2nd bloom filter */
|
|
fd_aux2 = fopen(buffer_bloom_file,"wb");
|
|
if(fd_aux2 != NULL) {
|
|
printf("[+] Writing bloom filter to file %s ",buffer_bloom_file);
|
|
fflush(stdout);
|
|
for(i = 0; i < 256;i++) {
|
|
readed = fwrite(&bloom_bPx2nd[i],sizeof(struct bloom),1,fd_aux2);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error writing the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
readed = fwrite(bloom_bPx2nd[i].bf,bloom_bPx2nd[i].bytes,1,fd_aux2);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error writing the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
readed = fwrite(&bloom_bPx2nd_checksums[i],sizeof(struct checksumsha256),1,fd_aux2);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error writing the file %s please delete it\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if(i % 64 == 0) {
|
|
printf(".");
|
|
fflush(stdout);
|
|
}
|
|
}
|
|
printf(" Done!\n");
|
|
fclose(fd_aux2);
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] Error can't create the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
if(!FLAGREADEDFILE3) {
|
|
/* Writing file for bPtable */
|
|
snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_2_%" PRIu64 ".tbl",bsgs_m3);
|
|
fd_aux3 = fopen(buffer_bloom_file,"wb");
|
|
if(fd_aux3 != NULL) {
|
|
printf("[+] Writing bP Table to file %s .. ",buffer_bloom_file);
|
|
fflush(stdout);
|
|
readed = fwrite(bPtable,bytes,1,fd_aux3);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error writing the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
readed = fwrite(checksum,32,1,fd_aux3);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error writing the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
printf("Done!\n");
|
|
fclose(fd_aux3);
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] Error can't create the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
if(!FLAGREADEDFILE4) {
|
|
snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_7_%" PRIu64 ".blm",bsgs_m3);
|
|
|
|
/* Writing file for 3rd bloom filter */
|
|
fd_aux2 = fopen(buffer_bloom_file,"wb");
|
|
if(fd_aux2 != NULL) {
|
|
printf("[+] Writing bloom filter to file %s ",buffer_bloom_file);
|
|
fflush(stdout);
|
|
for(i = 0; i < 256;i++) {
|
|
readed = fwrite(&bloom_bPx3rd[i],sizeof(struct bloom),1,fd_aux2);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error writing the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
readed = fwrite(bloom_bPx3rd[i].bf,bloom_bPx3rd[i].bytes,1,fd_aux2);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error writing the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
readed = fwrite(&bloom_bPx3rd_checksums[i],sizeof(struct checksumsha256),1,fd_aux2);
|
|
if(readed != 1) {
|
|
fprintf(stderr,"[E] Error writing the file %s please delete it\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if(i % 64 == 0) {
|
|
printf(".");
|
|
fflush(stdout);
|
|
}
|
|
}
|
|
printf(" Done!\n");
|
|
fclose(fd_aux2);
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] Error can't create the file %s\n",buffer_bloom_file);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
i = 0;
|
|
|
|
steps = (uint64_t *) calloc(NTHREADS,sizeof(uint64_t));
|
|
checkpointer((void *)steps,__FILE__,"calloc","steps" ,__LINE__ -1 );
|
|
ends = (unsigned int *) calloc(NTHREADS,sizeof(int));
|
|
checkpointer((void *)ends,__FILE__,"calloc","ends" ,__LINE__ -1 );
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
tid = (HANDLE*)calloc(NTHREADS, sizeof(HANDLE));
|
|
#else
|
|
tid = (pthread_t *) calloc(NTHREADS,sizeof(pthread_t));
|
|
#endif
|
|
checkpointer((void *)tid,__FILE__,"calloc","tid" ,__LINE__ -1 );
|
|
|
|
for(i= 0;i < NTHREADS; i++) {
|
|
tt = (tothread*) malloc(sizeof(struct tothread));
|
|
checkpointer((void *)tt,__FILE__,"malloc","tt" ,__LINE__ -1 );
|
|
tt->nt = i;
|
|
s = 0;
|
|
switch(FLAGBSGSMODE) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
case 0:
|
|
tid[i] = CreateThread(NULL, 0, thread_process_bsgs, (void*)tt, 0, &s);
|
|
break;
|
|
case 1:
|
|
tid[i] = CreateThread(NULL, 0, thread_process_bsgs_backward, (void*)tt, 0, &s);
|
|
break;
|
|
case 2:
|
|
tid[i] = CreateThread(NULL, 0, thread_process_bsgs_both, (void*)tt, 0, &s);
|
|
break;
|
|
case 3:
|
|
tid[i] = CreateThread(NULL, 0, thread_process_bsgs_random, (void*)tt, 0, &s);
|
|
break;
|
|
case 4:
|
|
tid[i] = CreateThread(NULL, 0, thread_process_bsgs_dance, (void*)tt, 0, &s);
|
|
break;
|
|
}
|
|
#else
|
|
|
|
case 0:
|
|
s = pthread_create(&tid[i],NULL,thread_process_bsgs,(void *)tt);
|
|
break;
|
|
case 1:
|
|
s = pthread_create(&tid[i],NULL,thread_process_bsgs_backward,(void *)tt);
|
|
break;
|
|
case 2:
|
|
s = pthread_create(&tid[i],NULL,thread_process_bsgs_both,(void *)tt);
|
|
break;
|
|
case 3:
|
|
s = pthread_create(&tid[i],NULL,thread_process_bsgs_random,(void *)tt);
|
|
break;
|
|
case 4:
|
|
s = pthread_create(&tid[i],NULL,thread_process_bsgs_dance,(void *)tt);
|
|
break;
|
|
#endif
|
|
}
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
if (tid[i] == NULL) {
|
|
#else
|
|
if(s != 0) {
|
|
#endif
|
|
fprintf(stderr,"[E] thread thread_process\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
|
|
free(aux);
|
|
}
|
|
if(FLAGMODE != MODE_BSGS) {
|
|
//if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); }
|
|
steps = (uint64_t *) calloc(NTHREADS,sizeof(uint64_t));
|
|
checkpointer((void *)steps,__FILE__,"calloc","steps" ,__LINE__ -1 );
|
|
ends = (unsigned int *) calloc(NTHREADS,sizeof(int));
|
|
checkpointer((void *)ends,__FILE__,"calloc","ends" ,__LINE__ -1 );
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
tid = (HANDLE*)calloc(NTHREADS, sizeof(HANDLE));
|
|
#else
|
|
tid = (pthread_t *) calloc(NTHREADS,sizeof(pthread_t));
|
|
#endif
|
|
checkpointer((void *)tid,__FILE__,"calloc","tid" ,__LINE__ -1 );
|
|
//if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); }
|
|
for(i= 0;i < NTHREADS; i++) {
|
|
tt = (tothread*) malloc(sizeof(struct tothread));
|
|
checkpointer((void *)tt,__FILE__,"malloc","tt" ,__LINE__ -1 );
|
|
tt->nt = i;
|
|
steps[i] = 0;
|
|
s = 0;
|
|
switch(FLAGMODE) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
case MODE_ADDRESS:
|
|
case MODE_XPOINT:
|
|
case MODE_RMD160:
|
|
//if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); }
|
|
tid[i] = CreateThread(NULL, 0, thread_process, (void*)tt, 0, &s);
|
|
break;
|
|
case MODE_PUB2RMD:
|
|
tid[i] = CreateThread(NULL, 0, thread_pub2rmd, (void*)tt, 0, &s);
|
|
break;
|
|
case MODE_MINIKEYS:
|
|
tid[i] = CreateThread(NULL, 0, thread_process_minikeys, (void*)tt, 0, &s);
|
|
break;
|
|
#else
|
|
case MODE_ADDRESS:
|
|
case MODE_XPOINT:
|
|
case MODE_RMD160:
|
|
s = pthread_create(&tid[i],NULL,thread_process,(void *)tt);
|
|
break;
|
|
case MODE_PUB2RMD:
|
|
s = pthread_create(&tid[i],NULL,thread_pub2rmd,(void *)tt);
|
|
break;
|
|
case MODE_MINIKEYS:
|
|
s = pthread_create(&tid[i],NULL,thread_process_minikeys,(void *)tt);
|
|
break;
|
|
case MODE_VANITY:
|
|
s = pthread_create(&tid[i],NULL,thread_process_vanity,(void *)tt);
|
|
break;
|
|
#endif
|
|
}
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
if (tid[i] == NULL) {
|
|
#else
|
|
if(s != 0) {
|
|
#endif
|
|
fprintf(stderr,"[E] pthread_create thread_process\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
}
|
|
i = 0;
|
|
|
|
while(i < 7) {
|
|
int_limits[i].SetBase10((char*)str_limits[i]);
|
|
i++;
|
|
}
|
|
|
|
continue_flag = 1;
|
|
total.SetInt32(0);
|
|
pretotal.SetInt32(0);
|
|
debugcount_mpz.Set(&BSGS_N);
|
|
seconds.SetInt32(0);
|
|
do {
|
|
sleep_ms(1000);
|
|
seconds.AddOne();
|
|
check_flag = 1;
|
|
for(i = 0; i <NTHREADS && check_flag; i++) {
|
|
check_flag &= ends[i];
|
|
}
|
|
if(check_flag) {
|
|
continue_flag = 0;
|
|
}
|
|
if(OUTPUTSECONDS.IsGreater(&ZERO) ){
|
|
MPZAUX.Set(&seconds);
|
|
MPZAUX.Mod(&OUTPUTSECONDS);
|
|
if(MPZAUX.IsZero()) {
|
|
total.SetInt32(0);
|
|
i = 0;
|
|
while(i < NTHREADS) {
|
|
pretotal.Set(&debugcount_mpz);
|
|
pretotal.Mult(steps[i]);
|
|
total.Add(&pretotal);
|
|
i++;
|
|
}
|
|
|
|
if(FLAGENDOMORPHISM) {
|
|
if(FLAGMODE == MODE_XPOINT) {
|
|
total.Mult(3);
|
|
}
|
|
else {
|
|
total.Mult(6);
|
|
}
|
|
}
|
|
else {
|
|
if(FLAGSEARCH == SEARCH_COMPRESS) {
|
|
total.Mult(2);
|
|
}
|
|
}
|
|
|
|
#ifdef _WIN64
|
|
WaitForSingleObject(bsgs_thread, INFINITE);
|
|
#else
|
|
pthread_mutex_lock(&bsgs_thread);
|
|
#endif
|
|
pretotal.Set(&total);
|
|
pretotal.Div(&seconds);
|
|
str_seconds = seconds.GetBase10();
|
|
str_pretotal = pretotal.GetBase10();
|
|
str_total = total.GetBase10();
|
|
|
|
if(pretotal.IsLower(&int_limits[0])) {
|
|
if(FLAGMATRIX) {
|
|
sprintf(buffer,"[+] Total %s keys in %s seconds: %s keys/s\n",str_total,str_seconds,str_pretotal);
|
|
}
|
|
else {
|
|
sprintf(buffer,"\r[+] Total %s keys in %s seconds: %s keys/s\r",str_total,str_seconds,str_pretotal);
|
|
}
|
|
}
|
|
else {
|
|
i = 0;
|
|
salir = 0;
|
|
while( i < 6 && !salir) {
|
|
if(pretotal.IsLower(&int_limits[i+1])) {
|
|
salir = 1;
|
|
}
|
|
else {
|
|
i++;
|
|
}
|
|
}
|
|
|
|
div_pretotal.Set(&pretotal);
|
|
div_pretotal.Div(&int_limits[salir ? i : i-1]);
|
|
str_divpretotal = div_pretotal.GetBase10();
|
|
if(FLAGMATRIX) {
|
|
sprintf(buffer,"[+] Total %s keys in %s seconds: ~%s %s (%s keys/s)\n",str_total,str_seconds,str_divpretotal,str_limits_prefixs[salir ? i : i-1],str_pretotal);
|
|
}
|
|
else {
|
|
if(THREADOUTPUT == 1) {
|
|
sprintf(buffer,"\r[+] Total %s keys in %s seconds: ~%s %s (%s keys/s)\r",str_total,str_seconds,str_divpretotal,str_limits_prefixs[salir ? i : i-1],str_pretotal);
|
|
}
|
|
else {
|
|
sprintf(buffer,"\r[+] Total %s keys in %s seconds: ~%s %s (%s keys/s)\r",str_total,str_seconds,str_divpretotal,str_limits_prefixs[salir ? i : i-1],str_pretotal);
|
|
}
|
|
}
|
|
free(str_divpretotal);
|
|
|
|
}
|
|
printf("%s",buffer);
|
|
fflush(stdout);
|
|
THREADOUTPUT = 0;
|
|
#ifdef _WIN64
|
|
ReleaseMutex(bsgs_thread);
|
|
#else
|
|
pthread_mutex_unlock(&bsgs_thread);
|
|
#endif
|
|
|
|
free(str_seconds);
|
|
free(str_pretotal);
|
|
free(str_total);
|
|
}
|
|
}
|
|
}while(continue_flag);
|
|
printf("\nEnd\n");
|
|
#ifdef _WIN64
|
|
CloseHandle(write_keys);
|
|
CloseHandle(write_random);
|
|
CloseHandle(bsgs_thread);
|
|
#endif
|
|
}
|
|
|
|
void pubkeytopubaddress_dst(char *pkey,int length,char *dst) {
|
|
char digest[60];
|
|
size_t pubaddress_size = 40;
|
|
sha256((uint8_t*)pkey, length,(uint8_t*) digest);
|
|
rmd160((const unsigned char*)digest,32,(unsigned char*) digest+1);
|
|
digest[0] = 0;
|
|
sha256((uint8_t*)digest, 21,(uint8_t*) digest+21);
|
|
sha256((uint8_t*)digest+21, 32,(uint8_t*) digest+21);
|
|
if(!b58enc(dst,&pubaddress_size,digest,25)){
|
|
fprintf(stderr,"error b58enc\n");
|
|
}
|
|
}
|
|
|
|
void rmd160toaddress_dst(char *rmd,char *dst){
|
|
char digest[60];
|
|
size_t pubaddress_size = 40;
|
|
digest[0] = byte_encode_crypto;
|
|
memcpy(digest+1,rmd,20);
|
|
sha256((uint8_t*)digest, 21,(uint8_t*) digest+21);
|
|
sha256((uint8_t*)digest+21, 32,(uint8_t*) digest+21);
|
|
if(!b58enc(dst,&pubaddress_size,digest,25)){
|
|
fprintf(stderr,"error b58enc\n");
|
|
}
|
|
}
|
|
|
|
|
|
char *pubkeytopubaddress(char *pkey,int length) {
|
|
char *pubaddress = (char*) calloc(MAXLENGTHADDRESS+10,1);
|
|
char *digest = (char*) calloc(60,1);
|
|
size_t pubaddress_size = MAXLENGTHADDRESS+10;
|
|
checkpointer((void *)pubaddress,__FILE__,"malloc","pubaddress" ,__LINE__ -1 );
|
|
checkpointer((void *)digest,__FILE__,"malloc","digest" ,__LINE__ -1 );
|
|
//digest [000...0]
|
|
sha256((uint8_t*)pkey, length,(uint8_t*) digest);
|
|
//digest [SHA256 32 bytes+000....0]
|
|
rmd160((const unsigned char*)digest,32, (unsigned char*)digest+1);
|
|
//digest [? +RMD160 20 bytes+????000....0]
|
|
digest[0] = 0;
|
|
//digest [0 +RMD160 20 bytes+????000....0]
|
|
sha256((uint8_t*)digest, 21,(uint8_t*) digest+21);
|
|
//digest [0 +RMD160 20 bytes+SHA256 32 bytes+....0]
|
|
sha256((uint8_t*)digest+21, 32,(uint8_t*) digest+21);
|
|
//digest [0 +RMD160 20 bytes+SHA256 32 bytes+....0]
|
|
if(!b58enc(pubaddress,&pubaddress_size,digest,25)){
|
|
fprintf(stderr,"error b58enc\n");
|
|
}
|
|
free(digest);
|
|
return pubaddress; // pubaddress need to be free by te caller funtion
|
|
}
|
|
|
|
int searchbinary(struct address_value *buffer,char *data,int64_t array_length) {
|
|
int64_t half,min,max,current;
|
|
int r = 0,rcmp;
|
|
min = 0;
|
|
current = 0;
|
|
max = array_length;
|
|
half = array_length;
|
|
while(!r && half >= 1) {
|
|
half = (max - min)/2;
|
|
rcmp = memcmp(data,buffer[current+half].value,20);
|
|
if(rcmp == 0) {
|
|
r = 1; //Found!!
|
|
}
|
|
else {
|
|
if(rcmp < 0) { //data < temp_read
|
|
max = (max-half);
|
|
}
|
|
else { // data > temp_read
|
|
min = (min+half);
|
|
}
|
|
current = min;
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
DWORD WINAPI thread_process_minikeys(LPVOID vargp) {
|
|
#else
|
|
void *thread_process_minikeys(void *vargp) {
|
|
#endif
|
|
FILE *keys;
|
|
Point publickey[4];
|
|
Int key_mpz[4];
|
|
struct tothread *tt;
|
|
uint64_t count;
|
|
char publickeyhashrmd160_uncompress[4][20];
|
|
char public_key_uncompressed_hex[131];
|
|
char rawvalue[4][32];
|
|
char address[4][40],minikey[4][24],minikeys[8][24],buffer_b58[21],minikey2check[24];
|
|
char *hextemp,rawbuffer[32];
|
|
int r,thread_number,continue_flag = 1,k,j,count_valid;
|
|
//Int counter;
|
|
tt = (struct tothread *)vargp;
|
|
thread_number = tt->nt;
|
|
free(tt);
|
|
//rawbuffer = (char*) &counter.bits64;
|
|
count_valid = 0;
|
|
for(k = 0; k < 4; k++) {
|
|
minikey[k][0] = 'S';
|
|
minikey[k][22] = '?';
|
|
minikey[k][23] = 0x00;
|
|
}
|
|
minikey2check[0] = 'S';
|
|
minikey2check[22] = '?';
|
|
minikey2check[23] = 0x00;
|
|
|
|
do {
|
|
if(FLAGRANDOM) {
|
|
random_bytes((unsigned char*)rawbuffer,32);
|
|
for(k = 0; k < 21; k++) {
|
|
buffer_b58[k] =(uint8_t)((uint8_t) rawbuffer[k] % 58);
|
|
}
|
|
}
|
|
else {
|
|
if(FLAGBASEMINIKEY) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(write_random, INFINITE);
|
|
memcpy(buffer_b58,raw_baseminikey,21);
|
|
increment_minikey_N(raw_baseminikey);
|
|
ReleaseMutex(write_random);
|
|
#else
|
|
pthread_mutex_lock(&write_random);
|
|
memcpy(buffer_b58,raw_baseminikey,21);
|
|
increment_minikey_N(raw_baseminikey);
|
|
pthread_mutex_unlock(&write_random);
|
|
#endif
|
|
}
|
|
else {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(write_random, INFINITE);
|
|
#else
|
|
pthread_mutex_lock(&write_random);
|
|
#endif
|
|
if(raw_baseminikey == NULL){
|
|
raw_baseminikey = (char *) malloc(22);
|
|
checkpointer((void *)raw_baseminikey,__FILE__,"malloc","raw_baseminikey" ,__LINE__ -1 );
|
|
random_bytes((unsigned char*)rawbuffer,32);
|
|
for(k = 0; k < 21; k++) {
|
|
raw_baseminikey[k] =(uint8_t)((uint8_t) rawbuffer[k] % 58);
|
|
}
|
|
memcpy(buffer_b58,raw_baseminikey,21);
|
|
increment_minikey_N(raw_baseminikey);
|
|
|
|
}
|
|
else {
|
|
memcpy(buffer_b58,raw_baseminikey,21);
|
|
increment_minikey_N(raw_baseminikey);
|
|
}
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
ReleaseMutex(write_random);
|
|
#else
|
|
pthread_mutex_unlock(&write_random);
|
|
#endif
|
|
|
|
}
|
|
}
|
|
set_minikey(minikey2check+1,buffer_b58,21);
|
|
if(continue_flag) {
|
|
count = 0;
|
|
if(FLAGMATRIX) {
|
|
printf("[+] Base minikey: %s \n",minikey2check);
|
|
fflush(stdout);
|
|
}
|
|
else {
|
|
if(!FLAGQUIET) {
|
|
printf("\r[+] Base minikey: %s \r",minikey2check);
|
|
fflush(stdout);
|
|
}
|
|
}
|
|
do {
|
|
for(j = 0;j<256; j++) {
|
|
|
|
if(count_valid > 0) {
|
|
for(k = 0; k < count_valid ; k++) {
|
|
memcpy(minikeys[k],minikeys[4+k],22);
|
|
}
|
|
}
|
|
do {
|
|
increment_minikey_index(minikey2check+1,buffer_b58,20);
|
|
memcpy(minikey[0]+1,minikey2check+1,21);
|
|
increment_minikey_index(minikey2check+1,buffer_b58,20);
|
|
memcpy(minikey[1]+1,minikey2check+1,21);
|
|
increment_minikey_index(minikey2check+1,buffer_b58,20);
|
|
memcpy(minikey[2]+1,minikey2check+1,21);
|
|
increment_minikey_index(minikey2check+1,buffer_b58,20);
|
|
memcpy(minikey[3]+1,minikey2check+1,21);
|
|
|
|
sha256sse_23((uint8_t*)minikey[0],(uint8_t*)minikey[1],(uint8_t*)minikey[2],(uint8_t*)minikey[3],(uint8_t*)rawvalue[0],(uint8_t*)rawvalue[1],(uint8_t*)rawvalue[2],(uint8_t*)rawvalue[3]);
|
|
for(k = 0; k < 4; k++){
|
|
if(rawvalue[k][0] == 0x00) {
|
|
memcpy(minikeys[count_valid],minikey[k],22);
|
|
count_valid++;
|
|
}
|
|
}
|
|
}while(count_valid < 4);
|
|
count_valid-=4;
|
|
sha256sse_22((uint8_t*)minikeys[0],(uint8_t*)minikeys[1],(uint8_t*)minikeys[2],(uint8_t*)minikeys[3],(uint8_t*)rawvalue[0],(uint8_t*)rawvalue[1],(uint8_t*)rawvalue[2],(uint8_t*)rawvalue[3]);
|
|
|
|
for(k = 0; k < 4; k++) {
|
|
key_mpz[k].Set32Bytes((uint8_t*)rawvalue[k]);
|
|
publickey[k] = secp->ComputePublicKey(&key_mpz[k]);
|
|
}
|
|
|
|
secp->GetHash160(P2PKH,false,publickey[0],publickey[1],publickey[2],publickey[3],(uint8_t*)publickeyhashrmd160_uncompress[0],(uint8_t*)publickeyhashrmd160_uncompress[1],(uint8_t*)publickeyhashrmd160_uncompress[2],(uint8_t*)publickeyhashrmd160_uncompress[3]);
|
|
|
|
for(k = 0; k < 4; k++) {
|
|
r = bloom_check(&bloom,publickeyhashrmd160_uncompress[k],20);
|
|
if(r) {
|
|
r = searchbinary(addressTable,publickeyhashrmd160_uncompress[k],N);
|
|
if(r) {
|
|
/* hit */
|
|
hextemp = key_mpz[k].GetBase16();
|
|
secp->GetPublicKeyHex(false,publickey[k],public_key_uncompressed_hex);
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(write_keys, INFINITE);
|
|
#else
|
|
pthread_mutex_lock(&write_keys);
|
|
#endif
|
|
|
|
keys = fopen("KEYFOUNDKEYFOUND.txt","a+");
|
|
rmd160toaddress_dst(publickeyhashrmd160_uncompress[k],address[k]);
|
|
minikeys[k][22] = '\0';
|
|
if(keys != NULL) {
|
|
fprintf(keys,"Private Key: %s\npubkey: %s\nminikey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,minikeys[k],address[k]);
|
|
fclose(keys);
|
|
}
|
|
printf("\nHIT!! Private Key: %s\npubkey: %s\nminikey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,minikeys[k],address[k]);
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
ReleaseMutex(write_keys);
|
|
#else
|
|
pthread_mutex_unlock(&write_keys);
|
|
#endif
|
|
|
|
free(hextemp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
steps[thread_number]++;
|
|
count+=1024;
|
|
}while(count < N_SEQUENTIAL_MAX && continue_flag);
|
|
}
|
|
}while(continue_flag);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
DWORD WINAPI thread_process(LPVOID vargp) {
|
|
#else
|
|
void *thread_process(void *vargp) {
|
|
#endif
|
|
struct tothread *tt;
|
|
|
|
Point pts[CPU_GRP_SIZE];
|
|
Point endomorphism_beta[CPU_GRP_SIZE];
|
|
Point endomorphism_beta2[CPU_GRP_SIZE];
|
|
Point endomorphism_negeted_point[4];
|
|
|
|
|
|
Int dx[CPU_GRP_SIZE / 2 + 1];
|
|
IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1);
|
|
Point startP;
|
|
Int dy;
|
|
Int dyn;
|
|
Int _s;
|
|
Int _p;
|
|
Point pp;
|
|
Point pn;
|
|
int l,pp_offset,pn_offset;
|
|
int i,hLength = (CPU_GRP_SIZE / 2 - 1);
|
|
uint64_t j,count;
|
|
Point R,temporal,publickey;
|
|
int r,thread_number,continue_flag = 1,k;
|
|
char *hextemp = NULL;
|
|
|
|
char publickeyhashrmd160[20];
|
|
char publickeyhashrmd160_uncompress[4][20];
|
|
char rawvalue[32];
|
|
|
|
char publickeyhashrmd160_endomorphism[12][4][20];
|
|
|
|
bool calculate_y = FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH;
|
|
Int key_mpz,keyfound,temp_stride;
|
|
tt = (struct tothread *)vargp;
|
|
thread_number = tt->nt;
|
|
free(tt);
|
|
grp->Set(dx);
|
|
|
|
do {
|
|
if(FLAGRANDOM){
|
|
key_mpz.Rand(&n_range_start,&n_range_end);
|
|
}
|
|
else {
|
|
if(n_range_start.IsLower(&n_range_end)) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(write_random, INFINITE);
|
|
key_mpz.Set(&n_range_start);
|
|
n_range_start.Add(N_SEQUENTIAL_MAX);
|
|
ReleaseMutex(write_random);
|
|
#else
|
|
pthread_mutex_lock(&write_random);
|
|
key_mpz.Set(&n_range_start);
|
|
n_range_start.Add(N_SEQUENTIAL_MAX);
|
|
pthread_mutex_unlock(&write_random);
|
|
#endif
|
|
}
|
|
else {
|
|
continue_flag = 0;
|
|
}
|
|
}
|
|
if(continue_flag) {
|
|
count = 0;
|
|
if(FLAGMATRIX) {
|
|
hextemp = key_mpz.GetBase16();
|
|
printf("Base key: %s thread %i\n",hextemp,thread_number);
|
|
fflush(stdout);
|
|
free(hextemp);
|
|
}
|
|
else {
|
|
if(FLAGQUIET == 0){
|
|
hextemp = key_mpz.GetBase16();
|
|
printf("\rBase key: %s \r",hextemp);
|
|
fflush(stdout);
|
|
free(hextemp);
|
|
THREADOUTPUT = 1;
|
|
}
|
|
}
|
|
do {
|
|
temp_stride.SetInt32(CPU_GRP_SIZE / 2);
|
|
temp_stride.Mult(&stride);
|
|
key_mpz.Add(&temp_stride);
|
|
startP = secp->ComputePublicKey(&key_mpz);
|
|
key_mpz.Sub(&temp_stride);
|
|
|
|
for(i = 0; i < hLength; i++) {
|
|
dx[i].ModSub(&Gn[i].x,&startP.x);
|
|
}
|
|
|
|
dx[i].ModSub(&Gn[i].x,&startP.x); // For the first point
|
|
dx[i + 1].ModSub(&_2Gn.x,&startP.x); // For the next center point
|
|
grp->ModInv();
|
|
|
|
pts[CPU_GRP_SIZE / 2] = startP;
|
|
|
|
for(i = 0; i<hLength; i++) {
|
|
pp = startP;
|
|
pn = startP;
|
|
|
|
// P = startP + i*G
|
|
dy.ModSub(&Gn[i].y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&Gn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
if(calculate_y) {
|
|
pp.y.ModSub(&Gn[i].x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&Gn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
}
|
|
|
|
// P = startP - i*G , if (x,y) = i*G then (x,-y) = -i*G
|
|
dyn.Set(&Gn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&Gn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
if(calculate_y) {
|
|
pn.y.ModSub(&Gn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&Gn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
}
|
|
|
|
pp_offset = CPU_GRP_SIZE / 2 + (i + 1);
|
|
pn_offset = CPU_GRP_SIZE / 2 - (i + 1);
|
|
|
|
pts[pp_offset] = pp;
|
|
pts[pn_offset] = pn;
|
|
|
|
if(FLAGENDOMORPHISM) {
|
|
/*
|
|
Q = (x,y)
|
|
For any point Q
|
|
Q*lambda = (x*beta mod p ,y)
|
|
Q*lambda is a Scalar Multiplication
|
|
x*beta is just a Multiplication (Very fast)
|
|
*/
|
|
|
|
if( calculate_y ) {
|
|
endomorphism_beta[pp_offset].y.Set(&pp.y);
|
|
endomorphism_beta[pn_offset].y.Set(&pn.y);
|
|
endomorphism_beta2[pp_offset].y.Set(&pp.y);
|
|
endomorphism_beta2[pn_offset].y.Set(&pn.y);
|
|
}
|
|
endomorphism_beta[pp_offset].x.ModMulK1(&pp.x, &beta);
|
|
endomorphism_beta[pn_offset].x.ModMulK1(&pn.x, &beta);
|
|
endomorphism_beta2[pp_offset].x.ModMulK1(&pp.x, &beta2);
|
|
endomorphism_beta2[pn_offset].x.ModMulK1(&pn.x, &beta2);
|
|
}
|
|
}
|
|
/*
|
|
Half point for endomorphism because pts[CPU_GRP_SIZE / 2] was not calcualte in the previous cycle
|
|
*/
|
|
if(FLAGENDOMORPHISM) {
|
|
if( calculate_y ) {
|
|
|
|
endomorphism_beta[CPU_GRP_SIZE / 2].y.Set(&pts[CPU_GRP_SIZE / 2].y);
|
|
endomorphism_beta2[CPU_GRP_SIZE / 2].y.Set(&pts[CPU_GRP_SIZE / 2].y);
|
|
}
|
|
endomorphism_beta[CPU_GRP_SIZE / 2].x.ModMulK1(&pts[CPU_GRP_SIZE / 2].x, &beta);
|
|
endomorphism_beta2[CPU_GRP_SIZE / 2].x.ModMulK1(&pts[CPU_GRP_SIZE / 2].x, &beta2);
|
|
}
|
|
|
|
// First point (startP - (GRP_SZIE/2)*G)
|
|
pn = startP;
|
|
dyn.Set(&Gn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&Gn[i].x);
|
|
|
|
if(calculate_y) {
|
|
pn.y.ModSub(&Gn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&Gn[i].y);
|
|
}
|
|
|
|
pts[0] = pn;
|
|
|
|
/*
|
|
First point for endomorphism because pts[0] was not calcualte previously
|
|
*/
|
|
if(FLAGENDOMORPHISM) {
|
|
if( calculate_y ) {
|
|
endomorphism_beta[0].y.Set(&pn.y);
|
|
endomorphism_beta2[0].y.Set(&pn.y);
|
|
}
|
|
endomorphism_beta[0].x.ModMulK1(&pn.x, &beta);
|
|
endomorphism_beta2[0].x.ModMulK1(&pn.x, &beta2);
|
|
}
|
|
|
|
|
|
for(j = 0; j < CPU_GRP_SIZE/4;j++){
|
|
switch(FLAGMODE) {
|
|
case MODE_RMD160:
|
|
case MODE_ADDRESS:
|
|
if(FLAGCRYPTO == CRYPTO_BTC){
|
|
|
|
if(FLAGSEARCH == SEARCH_COMPRESS || FLAGSEARCH == SEARCH_BOTH ){
|
|
if(FLAGENDOMORPHISM) {
|
|
secp->GetHash160_fromX(P2PKH,0x02,&pts[(j*4)].x,&pts[(j*4)+1].x,&pts[(j*4)+2].x,&pts[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[0][0],(uint8_t*)publickeyhashrmd160_endomorphism[0][1],(uint8_t*)publickeyhashrmd160_endomorphism[0][2],(uint8_t*)publickeyhashrmd160_endomorphism[0][3]);
|
|
secp->GetHash160_fromX(P2PKH,0x03,&pts[(j*4)].x,&pts[(j*4)+1].x,&pts[(j*4)+2].x,&pts[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[1][0],(uint8_t*)publickeyhashrmd160_endomorphism[1][1],(uint8_t*)publickeyhashrmd160_endomorphism[1][2],(uint8_t*)publickeyhashrmd160_endomorphism[1][3]);
|
|
|
|
secp->GetHash160_fromX(P2PKH,0x02,&endomorphism_beta[(j*4)].x,&endomorphism_beta[(j*4)+1].x,&endomorphism_beta[(j*4)+2].x,&endomorphism_beta[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[2][0],(uint8_t*)publickeyhashrmd160_endomorphism[2][1],(uint8_t*)publickeyhashrmd160_endomorphism[2][2],(uint8_t*)publickeyhashrmd160_endomorphism[2][3]);
|
|
secp->GetHash160_fromX(P2PKH,0x03,&endomorphism_beta[(j*4)].x,&endomorphism_beta[(j*4)+1].x,&endomorphism_beta[(j*4)+2].x,&endomorphism_beta[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[3][0],(uint8_t*)publickeyhashrmd160_endomorphism[3][1],(uint8_t*)publickeyhashrmd160_endomorphism[3][2],(uint8_t*)publickeyhashrmd160_endomorphism[3][3]);
|
|
|
|
secp->GetHash160_fromX(P2PKH,0x02,&endomorphism_beta2[(j*4)].x,&endomorphism_beta2[(j*4)+1].x,&endomorphism_beta2[(j*4)+2].x,&endomorphism_beta2[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[4][0],(uint8_t*)publickeyhashrmd160_endomorphism[4][1],(uint8_t*)publickeyhashrmd160_endomorphism[4][2],(uint8_t*)publickeyhashrmd160_endomorphism[4][3]);
|
|
secp->GetHash160_fromX(P2PKH,0x03,&endomorphism_beta2[(j*4)].x,&endomorphism_beta2[(j*4)+1].x,&endomorphism_beta2[(j*4)+2].x,&endomorphism_beta2[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[5][0],(uint8_t*)publickeyhashrmd160_endomorphism[5][1],(uint8_t*)publickeyhashrmd160_endomorphism[5][2],(uint8_t*)publickeyhashrmd160_endomorphism[5][3]);
|
|
}
|
|
else {
|
|
secp->GetHash160_fromX(P2PKH,0x02,&pts[(j*4)].x,&pts[(j*4)+1].x,&pts[(j*4)+2].x,&pts[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[0][0],(uint8_t*)publickeyhashrmd160_endomorphism[0][1],(uint8_t*)publickeyhashrmd160_endomorphism[0][2],(uint8_t*)publickeyhashrmd160_endomorphism[0][3]);
|
|
secp->GetHash160_fromX(P2PKH,0x03,&pts[(j*4)].x,&pts[(j*4)+1].x,&pts[(j*4)+2].x,&pts[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[1][0],(uint8_t*)publickeyhashrmd160_endomorphism[1][1],(uint8_t*)publickeyhashrmd160_endomorphism[1][2],(uint8_t*)publickeyhashrmd160_endomorphism[1][3]);
|
|
}
|
|
|
|
}
|
|
if(FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH){
|
|
if(FLAGENDOMORPHISM) {
|
|
for(l = 0; l < 4; l++) {
|
|
endomorphism_negeted_point[l] = secp->Negation(pts[(j*4)+l]);
|
|
}
|
|
secp->GetHash160(P2PKH,false, pts[(j*4)], pts[(j*4)+1], pts[(j*4)+2], pts[(j*4)+3],(uint8_t*)publickeyhashrmd160_endomorphism[6][0],(uint8_t*)publickeyhashrmd160_endomorphism[6][1],(uint8_t*)publickeyhashrmd160_endomorphism[6][2],(uint8_t*)publickeyhashrmd160_endomorphism[6][3]);
|
|
secp->GetHash160(P2PKH,false,endomorphism_negeted_point[0] ,endomorphism_negeted_point[1],endomorphism_negeted_point[2],endomorphism_negeted_point[3],(uint8_t*)publickeyhashrmd160_endomorphism[7][0],(uint8_t*)publickeyhashrmd160_endomorphism[7][1],(uint8_t*)publickeyhashrmd160_endomorphism[7][2],(uint8_t*)publickeyhashrmd160_endomorphism[7][3]);
|
|
for(l = 0; l < 4; l++) {
|
|
endomorphism_negeted_point[l] = secp->Negation(endomorphism_beta[(j*4)+l]);
|
|
}
|
|
secp->GetHash160(P2PKH,false,endomorphism_beta[(j*4)], endomorphism_beta[(j*4)+1], endomorphism_beta[(j*4)+2], endomorphism_beta[(j*4)+3] ,(uint8_t*)publickeyhashrmd160_endomorphism[8][0],(uint8_t*)publickeyhashrmd160_endomorphism[8][1],(uint8_t*)publickeyhashrmd160_endomorphism[8][2],(uint8_t*)publickeyhashrmd160_endomorphism[8][3]);
|
|
secp->GetHash160(P2PKH,false,endomorphism_negeted_point[0],endomorphism_negeted_point[1],endomorphism_negeted_point[2],endomorphism_negeted_point[3],(uint8_t*)publickeyhashrmd160_endomorphism[9][0],(uint8_t*)publickeyhashrmd160_endomorphism[9][1],(uint8_t*)publickeyhashrmd160_endomorphism[9][2],(uint8_t*)publickeyhashrmd160_endomorphism[9][3]);
|
|
|
|
for(l = 0; l < 4; l++) {
|
|
endomorphism_negeted_point[l] = secp->Negation(endomorphism_beta2[(j*4)+l]);
|
|
}
|
|
secp->GetHash160(P2PKH,false, endomorphism_beta2[(j*4)], endomorphism_beta2[(j*4)+1] , endomorphism_beta2[(j*4)+2] , endomorphism_beta2[(j*4)+3] ,(uint8_t*)publickeyhashrmd160_endomorphism[10][0],(uint8_t*)publickeyhashrmd160_endomorphism[10][1],(uint8_t*)publickeyhashrmd160_endomorphism[10][2],(uint8_t*)publickeyhashrmd160_endomorphism[10][3]);
|
|
secp->GetHash160(P2PKH,false, endomorphism_negeted_point[0], endomorphism_negeted_point[1], endomorphism_negeted_point[2],endomorphism_negeted_point[3],(uint8_t*)publickeyhashrmd160_endomorphism[11][0],(uint8_t*)publickeyhashrmd160_endomorphism[11][1],(uint8_t*)publickeyhashrmd160_endomorphism[11][2],(uint8_t*)publickeyhashrmd160_endomorphism[11][3]);
|
|
|
|
}
|
|
else {
|
|
secp->GetHash160(P2PKH,false,pts[(j*4)],pts[(j*4)+1],pts[(j*4)+2],pts[(j*4)+3],(uint8_t*)publickeyhashrmd160_uncompress[0],(uint8_t*)publickeyhashrmd160_uncompress[1],(uint8_t*)publickeyhashrmd160_uncompress[2],(uint8_t*)publickeyhashrmd160_uncompress[3]);
|
|
|
|
}
|
|
}
|
|
}
|
|
else if(FLAGCRYPTO == CRYPTO_ETH){
|
|
if(FLAGENDOMORPHISM) {
|
|
for(k = 0; k < 4;k++) {
|
|
endomorphism_negeted_point[k] = secp->Negation(pts[(j*4)+k]);
|
|
generate_binaddress_eth(pts[(4*j)+k],(uint8_t*)publickeyhashrmd160_endomorphism[0][k]);
|
|
generate_binaddress_eth(endomorphism_negeted_point[k],(uint8_t*)publickeyhashrmd160_endomorphism[1][k]);
|
|
endomorphism_negeted_point[k] = secp->Negation(endomorphism_beta[(j*4)+k]);
|
|
generate_binaddress_eth(endomorphism_beta[(4*j)+k],(uint8_t*)publickeyhashrmd160_endomorphism[2][k]);
|
|
generate_binaddress_eth(endomorphism_negeted_point[k],(uint8_t*)publickeyhashrmd160_endomorphism[3][k]);
|
|
endomorphism_negeted_point[k] = secp->Negation(endomorphism_beta2[(j*4)+k]);
|
|
generate_binaddress_eth(endomorphism_beta[(4*j)+k],(uint8_t*)publickeyhashrmd160_endomorphism[4][k]);
|
|
generate_binaddress_eth(endomorphism_negeted_point[k],(uint8_t*)publickeyhashrmd160_endomorphism[5][k]);
|
|
}
|
|
}
|
|
else {
|
|
for(k = 0; k < 4;k++) {
|
|
generate_binaddress_eth(pts[(4*j)+k],(uint8_t*)publickeyhashrmd160_uncompress[k]);
|
|
}
|
|
}
|
|
|
|
}
|
|
break;
|
|
}
|
|
switch(FLAGMODE) {
|
|
case MODE_RMD160:
|
|
case MODE_ADDRESS:
|
|
if( FLAGCRYPTO == CRYPTO_BTC) {
|
|
for(k = 0; k < 4;k++) {
|
|
if(FLAGSEARCH == SEARCH_COMPRESS || FLAGSEARCH == SEARCH_BOTH){
|
|
if(FLAGENDOMORPHISM) {
|
|
for(l = 0;l < 6; l++) {
|
|
r = bloom_check(&bloom,publickeyhashrmd160_endomorphism[l][k],MAXLENGTHADDRESS);
|
|
if(r) {
|
|
r = searchbinary(addressTable,publickeyhashrmd160_endomorphism[l][k],N);
|
|
if(r) {
|
|
keyfound.SetInt32(k);
|
|
keyfound.Mult(&stride);
|
|
keyfound.Add(&key_mpz);
|
|
publickey = secp->ComputePublicKey(&keyfound);
|
|
switch(l) {
|
|
case 0: //Original point, prefix 02
|
|
if(publickey.y.IsOdd()) { //if the current publickey is odd that means, we need to negate the keyfound to get the correct key
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
// else we dont need to chage the current keyfound because it already have prefix 02
|
|
break;
|
|
case 1: //Original point, prefix 03
|
|
if(publickey.y.IsEven()) { //if the current publickey is even that means, we need to negate the keyfound to get the correct key
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
// else we dont need to chage the current keyfound because it already have prefix 03
|
|
break;
|
|
case 2: //Beta point, prefix 02
|
|
keyfound.ModMulK1order(&lambda);
|
|
if(publickey.y.IsOdd()) { //if the current publickey is odd that means, we need to negate the keyfound to get the correct key
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
// else we dont need to chage the current keyfound because it already have prefix 02
|
|
break;
|
|
case 3: //Beta point, prefix 03
|
|
keyfound.ModMulK1order(&lambda);
|
|
if(publickey.y.IsEven()) { //if the current publickey is even that means, we need to negate the keyfound to get the correct key
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
// else we dont need to chage the current keyfound because it already have prefix 02
|
|
break;
|
|
case 4: //Beta^2 point, prefix 02
|
|
keyfound.ModMulK1order(&lambda2);
|
|
if(publickey.y.IsOdd()) { //if the current publickey is odd that means, we need to negate the keyfound to get the correct key
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
// else we dont need to chage the current keyfound because it already have prefix 02
|
|
break;
|
|
case 5: //Beta^2 point, prefix 03
|
|
keyfound.ModMulK1order(&lambda2);
|
|
if(publickey.y.IsEven()) { //if the current publickey is even that means, we need to negate the keyfound to get the correct key
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
// else we dont need to chage the current keyfound because it already have prefix 02
|
|
break;
|
|
}
|
|
writekey(true,&keyfound);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for(l = 0;l < 2; l++) {
|
|
r = bloom_check(&bloom,publickeyhashrmd160_endomorphism[l][k],MAXLENGTHADDRESS);
|
|
if(r) {
|
|
r = searchbinary(addressTable,publickeyhashrmd160_endomorphism[l][k],N);
|
|
if(r) {
|
|
keyfound.SetInt32(k);
|
|
keyfound.Mult(&stride);
|
|
keyfound.Add(&key_mpz);
|
|
|
|
publickey = secp->ComputePublicKey(&keyfound);
|
|
secp->GetHash160(P2PKH,true,publickey,(uint8_t*)publickeyhashrmd160);
|
|
if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160,20) != 0) {
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
writekey(true,&keyfound);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH) {
|
|
if(FLAGENDOMORPHISM) {
|
|
for(l = 6;l < 12; l++) { //We check the array from 6 to 12(excluded) because we save the uncompressed information there
|
|
r = bloom_check(&bloom,publickeyhashrmd160_endomorphism[l][k],MAXLENGTHADDRESS); //Check in Bloom filter
|
|
if(r) {
|
|
r = searchbinary(addressTable,publickeyhashrmd160_endomorphism[l][k],N); //Check in Array using Binary search
|
|
if(r) {
|
|
keyfound.SetInt32(k);
|
|
keyfound.Mult(&stride);
|
|
keyfound.Add(&key_mpz);
|
|
switch(l) {
|
|
case 6:
|
|
case 7:
|
|
publickey = secp->ComputePublicKey(&keyfound);
|
|
secp->GetHash160(P2PKH,false,publickey,(uint8_t*)publickeyhashrmd160_uncompress[0]);
|
|
if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160_uncompress[0],20) != 0){
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
break;
|
|
case 8:
|
|
case 9:
|
|
keyfound.ModMulK1order(&lambda);
|
|
publickey = secp->ComputePublicKey(&keyfound);
|
|
secp->GetHash160(P2PKH,false,publickey,(uint8_t*)publickeyhashrmd160_uncompress[0]);
|
|
if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160_uncompress[0],20) != 0){
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
break;
|
|
case 10:
|
|
case 11:
|
|
keyfound.ModMulK1order(&lambda2);
|
|
publickey = secp->ComputePublicKey(&keyfound);
|
|
secp->GetHash160(P2PKH,false,publickey,(uint8_t*)publickeyhashrmd160_uncompress[0]);
|
|
if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160_uncompress[0],20) != 0){
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
break;
|
|
}
|
|
writekey(false,&keyfound);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
r = bloom_check(&bloom,publickeyhashrmd160_uncompress[k],MAXLENGTHADDRESS);
|
|
if(r) {
|
|
r = searchbinary(addressTable,publickeyhashrmd160_uncompress[k],N);
|
|
if(r) {
|
|
keyfound.SetInt32(k);
|
|
keyfound.Mult(&stride);
|
|
keyfound.Add(&key_mpz);
|
|
|
|
writekey(false,&keyfound);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if( FLAGCRYPTO == CRYPTO_ETH) {
|
|
if(FLAGENDOMORPHISM) {
|
|
for(k = 0; k < 4;k++) {
|
|
for(l = 0;l < 6; l++) {
|
|
r = bloom_check(&bloom,publickeyhashrmd160_endomorphism[l][k],MAXLENGTHADDRESS);
|
|
if(r) {
|
|
r = searchbinary(addressTable,publickeyhashrmd160_endomorphism[l][k],N);
|
|
if(r) {
|
|
keyfound.SetInt32(k);
|
|
keyfound.Mult(&stride);
|
|
keyfound.Add(&key_mpz);
|
|
switch(l) {
|
|
case 0:
|
|
case 1:
|
|
publickey = secp->ComputePublicKey(&keyfound);
|
|
generate_binaddress_eth(publickey,(uint8_t*)publickeyhashrmd160_uncompress[0]);
|
|
if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160_uncompress[0],20) != 0){
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
keyfound.ModMulK1order(&lambda);
|
|
publickey = secp->ComputePublicKey(&keyfound);
|
|
generate_binaddress_eth(publickey,(uint8_t*)publickeyhashrmd160_uncompress[0]);
|
|
if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160_uncompress[0],20) != 0){
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
break;
|
|
case 4:
|
|
case 5:
|
|
keyfound.ModMulK1order(&lambda2);
|
|
publickey = secp->ComputePublicKey(&keyfound);
|
|
generate_binaddress_eth(publickey,(uint8_t*)publickeyhashrmd160_uncompress[0]);
|
|
if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160_uncompress[0],20) != 0){
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
break;
|
|
}
|
|
writekeyeth(&keyfound);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for(k = 0; k < 4;k++) {
|
|
r = bloom_check(&bloom,publickeyhashrmd160_uncompress[k],MAXLENGTHADDRESS);
|
|
if(r) {
|
|
r = searchbinary(addressTable,publickeyhashrmd160_uncompress[k],N);
|
|
if(r) {
|
|
keyfound.SetInt32(k);
|
|
keyfound.Mult(&stride);
|
|
keyfound.Add(&key_mpz);
|
|
writekeyeth(&keyfound);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case MODE_XPOINT:
|
|
for(k = 0; k < 4;k++) {
|
|
if(FLAGENDOMORPHISM) {
|
|
pts[(4*j)+k].x.Get32Bytes((unsigned char *)rawvalue);
|
|
r = bloom_check(&bloom,rawvalue,MAXLENGTHADDRESS);
|
|
if(r) {
|
|
r = searchbinary(addressTable,rawvalue,N);
|
|
if(r) {
|
|
keyfound.SetInt32(k);
|
|
keyfound.Mult(&stride);
|
|
keyfound.Add(&key_mpz);
|
|
|
|
writekey(false,&keyfound);
|
|
}
|
|
}
|
|
endomorphism_beta[(j*4)+k].x.Get32Bytes((unsigned char *)rawvalue);
|
|
r = bloom_check(&bloom,rawvalue,MAXLENGTHADDRESS);
|
|
if(r) {
|
|
r = searchbinary(addressTable,rawvalue,N);
|
|
if(r) {
|
|
keyfound.SetInt32(k);
|
|
keyfound.Mult(&stride);
|
|
keyfound.Add(&key_mpz);
|
|
keyfound.ModMulK1order(&lambda);
|
|
|
|
writekey(false,&keyfound);
|
|
}
|
|
}
|
|
|
|
endomorphism_beta2[(j*4)+k].x.Get32Bytes((unsigned char *)rawvalue);
|
|
r = bloom_check(&bloom,rawvalue,MAXLENGTHADDRESS);
|
|
if(r) {
|
|
r = searchbinary(addressTable,rawvalue,N);
|
|
if(r) {
|
|
keyfound.SetInt32(k);
|
|
keyfound.Mult(&stride);
|
|
keyfound.Add(&key_mpz);
|
|
keyfound.ModMulK1order(&lambda2);
|
|
writekey(false,&keyfound);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
pts[(4*j)+k].x.Get32Bytes((unsigned char *)rawvalue);
|
|
r = bloom_check(&bloom,rawvalue,MAXLENGTHADDRESS);
|
|
if(r) {
|
|
r = searchbinary(addressTable,rawvalue,N);
|
|
if(r) {
|
|
keyfound.SetInt32(k);
|
|
keyfound.Mult(&stride);
|
|
keyfound.Add(&key_mpz);
|
|
|
|
writekey(false,&keyfound);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
count+=4;
|
|
temp_stride.SetInt32(4);
|
|
temp_stride.Mult(&stride);
|
|
key_mpz.Add(&temp_stride);
|
|
}
|
|
|
|
steps[thread_number]++;
|
|
|
|
// Next start point (startP + GRP_SIZE*G)
|
|
pp = startP;
|
|
dy.ModSub(&_2Gn.y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i + 1]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&_2Gn.x);
|
|
|
|
//The Y value for the next start point always need to be calculated
|
|
pp.y.ModSub(&_2Gn.x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&_2Gn.y);
|
|
startP = pp;
|
|
}while(count < N_SEQUENTIAL_MAX && continue_flag);
|
|
}
|
|
} while(continue_flag);
|
|
ends[thread_number] = 1;
|
|
return NULL;
|
|
}
|
|
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
DWORD WINAPI thread_process_vanity(LPVOID vargp) {
|
|
#else
|
|
void *thread_process_vanity(void *vargp) {
|
|
#endif
|
|
struct tothread *tt;
|
|
Point pts[CPU_GRP_SIZE];
|
|
Point endomorphism_beta[CPU_GRP_SIZE];
|
|
Point endomorphism_beta2[CPU_GRP_SIZE];
|
|
Point endomorphism_negeted_point[4];
|
|
|
|
Int dx[CPU_GRP_SIZE / 2 + 1];
|
|
|
|
IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1);
|
|
Point startP;
|
|
Int dy;
|
|
Int dyn;
|
|
Int _s;
|
|
Int _p;
|
|
Point pp; //point positive
|
|
Point pn; //point negative
|
|
int i,hLength = (CPU_GRP_SIZE / 2 - 1);
|
|
int l,pp_offset,pn_offset;
|
|
uint64_t j,count;
|
|
Point R,temporal,publickey;
|
|
int thread_number,continue_flag = 1,k;
|
|
char *hextemp = NULL;
|
|
char publickeyhashrmd160[20];
|
|
char publickeyhashrmd160_uncompress[4][20];
|
|
char publickeyhashrmd160_endomorphism[12][4][20];
|
|
|
|
Int key_mpz,temp_stride,keyfound;
|
|
tt = (struct tothread *)vargp;
|
|
thread_number = tt->nt;
|
|
free(tt);
|
|
grp->Set(dx);
|
|
|
|
|
|
//if FLAGENDOMORPHISM == 1 and only compress search is enabled then there is no need to calculate the Y value value
|
|
|
|
bool calculate_y = FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH;
|
|
|
|
/*
|
|
if(FLAGDEBUG && thread_number == 0) {
|
|
printf("[D] vanity_rmd_targets = %i fillllll\n",vanity_rmd_targets);
|
|
printf("[D] vanity_rmd_total = %i\n",vanity_rmd_total);
|
|
for(i =0; i < vanity_rmd_targets;i++) {
|
|
printf("[D] vanity_rmd_limits[%li] = %i\n",i,vanity_rmd_limits[i]);
|
|
|
|
}
|
|
printf("[D] vanity_rmd_minimun_bytes_check_length = %i\n",vanity_rmd_minimun_bytes_check_length);
|
|
}
|
|
*/
|
|
|
|
|
|
do {
|
|
if(FLAGRANDOM){
|
|
key_mpz.Rand(&n_range_start,&n_range_end);
|
|
}
|
|
else {
|
|
if(n_range_start.IsLower(&n_range_end)) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(write_random, INFINITE);
|
|
key_mpz.Set(&n_range_start);
|
|
n_range_start.Add(N_SEQUENTIAL_MAX);
|
|
ReleaseMutex(write_random);
|
|
#else
|
|
pthread_mutex_lock(&write_random);
|
|
key_mpz.Set(&n_range_start);
|
|
n_range_start.Add(N_SEQUENTIAL_MAX);
|
|
pthread_mutex_unlock(&write_random);
|
|
#endif
|
|
}
|
|
else {
|
|
continue_flag = 0;
|
|
}
|
|
}
|
|
if(continue_flag) {
|
|
count = 0;
|
|
if(FLAGMATRIX) {
|
|
hextemp = key_mpz.GetBase16();
|
|
printf("Base key: %s thread %i\n",hextemp,thread_number);
|
|
fflush(stdout);
|
|
free(hextemp);
|
|
}
|
|
else {
|
|
if(FLAGQUIET == 0) {
|
|
hextemp = key_mpz.GetBase16();
|
|
printf("\rBase key: %s \r",hextemp);
|
|
fflush(stdout);
|
|
free(hextemp);
|
|
THREADOUTPUT = 1;
|
|
}
|
|
}
|
|
do {
|
|
temp_stride.SetInt32(CPU_GRP_SIZE / 2);
|
|
temp_stride.Mult(&stride);
|
|
key_mpz.Add(&temp_stride);
|
|
startP = secp->ComputePublicKey(&key_mpz);
|
|
key_mpz.Sub(&temp_stride);
|
|
|
|
for(i = 0; i < hLength; i++) {
|
|
dx[i].ModSub(&Gn[i].x,&startP.x);
|
|
}
|
|
|
|
dx[i].ModSub(&Gn[i].x,&startP.x); // For the first point
|
|
dx[i + 1].ModSub(&_2Gn.x,&startP.x); // For the next center point
|
|
grp->ModInv();
|
|
|
|
pts[CPU_GRP_SIZE / 2] = startP;
|
|
|
|
for(i = 0; i<hLength; i++) {
|
|
pp = startP;
|
|
pn = startP;
|
|
|
|
// P = startP + i*G
|
|
dy.ModSub(&Gn[i].y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&Gn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
if(calculate_y) {
|
|
pp.y.ModSub(&Gn[i].x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&Gn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
}
|
|
|
|
// P = startP - i*G , if (x,y) = i*G then (x,-y) = -i*G
|
|
dyn.Set(&Gn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&Gn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
if( calculate_y ) {
|
|
pn.y.ModSub(&Gn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&Gn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
}
|
|
pp_offset = CPU_GRP_SIZE / 2 + (i + 1);
|
|
pn_offset = CPU_GRP_SIZE / 2 - (i + 1);
|
|
|
|
pts[pp_offset] = pp;
|
|
pts[pn_offset] = pn;
|
|
|
|
if(FLAGENDOMORPHISM) {
|
|
/*
|
|
Q = (x,y)
|
|
For any point Q
|
|
Q*lambda = (x*beta mod p ,y)
|
|
Q*lambda is a Scalar Multiplication
|
|
x*beta is just a Multiplication (Very fast)
|
|
*/
|
|
|
|
if( calculate_y ) {
|
|
endomorphism_beta[pp_offset].y.Set(&pp.y);
|
|
endomorphism_beta[pn_offset].y.Set(&pn.y);
|
|
endomorphism_beta2[pp_offset].y.Set(&pp.y);
|
|
endomorphism_beta2[pn_offset].y.Set(&pn.y);
|
|
}
|
|
endomorphism_beta[pp_offset].x.ModMulK1(&pp.x, &beta);
|
|
endomorphism_beta[pn_offset].x.ModMulK1(&pn.x, &beta);
|
|
endomorphism_beta2[pp_offset].x.ModMulK1(&pp.x, &beta2);
|
|
endomorphism_beta2[pn_offset].x.ModMulK1(&pn.x, &beta2);
|
|
|
|
/*
|
|
if(FLAGDEBUG) {
|
|
hextemp = secp->GetPublicKeyHex(false,pp);
|
|
secp->GetHash160(P2PKH,false, pp,(uint8_t*)publickeyhashrmd160_uncompress[0]);
|
|
rmd160toaddress_dst(publickeyhashrmd160_uncompress[0],address);
|
|
printf("[D] pp[%i] = %s , %s y = %s\n",pp_offset,hextemp,address,pp.y.IsEven() ? "Even" : "Odd");
|
|
free(hextemp);
|
|
|
|
hextemp = secp->GetPublicKeyHex(false,pn);
|
|
secp->GetHash160(P2PKH,false, pn,(uint8_t*)publickeyhashrmd160_uncompress[0]);
|
|
rmd160toaddress_dst(publickeyhashrmd160_uncompress[0],address);
|
|
printf("[D] pn[%i] = %s , %s y = %s\n",pn_offset,hextemp,address,pn.y.IsEven() ? "Even" : "Odd");
|
|
free(hextemp);
|
|
|
|
|
|
hextemp = secp->GetPublicKeyHex(false,endomorphism_beta[pp_offset]);
|
|
secp->GetHash160(P2PKH,false, endomorphism_beta[pp_offset],(uint8_t*)publickeyhashrmd160_uncompress[0]);
|
|
rmd160toaddress_dst(publickeyhashrmd160_uncompress[0],address);
|
|
printf("[D] endomorphism_beta[%i] = %s , %s y = %s\n",pp_offset,hextemp,address,endomorphism_beta[pp_offset].y.IsEven() ? "Even" : "Odd");
|
|
free(hextemp);
|
|
hextemp = secp->GetPublicKeyHex(false,endomorphism_beta[pn_offset]);
|
|
secp->GetHash160(P2PKH,false, endomorphism_beta[pn_offset],(uint8_t*)publickeyhashrmd160_uncompress[0]);
|
|
rmd160toaddress_dst(publickeyhashrmd160_uncompress[0],address);
|
|
|
|
printf("[D] endomorphism_beta[%i] = %s , %s y = %s\n",pn_offset,hextemp,address,endomorphism_beta[pn_offset].y.IsEven() ? "Even" : "Odd");
|
|
free(hextemp);
|
|
hextemp = secp->GetPublicKeyHex(false,endomorphism_beta2[pp_offset]);
|
|
secp->GetHash160(P2PKH,false, endomorphism_beta2[pp_offset],(uint8_t*)publickeyhashrmd160_uncompress[0]);
|
|
rmd160toaddress_dst(publickeyhashrmd160_uncompress[0],address);
|
|
printf("[D] endomorphism_beta2[%i] = %s , %s y = %s\n",pp_offset,hextemp,address,endomorphism_beta2[pp_offset].y.IsEven() ? "Even" : "Odd");
|
|
free(hextemp);
|
|
hextemp = secp->GetPublicKeyHex(false,endomorphism_beta2[pn_offset]);
|
|
secp->GetHash160(P2PKH,false, endomorphism_beta2[pn_offset],(uint8_t*)publickeyhashrmd160_uncompress[0]);
|
|
rmd160toaddress_dst(publickeyhashrmd160_uncompress[0],address);
|
|
printf("[D] endomorphism_beta2[%i] = %s , %s y = %s\n",pn_offset,hextemp,address,endomorphism_beta2[pn_offset].y.IsEven() ? "Even" : "Odd");
|
|
free(hextemp);
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
/*
|
|
Half point for endomorphism because pts[CPU_GRP_SIZE / 2] was not calcualte in the previous cycle
|
|
*/
|
|
if(FLAGENDOMORPHISM) {
|
|
if( calculate_y ) {
|
|
|
|
endomorphism_beta[CPU_GRP_SIZE / 2].y.Set(&pts[CPU_GRP_SIZE / 2].y);
|
|
endomorphism_beta2[CPU_GRP_SIZE / 2].y.Set(&pts[CPU_GRP_SIZE / 2].y);
|
|
}
|
|
endomorphism_beta[CPU_GRP_SIZE / 2].x.ModMulK1(&pts[CPU_GRP_SIZE / 2].x, &beta);
|
|
endomorphism_beta2[CPU_GRP_SIZE / 2].x.ModMulK1(&pts[CPU_GRP_SIZE / 2].x, &beta2);
|
|
}
|
|
|
|
// First point (startP - (GRP_SZIE/2)*G)
|
|
pn = startP;
|
|
dyn.Set(&Gn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&Gn[i].x);
|
|
|
|
if(calculate_y ) {
|
|
pn.y.ModSub(&Gn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&Gn[i].y);
|
|
}
|
|
pts[0] = pn;
|
|
|
|
/*
|
|
First point for endomorphism because pts[0] was not calcualte previously
|
|
*/
|
|
if(FLAGENDOMORPHISM) {
|
|
if( calculate_y ) {
|
|
endomorphism_beta[0].y.Set(&pn.y);
|
|
endomorphism_beta2[0].y.Set(&pn.y);
|
|
}
|
|
endomorphism_beta[0].x.ModMulK1(&pn.x, &beta);
|
|
endomorphism_beta2[0].x.ModMulK1(&pn.x, &beta2);
|
|
}
|
|
|
|
|
|
for(j = 0; j < CPU_GRP_SIZE/4;j++) {
|
|
if(FLAGSEARCH == SEARCH_COMPRESS || FLAGSEARCH == SEARCH_BOTH ){
|
|
if(FLAGENDOMORPHISM) {
|
|
secp->GetHash160_fromX(P2PKH,0x02,&pts[(j*4)].x,&pts[(j*4)+1].x,&pts[(j*4)+2].x,&pts[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[0][0],(uint8_t*)publickeyhashrmd160_endomorphism[0][1],(uint8_t*)publickeyhashrmd160_endomorphism[0][2],(uint8_t*)publickeyhashrmd160_endomorphism[0][3]);
|
|
secp->GetHash160_fromX(P2PKH,0x03,&pts[(j*4)].x,&pts[(j*4)+1].x,&pts[(j*4)+2].x,&pts[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[1][0],(uint8_t*)publickeyhashrmd160_endomorphism[1][1],(uint8_t*)publickeyhashrmd160_endomorphism[1][2],(uint8_t*)publickeyhashrmd160_endomorphism[1][3]);
|
|
|
|
secp->GetHash160_fromX(P2PKH,0x02,&endomorphism_beta[(j*4)].x,&endomorphism_beta[(j*4)+1].x,&endomorphism_beta[(j*4)+2].x,&endomorphism_beta[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[2][0],(uint8_t*)publickeyhashrmd160_endomorphism[2][1],(uint8_t*)publickeyhashrmd160_endomorphism[2][2],(uint8_t*)publickeyhashrmd160_endomorphism[2][3]);
|
|
secp->GetHash160_fromX(P2PKH,0x03,&endomorphism_beta[(j*4)].x,&endomorphism_beta[(j*4)+1].x,&endomorphism_beta[(j*4)+2].x,&endomorphism_beta[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[3][0],(uint8_t*)publickeyhashrmd160_endomorphism[3][1],(uint8_t*)publickeyhashrmd160_endomorphism[3][2],(uint8_t*)publickeyhashrmd160_endomorphism[3][3]);
|
|
|
|
secp->GetHash160_fromX(P2PKH,0x02,&endomorphism_beta2[(j*4)].x,&endomorphism_beta2[(j*4)+1].x,&endomorphism_beta2[(j*4)+2].x,&endomorphism_beta2[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[4][0],(uint8_t*)publickeyhashrmd160_endomorphism[4][1],(uint8_t*)publickeyhashrmd160_endomorphism[4][2],(uint8_t*)publickeyhashrmd160_endomorphism[4][3]);
|
|
secp->GetHash160_fromX(P2PKH,0x03,&endomorphism_beta2[(j*4)].x,&endomorphism_beta2[(j*4)+1].x,&endomorphism_beta2[(j*4)+2].x,&endomorphism_beta2[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[5][0],(uint8_t*)publickeyhashrmd160_endomorphism[5][1],(uint8_t*)publickeyhashrmd160_endomorphism[5][2],(uint8_t*)publickeyhashrmd160_endomorphism[5][3]);
|
|
|
|
}
|
|
else {
|
|
secp->GetHash160_fromX(P2PKH,0x02,&pts[(j*4)].x,&pts[(j*4)+1].x,&pts[(j*4)+2].x,&pts[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[0][0],(uint8_t*)publickeyhashrmd160_endomorphism[0][1],(uint8_t*)publickeyhashrmd160_endomorphism[0][2],(uint8_t*)publickeyhashrmd160_endomorphism[0][3]);
|
|
secp->GetHash160_fromX(P2PKH,0x03,&pts[(j*4)].x,&pts[(j*4)+1].x,&pts[(j*4)+2].x,&pts[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[1][0],(uint8_t*)publickeyhashrmd160_endomorphism[1][1],(uint8_t*)publickeyhashrmd160_endomorphism[1][2],(uint8_t*)publickeyhashrmd160_endomorphism[1][3]);
|
|
}
|
|
}
|
|
if(FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH) {
|
|
if(FLAGENDOMORPHISM) {
|
|
for(l = 0; l < 4; l++) {
|
|
endomorphism_negeted_point[l] = secp->Negation(pts[(j*4)+l]);
|
|
}
|
|
secp->GetHash160(P2PKH,false, pts[(j*4)], pts[(j*4)+1], pts[(j*4)+2], pts[(j*4)+3],(uint8_t*)publickeyhashrmd160_endomorphism[6][0],(uint8_t*)publickeyhashrmd160_endomorphism[6][1],(uint8_t*)publickeyhashrmd160_endomorphism[6][2],(uint8_t*)publickeyhashrmd160_endomorphism[6][3]);
|
|
secp->GetHash160(P2PKH,false,endomorphism_negeted_point[0] ,endomorphism_negeted_point[1],endomorphism_negeted_point[2],endomorphism_negeted_point[3],(uint8_t*)publickeyhashrmd160_endomorphism[7][0],(uint8_t*)publickeyhashrmd160_endomorphism[7][1],(uint8_t*)publickeyhashrmd160_endomorphism[7][2],(uint8_t*)publickeyhashrmd160_endomorphism[7][3]);
|
|
for(l = 0; l < 4; l++) {
|
|
endomorphism_negeted_point[l] = secp->Negation(endomorphism_beta[(j*4)+l]);
|
|
}
|
|
secp->GetHash160(P2PKH,false,endomorphism_beta[(j*4)], endomorphism_beta[(j*4)+1], endomorphism_beta[(j*4)+2], endomorphism_beta[(j*4)+3] ,(uint8_t*)publickeyhashrmd160_endomorphism[8][0],(uint8_t*)publickeyhashrmd160_endomorphism[8][1],(uint8_t*)publickeyhashrmd160_endomorphism[8][2],(uint8_t*)publickeyhashrmd160_endomorphism[8][3]);
|
|
secp->GetHash160(P2PKH,false,endomorphism_negeted_point[0],endomorphism_negeted_point[1],endomorphism_negeted_point[2],endomorphism_negeted_point[3],(uint8_t*)publickeyhashrmd160_endomorphism[9][0],(uint8_t*)publickeyhashrmd160_endomorphism[9][1],(uint8_t*)publickeyhashrmd160_endomorphism[9][2],(uint8_t*)publickeyhashrmd160_endomorphism[9][3]);
|
|
|
|
for(l = 0; l < 4; l++) {
|
|
endomorphism_negeted_point[l] = secp->Negation(endomorphism_beta2[(j*4)+l]);
|
|
}
|
|
secp->GetHash160(P2PKH,false, endomorphism_beta2[(j*4)], endomorphism_beta2[(j*4)+1] , endomorphism_beta2[(j*4)+2] , endomorphism_beta2[(j*4)+3] ,(uint8_t*)publickeyhashrmd160_endomorphism[10][0],(uint8_t*)publickeyhashrmd160_endomorphism[10][1],(uint8_t*)publickeyhashrmd160_endomorphism[10][2],(uint8_t*)publickeyhashrmd160_endomorphism[10][3]);
|
|
secp->GetHash160(P2PKH,false, endomorphism_negeted_point[0], endomorphism_negeted_point[1], endomorphism_negeted_point[2],endomorphism_negeted_point[3],(uint8_t*)publickeyhashrmd160_endomorphism[11][0],(uint8_t*)publickeyhashrmd160_endomorphism[11][1],(uint8_t*)publickeyhashrmd160_endomorphism[11][2],(uint8_t*)publickeyhashrmd160_endomorphism[11][3]);
|
|
}
|
|
else {
|
|
secp->GetHash160(P2PKH,false,pts[(j*4)],pts[(j*4)+1],pts[(j*4)+2],pts[(j*4)+3],(uint8_t*)publickeyhashrmd160_uncompress[0],(uint8_t*)publickeyhashrmd160_uncompress[1],(uint8_t*)publickeyhashrmd160_uncompress[2],(uint8_t*)publickeyhashrmd160_uncompress[3]);
|
|
|
|
}
|
|
}
|
|
for(k = 0; k < 4;k++) {
|
|
if(FLAGSEARCH == SEARCH_COMPRESS || FLAGSEARCH == SEARCH_BOTH ){
|
|
if(FLAGENDOMORPHISM) {
|
|
for(l = 0;l < 6; l++) {
|
|
if(vanityrmdmatch((uint8_t*)publickeyhashrmd160_endomorphism[l][k])) {
|
|
// Here the given publickeyhashrmd160 match againts one of the vanity targets
|
|
// We need to check which of the cases is it.
|
|
|
|
keyfound.SetInt32(k);
|
|
keyfound.Mult(&stride);
|
|
keyfound.Add(&key_mpz);
|
|
publickey = secp->ComputePublicKey(&keyfound);
|
|
|
|
/*
|
|
if(FLAGDEBUG) {
|
|
|
|
rmd160toaddress_dst(publickeyhashrmd160_endomorphism[l][k],address);
|
|
|
|
hextemp = tohex(publickeyhashrmd160_endomorphism[l][k],20);
|
|
printf("[D] hash found: %s : address %s\n",hextemp,address);
|
|
free(hextemp);
|
|
hextemp = keyfound.GetBase16();
|
|
printf("[D] key: %s\n",hextemp);
|
|
free(hextemp);
|
|
|
|
hextemp = secp->GetPublicKeyHex(true,publickey);
|
|
printf("[D] GetPublicKeyHex: %s\n",hextemp);
|
|
free(hextemp);
|
|
|
|
printf("[D] found something l = %i\n",l);
|
|
|
|
}
|
|
*/
|
|
|
|
switch(l) {
|
|
case 0: //Original point, prefix 02
|
|
if(publickey.y.IsOdd()) { //if the current publickey is odd that means, we need to negate the keyfound to get the correct key
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
// else we dont need to chage the current keyfound because it already have prefix 02
|
|
break;
|
|
case 1: //Original point, prefix 03
|
|
if(publickey.y.IsEven()) { //if the current publickey is even that means, we need to negate the keyfound to get the correct key
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
// else we dont need to chage the current keyfound because it already have prefix 03
|
|
break;
|
|
case 2: //Beta point, prefix 02
|
|
keyfound.ModMulK1order(&lambda);
|
|
if(publickey.y.IsOdd()) { //if the current publickey is odd that means, we need to negate the keyfound to get the correct key
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
// else we dont need to chage the current keyfound because it already have prefix 02
|
|
break;
|
|
case 3: //Beta point, prefix 03
|
|
keyfound.ModMulK1order(&lambda);
|
|
if(publickey.y.IsEven()) { //if the current publickey is even that means, we need to negate the keyfound to get the correct key
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
// else we dont need to chage the current keyfound because it already have prefix 02
|
|
break;
|
|
case 4: //Beta^2 point, prefix 02
|
|
keyfound.ModMulK1order(&lambda2);
|
|
if(publickey.y.IsOdd()) { //if the current publickey is odd that means, we need to negate the keyfound to get the correct key
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
// else we dont need to chage the current keyfound because it already have prefix 02
|
|
break;
|
|
case 5: //Beta^2 point, prefix 03
|
|
keyfound.ModMulK1order(&lambda2);
|
|
if(publickey.y.IsEven()) { //if the current publickey is even that means, we need to negate the keyfound to get the correct key
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
// else we dont need to chage the current keyfound because it already have prefix 02
|
|
break;
|
|
}
|
|
writevanitykey(true,&keyfound);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
for(l = 0;l < 2; l++) {
|
|
if(vanityrmdmatch((uint8_t*)publickeyhashrmd160_endomorphism[l][k])) {
|
|
keyfound.SetInt32(k);
|
|
keyfound.Mult(&stride);
|
|
keyfound.Add(&key_mpz);
|
|
|
|
publickey = secp->ComputePublicKey(&keyfound);
|
|
secp->GetHash160(P2PKH,true,publickey,(uint8_t*)publickeyhashrmd160);
|
|
if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160,20) != 0){
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
//if(FLAGDEBUG) printf("[D] Key need to be negated\n");
|
|
}
|
|
writevanitykey(true,&keyfound);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH) {
|
|
if(FLAGENDOMORPHISM) {
|
|
for(l = 6;l < 12; l++) {
|
|
if(vanityrmdmatch((uint8_t*)publickeyhashrmd160_endomorphism[l][k])) {
|
|
// Here the given publickeyhashrmd160 match againts one of the vanity targets
|
|
// We need to check which of the cases is it.
|
|
|
|
//rmd160toaddress_dst(publickeyhashrmd160_endomorphism[l][k],address);
|
|
keyfound.SetInt32(k);
|
|
keyfound.Mult(&stride);
|
|
keyfound.Add(&key_mpz);
|
|
|
|
|
|
/*
|
|
if(FLAGDEBUG) {
|
|
|
|
rmd160toaddress_dst(publickeyhashrmd160_endomorphism[l][k],address);
|
|
|
|
hextemp = tohex(publickeyhashrmd160_endomorphism[l][k],20);
|
|
printf("[D] hash found: %s : address %s\n",hextemp,address);
|
|
free(hextemp);
|
|
hextemp = keyfound.GetBase16();
|
|
printf("[D] key: %s\n",hextemp);
|
|
free(hextemp);
|
|
|
|
hextemp = secp->GetPublicKeyHex(true,publickey);
|
|
printf("[D] GetPublicKeyHex: %s\n",hextemp);
|
|
free(hextemp);
|
|
|
|
printf("[D] found something l = %i\n",l);
|
|
|
|
}
|
|
*/
|
|
|
|
switch(l) {
|
|
case 6:
|
|
case 7:
|
|
publickey = secp->ComputePublicKey(&keyfound);
|
|
secp->GetHash160(P2PKH,false,publickey,(uint8_t*)publickeyhashrmd160_uncompress[0]);
|
|
if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160_uncompress[0],20) != 0){
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
break;
|
|
case 8:
|
|
case 9:
|
|
keyfound.ModMulK1order(&lambda);
|
|
publickey = secp->ComputePublicKey(&keyfound);
|
|
secp->GetHash160(P2PKH,false,publickey,(uint8_t*)publickeyhashrmd160_uncompress[0]);
|
|
if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160_uncompress[0],20) != 0){
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
break;
|
|
case 10:
|
|
case 11:
|
|
keyfound.ModMulK1order(&lambda2);
|
|
publickey = secp->ComputePublicKey(&keyfound);
|
|
secp->GetHash160(P2PKH,false,publickey,(uint8_t*)publickeyhashrmd160_uncompress[0]);
|
|
if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160_uncompress[0],20) != 0){
|
|
keyfound.Neg();
|
|
keyfound.Add(&secp->order);
|
|
}
|
|
break;
|
|
}
|
|
writevanitykey(false,&keyfound);
|
|
}
|
|
}
|
|
|
|
}
|
|
else {
|
|
if(vanityrmdmatch((uint8_t*)publickeyhashrmd160_uncompress[k])) {
|
|
keyfound.SetInt32(k);
|
|
keyfound.Mult(&stride);
|
|
keyfound.Add(&key_mpz);
|
|
writevanitykey(false,&keyfound);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
count+=4;
|
|
temp_stride.SetInt32(4);
|
|
temp_stride.Mult(&stride);
|
|
key_mpz.Add(&temp_stride);
|
|
}
|
|
steps[thread_number]++;
|
|
|
|
// Next start point (startP + GRP_SIZE*G)
|
|
pp = startP;
|
|
dy.ModSub(&_2Gn.y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i + 1]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&_2Gn.x);
|
|
|
|
//The Y value for the next start point always need to be calculated
|
|
pp.y.ModSub(&_2Gn.x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&_2Gn.y);
|
|
startP = pp;
|
|
}while(count < N_SEQUENTIAL_MAX && continue_flag);
|
|
}
|
|
} while(continue_flag);
|
|
ends[thread_number] = 1;
|
|
return NULL;
|
|
}
|
|
|
|
void _swap(struct address_value *a,struct address_value *b) {
|
|
struct address_value t;
|
|
t = *a;
|
|
*a = *b;
|
|
*b = t;
|
|
}
|
|
|
|
void _sort(struct address_value *arr,int64_t n) {
|
|
uint32_t depthLimit = ((uint32_t) ceil(log(n))) * 2;
|
|
_introsort(arr,depthLimit,n);
|
|
}
|
|
|
|
void _introsort(struct address_value *arr,uint32_t depthLimit, int64_t n) {
|
|
int64_t p;
|
|
if(n > 1) {
|
|
if(n <= 16) {
|
|
_insertionsort(arr,n);
|
|
}
|
|
else {
|
|
if(depthLimit == 0) {
|
|
_myheapsort(arr,n);
|
|
}
|
|
else {
|
|
p = _partition(arr,n);
|
|
if(p > 0) _introsort(arr , depthLimit-1 , p);
|
|
if(p < n) _introsort(&arr[p+1],depthLimit-1,n-(p+1));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void _insertionsort(struct address_value *arr, int64_t n) {
|
|
int64_t j;
|
|
int64_t i;
|
|
struct address_value key;
|
|
for(i = 1; i < n ; i++ ) {
|
|
key = arr[i];
|
|
j= i-1;
|
|
while(j >= 0 && memcmp(arr[j].value,key.value,20) > 0) {
|
|
arr[j+1] = arr[j];
|
|
j--;
|
|
}
|
|
arr[j+1] = key;
|
|
}
|
|
}
|
|
|
|
int64_t _partition(struct address_value *arr, int64_t n) {
|
|
struct address_value pivot;
|
|
int64_t r,left,right;
|
|
r = n/2;
|
|
pivot = arr[r];
|
|
left = 0;
|
|
right = n-1;
|
|
do {
|
|
while(left < right && memcmp(arr[left].value,pivot.value,20) <= 0 ) {
|
|
left++;
|
|
}
|
|
while(right >= left && memcmp(arr[right].value,pivot.value,20) > 0) {
|
|
right--;
|
|
}
|
|
if(left < right) {
|
|
if(left == r || right == r) {
|
|
if(left == r) {
|
|
r = right;
|
|
}
|
|
if(right == r) {
|
|
r = left;
|
|
}
|
|
}
|
|
_swap(&arr[right],&arr[left]);
|
|
}
|
|
}while(left < right);
|
|
if(right != r) {
|
|
_swap(&arr[right],&arr[r]);
|
|
}
|
|
return right;
|
|
}
|
|
|
|
void _heapify(struct address_value *arr, int64_t n, int64_t i) {
|
|
int64_t largest = i;
|
|
int64_t l = 2 * i + 1;
|
|
int64_t r = 2 * i + 2;
|
|
if (l < n && memcmp(arr[l].value,arr[largest].value,20) > 0)
|
|
largest = l;
|
|
if (r < n && memcmp(arr[r].value,arr[largest].value,20) > 0)
|
|
largest = r;
|
|
if (largest != i) {
|
|
_swap(&arr[i],&arr[largest]);
|
|
_heapify(arr, n, largest);
|
|
}
|
|
}
|
|
|
|
void _myheapsort(struct address_value *arr, int64_t n) {
|
|
int64_t i;
|
|
for ( i = (n / 2) - 1; i >= 0; i--) {
|
|
_heapify(arr, n, i);
|
|
}
|
|
for ( i = n - 1; i > 0; i--) {
|
|
_swap(&arr[0] , &arr[i]);
|
|
_heapify(arr, i, 0);
|
|
}
|
|
}
|
|
|
|
/* OK */
|
|
void bsgs_swap(struct bsgs_xvalue *a,struct bsgs_xvalue *b) {
|
|
struct bsgs_xvalue t;
|
|
t = *a;
|
|
*a = *b;
|
|
*b = t;
|
|
}
|
|
|
|
/* OK */
|
|
void bsgs_sort(struct bsgs_xvalue *arr,int64_t n) {
|
|
uint32_t depthLimit = ((uint32_t) ceil(log(n))) * 2;
|
|
bsgs_introsort(arr,depthLimit,n);
|
|
}
|
|
|
|
/* OK */
|
|
void bsgs_introsort(struct bsgs_xvalue *arr,uint32_t depthLimit, int64_t n) {
|
|
int64_t p;
|
|
if(n > 1) {
|
|
if(n <= 16) {
|
|
bsgs_insertionsort(arr,n);
|
|
}
|
|
else {
|
|
if(depthLimit == 0) {
|
|
bsgs_myheapsort(arr,n);
|
|
}
|
|
else {
|
|
p = bsgs_partition(arr,n);
|
|
if(p > 0) bsgs_introsort(arr , depthLimit-1 , p);
|
|
if(p < n) bsgs_introsort(&arr[p+1],depthLimit-1,n-(p+1));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* OK */
|
|
void bsgs_insertionsort(struct bsgs_xvalue *arr, int64_t n) {
|
|
int64_t j;
|
|
int64_t i;
|
|
struct bsgs_xvalue key;
|
|
for(i = 1; i < n ; i++ ) {
|
|
key = arr[i];
|
|
j= i-1;
|
|
while(j >= 0 && memcmp(arr[j].value,key.value,BSGS_XVALUE_RAM) > 0) {
|
|
arr[j+1] = arr[j];
|
|
j--;
|
|
}
|
|
arr[j+1] = key;
|
|
}
|
|
}
|
|
|
|
int64_t bsgs_partition(struct bsgs_xvalue *arr, int64_t n) {
|
|
struct bsgs_xvalue pivot;
|
|
int64_t r,left,right;
|
|
r = n/2;
|
|
pivot = arr[r];
|
|
left = 0;
|
|
right = n-1;
|
|
do {
|
|
while(left < right && memcmp(arr[left].value,pivot.value,BSGS_XVALUE_RAM) <= 0 ) {
|
|
left++;
|
|
}
|
|
while(right >= left && memcmp(arr[right].value,pivot.value,BSGS_XVALUE_RAM) > 0) {
|
|
right--;
|
|
}
|
|
if(left < right) {
|
|
if(left == r || right == r) {
|
|
if(left == r) {
|
|
r = right;
|
|
}
|
|
if(right == r) {
|
|
r = left;
|
|
}
|
|
}
|
|
bsgs_swap(&arr[right],&arr[left]);
|
|
}
|
|
}while(left < right);
|
|
if(right != r) {
|
|
bsgs_swap(&arr[right],&arr[r]);
|
|
}
|
|
return right;
|
|
}
|
|
|
|
void bsgs_heapify(struct bsgs_xvalue *arr, int64_t n, int64_t i) {
|
|
int64_t largest = i;
|
|
int64_t l = 2 * i + 1;
|
|
int64_t r = 2 * i + 2;
|
|
if (l < n && memcmp(arr[l].value,arr[largest].value,BSGS_XVALUE_RAM) > 0)
|
|
largest = l;
|
|
if (r < n && memcmp(arr[r].value,arr[largest].value,BSGS_XVALUE_RAM) > 0)
|
|
largest = r;
|
|
if (largest != i) {
|
|
bsgs_swap(&arr[i],&arr[largest]);
|
|
bsgs_heapify(arr, n, largest);
|
|
}
|
|
}
|
|
|
|
void bsgs_myheapsort(struct bsgs_xvalue *arr, int64_t n) {
|
|
int64_t i;
|
|
for ( i = (n / 2) - 1; i >= 0; i--) {
|
|
bsgs_heapify(arr, n, i);
|
|
}
|
|
for ( i = n - 1; i > 0; i--) {
|
|
bsgs_swap(&arr[0] , &arr[i]);
|
|
bsgs_heapify(arr, i, 0);
|
|
}
|
|
}
|
|
|
|
int bsgs_searchbinary(struct bsgs_xvalue *buffer,char *data,int64_t array_length,uint64_t *r_value) {
|
|
int64_t min,max,half,current;
|
|
int r = 0,rcmp;
|
|
min = 0;
|
|
current = 0;
|
|
max = array_length;
|
|
half = array_length;
|
|
while(!r && half >= 1) {
|
|
half = (max - min)/2;
|
|
rcmp = memcmp(data+16,buffer[current+half].value,BSGS_XVALUE_RAM);
|
|
if(rcmp == 0) {
|
|
*r_value = buffer[current+half].index;
|
|
r = 1;
|
|
}
|
|
else {
|
|
if(rcmp < 0) {
|
|
max = (max-half);
|
|
}
|
|
else {
|
|
min = (min+half);
|
|
}
|
|
current = min;
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
DWORD WINAPI thread_process_bsgs(LPVOID vargp) {
|
|
#else
|
|
void *thread_process_bsgs(void *vargp) {
|
|
#endif
|
|
|
|
FILE *filekey;
|
|
struct tothread *tt;
|
|
char xpoint_raw[32],*aux_c,*hextemp;
|
|
Int base_key,keyfound;
|
|
Point base_point,point_aux,point_found;
|
|
uint32_t j,k,l,r,salir,thread_number, cycles;
|
|
IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1);
|
|
Point startP;
|
|
|
|
int i,hLength = (CPU_GRP_SIZE / 2 - 1);
|
|
|
|
Int dx[CPU_GRP_SIZE / 2 + 1];
|
|
Point pts[CPU_GRP_SIZE];
|
|
|
|
Int dy;
|
|
Int dyn;
|
|
Int _s;
|
|
Int _p;
|
|
Int km,intaux;
|
|
Point pp;
|
|
Point pn;
|
|
grp->Set(dx);
|
|
|
|
|
|
tt = (struct tothread *)vargp;
|
|
thread_number = tt->nt;
|
|
free(tt);
|
|
|
|
cycles = bsgs_aux / 1024;
|
|
if(bsgs_aux % 1024 != 0) {
|
|
cycles++;
|
|
}
|
|
|
|
intaux.Set(&BSGS_M_double);
|
|
intaux.Mult(CPU_GRP_SIZE/2);
|
|
intaux.Add(&BSGS_M);
|
|
|
|
do {
|
|
|
|
/*
|
|
We do this in an atomic pthread_mutex operation to not affect others threads
|
|
so BSGS_CURRENT is never the same between threads
|
|
*/
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(bsgs_thread, INFINITE);
|
|
#else
|
|
pthread_mutex_lock(&bsgs_thread);
|
|
#endif
|
|
|
|
base_key.Set(&BSGS_CURRENT); /* we need to set our base_key to the current BSGS_CURRENT value*/
|
|
BSGS_CURRENT.Add(&BSGS_N_double); /*Then add 2*BSGS_N to BSGS_CURRENT*/
|
|
/*
|
|
BSGS_CURRENT.Add(&BSGS_N); //Then add BSGS_N to BSGS_CURRENT
|
|
BSGS_CURRENT.Add(&BSGS_N); //Then add BSGS_N to BSGS_CURRENT
|
|
*/
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
ReleaseMutex(bsgs_thread);
|
|
#else
|
|
pthread_mutex_unlock(&bsgs_thread);
|
|
#endif
|
|
|
|
if(base_key.IsGreaterOrEqual(&n_range_end))
|
|
break;
|
|
|
|
|
|
if(FLAGMATRIX) {
|
|
aux_c = base_key.GetBase16();
|
|
printf("[+] Thread 0x%s \n",aux_c);
|
|
fflush(stdout);
|
|
free(aux_c);
|
|
}
|
|
else {
|
|
if(FLAGQUIET == 0){
|
|
aux_c = base_key.GetBase16();
|
|
printf("\r[+] Thread 0x%s \r",aux_c);
|
|
fflush(stdout);
|
|
free(aux_c);
|
|
THREADOUTPUT = 1;
|
|
}
|
|
}
|
|
|
|
base_point = secp->ComputePublicKey(&base_key);
|
|
|
|
km.Set(&base_key);
|
|
km.Neg();
|
|
|
|
km.Add(&secp->order);
|
|
km.Sub(&intaux);
|
|
point_aux = secp->ComputePublicKey(&km);
|
|
|
|
for(k = 0; k < bsgs_point_number ; k++) {
|
|
if(bsgs_found[k] == 0) {
|
|
startP = secp->AddDirect(OriginalPointsBSGS[k],point_aux);
|
|
j = 0;
|
|
while( j < cycles && bsgs_found[k]== 0 ) {
|
|
|
|
for(i = 0; i < hLength; i++) {
|
|
dx[i].ModSub(&GSn[i].x,&startP.x);
|
|
}
|
|
dx[i].ModSub(&GSn[i].x,&startP.x); // For the first point
|
|
dx[i+1].ModSub(&_2GSn.x,&startP.x); // For the next center point
|
|
|
|
// Grouped ModInv
|
|
grp->ModInv();
|
|
|
|
/*
|
|
We use the fact that P + i*G and P - i*G has the same deltax, so the same inverse
|
|
We compute key in the positive and negative way from the center of the group
|
|
*/
|
|
|
|
// center point
|
|
pts[CPU_GRP_SIZE / 2] = startP;
|
|
|
|
for(i = 0; i<hLength; i++) {
|
|
|
|
pp = startP;
|
|
pn = startP;
|
|
|
|
// P = startP + i*G
|
|
dy.ModSub(&GSn[i].y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&GSn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
#if 0
|
|
pp.y.ModSub(&GSn[i].x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&GSn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
#endif
|
|
|
|
// P = startP - i*G , if (x,y) = i*G then (x,-y) = -i*G
|
|
dyn.Set(&GSn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&GSn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
#if 0
|
|
pn.y.ModSub(&GSn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&GSn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
#endif
|
|
|
|
|
|
pts[CPU_GRP_SIZE / 2 + (i + 1)] = pp;
|
|
pts[CPU_GRP_SIZE / 2 - (i + 1)] = pn;
|
|
|
|
}
|
|
|
|
// First point (startP - (GRP_SZIE/2)*G)
|
|
pn = startP;
|
|
dyn.Set(&GSn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&GSn[i].x);
|
|
|
|
#if 0
|
|
pn.y.ModSub(&GSn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&GSn[i].y);
|
|
#endif
|
|
|
|
pts[0] = pn;
|
|
|
|
for(int i = 0; i<CPU_GRP_SIZE && bsgs_found[k]== 0; i++) {
|
|
pts[i].x.Get32Bytes((unsigned char*)xpoint_raw);
|
|
r = bloom_check(&bloom_bP[((unsigned char)xpoint_raw[0])],xpoint_raw,32);
|
|
if(r) {
|
|
if(FLAGDEBUG) {
|
|
hextemp = tohex(xpoint_raw,32);
|
|
aux_c = base_key.GetBase16();
|
|
printf("[D] %s pass the bloom filter check %4i %i, base %s\n",hextemp,i,j,aux_c);
|
|
free(hextemp);
|
|
free(aux_c);
|
|
}
|
|
r = bsgs_secondcheck(&base_key,((j*1024) + i),k,&keyfound);
|
|
if(r) {
|
|
hextemp = keyfound.GetBase16();
|
|
printf("[+] Thread Key found privkey %s \n",hextemp);
|
|
point_found = secp->ComputePublicKey(&keyfound);
|
|
aux_c = secp->GetPublicKeyHex(OriginalPointsBSGScompressed[k],point_found);
|
|
printf("[+] Publickey %s\n",aux_c);
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(write_keys, INFINITE);
|
|
#else
|
|
pthread_mutex_lock(&write_keys);
|
|
#endif
|
|
|
|
filekey = fopen("KEYFOUNDKEYFOUND.txt","a");
|
|
if(filekey != NULL) {
|
|
fprintf(filekey,"Key found privkey %s\nPublickey %s\n",hextemp,aux_c);
|
|
fclose(filekey);
|
|
}
|
|
free(hextemp);
|
|
free(aux_c);
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
ReleaseMutex(write_keys);
|
|
#else
|
|
pthread_mutex_unlock(&write_keys);
|
|
#endif
|
|
bsgs_found[k] = 1;
|
|
salir = 1;
|
|
for(l = 0; l < bsgs_point_number && salir; l++) {
|
|
salir &= bsgs_found[l];
|
|
}
|
|
if(salir) {
|
|
printf("All points were found\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
} //End if second check
|
|
}//End if first check
|
|
|
|
}// For for pts variable
|
|
|
|
// Next start point (startP += (bsSize*GRP_SIZE).G)
|
|
|
|
pp = startP;
|
|
dy.ModSub(&_2GSn.y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i + 1]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&_2GSn.x);
|
|
|
|
pp.y.ModSub(&_2GSn.x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&_2GSn.y);
|
|
startP = pp;
|
|
|
|
j++;
|
|
} //while all the aMP points
|
|
}// End if
|
|
}
|
|
steps[thread_number]+=2;
|
|
}while(1);
|
|
ends[thread_number] = 1;
|
|
return NULL;
|
|
}
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
DWORD WINAPI thread_process_bsgs_random(LPVOID vargp) {
|
|
#else
|
|
void *thread_process_bsgs_random(void *vargp) {
|
|
#endif
|
|
|
|
FILE *filekey;
|
|
struct tothread *tt;
|
|
char xpoint_raw[32],*aux_c,*hextemp;
|
|
Int base_key,keyfound,n_range_random;
|
|
Point base_point,point_aux,point_found;
|
|
uint32_t k,l,r,salir,thread_number,cycles;
|
|
|
|
IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1);
|
|
Point startP;
|
|
|
|
int hLength = (CPU_GRP_SIZE / 2 - 1);
|
|
|
|
Int dx[CPU_GRP_SIZE / 2 + 1];
|
|
Point pts[CPU_GRP_SIZE];
|
|
|
|
Int dy;
|
|
Int dyn;
|
|
Int _s;
|
|
Int _p;
|
|
Int km,intaux;
|
|
Point pp;
|
|
Point pn;
|
|
grp->Set(dx);
|
|
|
|
|
|
tt = (struct tothread *)vargp;
|
|
thread_number = tt->nt;
|
|
free(tt);
|
|
|
|
cycles = bsgs_aux / 1024;
|
|
if(bsgs_aux % 1024 != 0) {
|
|
cycles++;
|
|
}
|
|
|
|
intaux.Set(&BSGS_M_double);
|
|
intaux.Mult(CPU_GRP_SIZE/2);
|
|
intaux.Add(&BSGS_M);
|
|
|
|
/*
|
|
while base_key is less than n_range_end then:
|
|
*/
|
|
do {
|
|
|
|
|
|
/* | Start Range | End Range |
|
|
None | 1 | EC.N |
|
|
-b bit | Min bit value | Max bit value |
|
|
-r A:B | A | B |
|
|
*/
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(bsgs_thread, INFINITE);
|
|
#else
|
|
pthread_mutex_lock(&bsgs_thread);
|
|
#endif
|
|
|
|
base_key.Rand(&n_range_start,&n_range_end);
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
ReleaseMutex(bsgs_thread);
|
|
#else
|
|
pthread_mutex_unlock(&bsgs_thread);
|
|
#endif
|
|
|
|
if(FLAGMATRIX) {
|
|
aux_c = base_key.GetBase16();
|
|
printf("[+] Thread 0x%s \n",aux_c);
|
|
fflush(stdout);
|
|
free(aux_c);
|
|
}
|
|
else{
|
|
if(FLAGQUIET == 0){
|
|
aux_c = base_key.GetBase16();
|
|
printf("\r[+] Thread 0x%s \r",aux_c);
|
|
fflush(stdout);
|
|
free(aux_c);
|
|
THREADOUTPUT = 1;
|
|
}
|
|
}
|
|
base_point = secp->ComputePublicKey(&base_key);
|
|
|
|
km.Set(&base_key);
|
|
km.Neg();
|
|
|
|
|
|
km.Add(&secp->order);
|
|
km.Sub(&intaux);
|
|
point_aux = secp->ComputePublicKey(&km);
|
|
|
|
|
|
/* We need to test individually every point in BSGS_Q */
|
|
for(k = 0; k < bsgs_point_number ; k++) {
|
|
if(bsgs_found[k] == 0) {
|
|
startP = secp->AddDirect(OriginalPointsBSGS[k],point_aux);
|
|
uint32_t j = 0;
|
|
while( j < cycles && bsgs_found[k]== 0 ) {
|
|
|
|
int i;
|
|
for(i = 0; i < hLength; i++) {
|
|
dx[i].ModSub(&GSn[i].x,&startP.x);
|
|
}
|
|
dx[i].ModSub(&GSn[i].x,&startP.x); // For the first point
|
|
dx[i+1].ModSub(&_2GSn.x,&startP.x); // For the next center point
|
|
|
|
// Grouped ModInv
|
|
grp->ModInv();
|
|
|
|
/*
|
|
We use the fact that P + i*G and P - i*G has the same deltax, so the same inverse
|
|
We compute key in the positive and negative way from the center of the group
|
|
*/
|
|
|
|
// center point
|
|
pts[CPU_GRP_SIZE / 2] = startP;
|
|
|
|
for(i = 0; i<hLength; i++) {
|
|
|
|
pp = startP;
|
|
pn = startP;
|
|
|
|
// P = startP + i*G
|
|
dy.ModSub(&GSn[i].y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&GSn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
#if 0
|
|
pp.y.ModSub(&GSn[i].x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&GSn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
#endif
|
|
|
|
// P = startP - i*G , if (x,y) = i*G then (x,-y) = -i*G
|
|
dyn.Set(&GSn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&GSn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
#if 0
|
|
pn.y.ModSub(&GSn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&GSn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
#endif
|
|
|
|
|
|
pts[CPU_GRP_SIZE / 2 + (i + 1)] = pp;
|
|
pts[CPU_GRP_SIZE / 2 - (i + 1)] = pn;
|
|
|
|
}
|
|
|
|
// First point (startP - (GRP_SZIE/2)*G)
|
|
pn = startP;
|
|
dyn.Set(&GSn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&GSn[i].x);
|
|
|
|
#if 0
|
|
pn.y.ModSub(&GSn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&GSn[i].y);
|
|
#endif
|
|
|
|
pts[0] = pn;
|
|
|
|
for(int i = 0; i<CPU_GRP_SIZE && bsgs_found[k]== 0; i++) {
|
|
pts[i].x.Get32Bytes((unsigned char*)xpoint_raw);
|
|
r = bloom_check(&bloom_bP[((unsigned char)xpoint_raw[0])],xpoint_raw,32);
|
|
if(r) {
|
|
r = bsgs_secondcheck(&base_key,((j*1024) + i),k,&keyfound);
|
|
if(r) {
|
|
hextemp = keyfound.GetBase16();
|
|
printf("[+] Thread Key found privkey %s \n",hextemp);
|
|
point_found = secp->ComputePublicKey(&keyfound);
|
|
aux_c = secp->GetPublicKeyHex(OriginalPointsBSGScompressed[k],point_found);
|
|
printf("[+] Publickey %s\n",aux_c);
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(write_keys, INFINITE);
|
|
#else
|
|
pthread_mutex_lock(&write_keys);
|
|
#endif
|
|
|
|
filekey = fopen("KEYFOUNDKEYFOUND.txt","a");
|
|
if(filekey != NULL) {
|
|
fprintf(filekey,"Key found privkey %s\nPublickey %s\n",hextemp,aux_c);
|
|
fclose(filekey);
|
|
}
|
|
free(hextemp);
|
|
free(aux_c);
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
ReleaseMutex(write_keys);
|
|
#else
|
|
pthread_mutex_unlock(&write_keys);
|
|
#endif
|
|
|
|
bsgs_found[k] = 1;
|
|
salir = 1;
|
|
for(l = 0; l < bsgs_point_number && salir; l++) {
|
|
salir &= bsgs_found[l];
|
|
}
|
|
if(salir) {
|
|
printf("All points were found\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
} //End if second check
|
|
}//End if first check
|
|
|
|
}// For for pts variable
|
|
|
|
// Next start point (startP += (bsSize*GRP_SIZE).G)
|
|
|
|
pp = startP;
|
|
dy.ModSub(&_2GSn.y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i + 1]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&_2GSn.x);
|
|
|
|
pp.y.ModSub(&_2GSn.x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&_2GSn.y);
|
|
startP = pp;
|
|
|
|
j++;
|
|
|
|
} //End While
|
|
|
|
} //End if
|
|
} // End for with k bsgs_point_number
|
|
|
|
steps[thread_number]+=2;
|
|
}while(1);
|
|
ends[thread_number] = 1;
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
The bsgs_secondcheck function is made to perform a second BSGS search in a Range of less size.
|
|
This funtion is made with the especific purpouse to USE a smaller bPtable in RAM.
|
|
*/
|
|
int bsgs_secondcheck(Int *start_range,uint32_t a,uint32_t k_index,Int *privatekey) {
|
|
int i = 0,found = 0,r = 0;
|
|
Int base_key;
|
|
Point base_point,point_aux;
|
|
Point BSGS_Q, BSGS_S,BSGS_Q_AMP;
|
|
char xpoint_raw[32];
|
|
|
|
|
|
base_key.Set(&BSGS_M_double);
|
|
base_key.Mult((uint64_t) a);
|
|
base_key.Add(start_range);
|
|
|
|
base_point = secp->ComputePublicKey(&base_key);
|
|
point_aux = secp->Negation(base_point);
|
|
|
|
/*
|
|
BSGS_S = Q - base_key
|
|
Q is the target Key
|
|
base_key is the Start range + a*BSGS_M
|
|
*/
|
|
BSGS_S = secp->AddDirect(OriginalPointsBSGS[k_index],point_aux);
|
|
BSGS_Q.Set(BSGS_S);
|
|
do {
|
|
BSGS_Q_AMP = secp->AddDirect(BSGS_Q,BSGS_AMP2[i]);
|
|
BSGS_S.Set(BSGS_Q_AMP);
|
|
BSGS_S.x.Get32Bytes((unsigned char *) xpoint_raw);
|
|
r = bloom_check(&bloom_bPx2nd[(uint8_t) xpoint_raw[0]],xpoint_raw,32);
|
|
if(r) {
|
|
found = bsgs_thirdcheck(&base_key,i,k_index,privatekey);
|
|
}
|
|
i++;
|
|
}while(i < 32 && !found);
|
|
return found;
|
|
}
|
|
|
|
int bsgs_thirdcheck(Int *start_range,uint32_t a,uint32_t k_index,Int *privatekey) {
|
|
uint64_t j = 0;
|
|
int i = 0,found = 0,r = 0;
|
|
Int base_key,calculatedkey;
|
|
Point base_point,point_aux;
|
|
Point BSGS_Q, BSGS_S,BSGS_Q_AMP;
|
|
char xpoint_raw[32];
|
|
|
|
base_key.SetInt32(a);
|
|
base_key.Mult(&BSGS_M2_double);
|
|
base_key.Add(start_range);
|
|
|
|
base_point = secp->ComputePublicKey(&base_key);
|
|
point_aux = secp->Negation(base_point);
|
|
|
|
BSGS_S = secp->AddDirect(OriginalPointsBSGS[k_index],point_aux);
|
|
BSGS_Q.Set(BSGS_S);
|
|
|
|
do {
|
|
BSGS_Q_AMP = secp->AddDirect(BSGS_Q,BSGS_AMP3[i]);
|
|
BSGS_S.Set(BSGS_Q_AMP);
|
|
BSGS_S.x.Get32Bytes((unsigned char *)xpoint_raw);
|
|
r = bloom_check(&bloom_bPx3rd[(uint8_t)xpoint_raw[0]],xpoint_raw,32);
|
|
if(r) {
|
|
r = bsgs_searchbinary(bPtable,xpoint_raw,bsgs_m3,&j);
|
|
if(r) {
|
|
calcualteindex(i,&calculatedkey);
|
|
privatekey->Set(&calculatedkey);
|
|
privatekey->Add((uint64_t)(j+1));
|
|
privatekey->Add(&base_key);
|
|
point_aux = secp->ComputePublicKey(privatekey);
|
|
if(point_aux.x.IsEqual(&OriginalPointsBSGS[k_index].x)) {
|
|
found = 1;
|
|
}
|
|
else {
|
|
calcualteindex(i,&calculatedkey);
|
|
privatekey->Set(&calculatedkey);
|
|
privatekey->Sub((uint64_t)(j+1));
|
|
privatekey->Add(&base_key);
|
|
point_aux = secp->ComputePublicKey(privatekey);
|
|
if(point_aux.x.IsEqual(&OriginalPointsBSGS[k_index].x)) {
|
|
found = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
/*
|
|
For some reason the AddDirect don't return 000000... value when the publickeys are the negated values from each other
|
|
Why JLP?
|
|
This is is an special case
|
|
*/
|
|
if(BSGS_Q.x.IsEqual(&BSGS_AMP3[i].x)) {
|
|
calcualteindex(i,&calculatedkey);
|
|
privatekey->Set(&calculatedkey);
|
|
privatekey->Add(&base_key);
|
|
found = 1;
|
|
}
|
|
}
|
|
i++;
|
|
}while(i < 32 && !found);
|
|
return found;
|
|
}
|
|
|
|
|
|
void sleep_ms(int milliseconds) { // cross-platform sleep function
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
Sleep(milliseconds);
|
|
#elif _POSIX_C_SOURCE >= 199309L
|
|
struct timespec ts;
|
|
ts.tv_sec = milliseconds / 1000;
|
|
ts.tv_nsec = (milliseconds % 1000) * 1000000;
|
|
nanosleep(&ts, NULL);
|
|
#else
|
|
if (milliseconds >= 1000)
|
|
sleep(milliseconds / 1000);
|
|
usleep((milliseconds % 1000) * 1000);
|
|
#endif
|
|
}
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
DWORD WINAPI thread_pub2rmd(LPVOID vargp) {
|
|
#else
|
|
void *thread_pub2rmd(void *vargp) {
|
|
#endif
|
|
FILE *fd;
|
|
Int key_mpz;
|
|
struct tothread *tt;
|
|
uint64_t i,limit;
|
|
char digest160[20];
|
|
char digest256[32];
|
|
char *temphex;
|
|
int thread_number,r;
|
|
int pub2rmd_continue = 1;
|
|
struct publickey pub;
|
|
limit = 0xFFFFFFFF;
|
|
tt = (struct tothread *)vargp;
|
|
thread_number = tt->nt;
|
|
do {
|
|
if(FLAGRANDOM){
|
|
key_mpz.Rand(&n_range_start,&n_range_diff);
|
|
}
|
|
else {
|
|
if(n_range_start.IsLower(&n_range_end)) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(write_random, INFINITE);
|
|
key_mpz.Set(&n_range_start);
|
|
n_range_start.Add(N_SEQUENTIAL_MAX);
|
|
ReleaseMutex(write_random);
|
|
#else
|
|
pthread_mutex_lock(&write_random);
|
|
key_mpz.Set(&n_range_start);
|
|
n_range_start.Add(N_SEQUENTIAL_MAX);
|
|
pthread_mutex_lock(&write_random);
|
|
#endif
|
|
}
|
|
else {
|
|
pub2rmd_continue = 0;
|
|
}
|
|
}
|
|
if(pub2rmd_continue) {
|
|
key_mpz.Get32Bytes(pub.X.data8);
|
|
pub.parity = 0x02;
|
|
pub.X.data32[7] = 0;
|
|
if(FLAGMATRIX) {
|
|
temphex = tohex((char*)&pub,33);
|
|
printf("[+] Thread 0x%s \n",temphex);
|
|
free(temphex);
|
|
fflush(stdout);
|
|
}
|
|
else {
|
|
if(FLAGQUIET == 0) {
|
|
temphex = tohex((char*)&pub,33);
|
|
printf("\r[+] Thread %s \r",temphex);
|
|
free(temphex);
|
|
fflush(stdout);
|
|
THREADOUTPUT = 1;
|
|
}
|
|
}
|
|
for(i = 0 ; i < limit ; i++) {
|
|
pub.parity = 0x02;
|
|
sha256((uint8_t*)&pub, 33, (uint8_t*)digest256);
|
|
rmd160((const unsigned char*)digest256,32,(unsigned char*) digest160);
|
|
r = bloom_check(&bloom,digest160,MAXLENGTHADDRESS);
|
|
if(r) {
|
|
r = searchbinary(addressTable,digest160,N);
|
|
if(r) {
|
|
temphex = tohex((char*)&pub,33);
|
|
printf("\nHit: Publickey found %s\n",temphex);
|
|
fd = fopen("KEYFOUNDKEYFOUND.txt","a+");
|
|
if(fd != NULL) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(write_keys, INFINITE);
|
|
fprintf(fd,"Publickey found %s\n",temphex);
|
|
fclose(fd);
|
|
ReleaseMutex(write_keys);
|
|
#else
|
|
pthread_mutex_lock(&write_keys);
|
|
fprintf(fd,"Publickey found %s\n",temphex);
|
|
fclose(fd);
|
|
pthread_mutex_unlock(&write_keys);
|
|
#endif
|
|
}
|
|
else {
|
|
fprintf(stderr,"\nPublickey found %s\nbut the file can't be open\n",temphex);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
free(temphex);
|
|
}
|
|
}
|
|
pub.parity = 0x03;
|
|
sha256((uint8_t*)&pub, 33,(uint8_t*) digest256);
|
|
rmd160((const unsigned char*)digest256,32,(unsigned char*) digest160);
|
|
r = bloom_check(&bloom,digest160,MAXLENGTHADDRESS);
|
|
if(r) {
|
|
r = searchbinary(addressTable,digest160,N);
|
|
if(r) {
|
|
temphex = tohex((char*)&pub,33);
|
|
printf("\nHit: Publickey found %s\n",temphex);
|
|
fd = fopen("KEYFOUNDKEYFOUND.txt","a+");
|
|
if(fd != NULL) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(write_keys, INFINITE);
|
|
fprintf(fd,"Publickey found %s\n",temphex);
|
|
fclose(fd);
|
|
ReleaseMutex(write_keys);
|
|
|
|
#else
|
|
pthread_mutex_lock(&write_keys);
|
|
fprintf(fd,"Publickey found %s\n",temphex);
|
|
fclose(fd);
|
|
pthread_mutex_unlock(&write_keys);
|
|
#endif
|
|
}
|
|
else {
|
|
fprintf(stderr,"\nPublickey found %s\nbut the file can't be open\n",temphex);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
free(temphex);
|
|
}
|
|
}
|
|
pub.X.data32[7]++;
|
|
if(pub.X.data32[7] % DEBUGCOUNT == 0) {
|
|
steps[thread_number]++;
|
|
}
|
|
}
|
|
}
|
|
}while(pub2rmd_continue);
|
|
ends[thread_number] = 1;
|
|
return NULL;
|
|
}
|
|
|
|
void init_generator() {
|
|
Point G = secp->ComputePublicKey(&stride);
|
|
Point g;
|
|
Gn.resize(CPU_GRP_SIZE / 2,g);
|
|
g.Set(G);
|
|
Gn[0] = g;
|
|
g = secp->DoubleDirect(g);
|
|
Gn[1] = g;
|
|
for(int i = 2; i < CPU_GRP_SIZE / 2; i++) {
|
|
g = secp->AddDirect(g,G);
|
|
Gn[i] = g;
|
|
}
|
|
_2Gn = secp->DoubleDirect(Gn[CPU_GRP_SIZE / 2 - 1]);
|
|
}
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
DWORD WINAPI thread_bPload(LPVOID vargp) {
|
|
#else
|
|
void *thread_bPload(void *vargp) {
|
|
#endif
|
|
|
|
char rawvalue[32];
|
|
struct bPload *tt;
|
|
uint64_t i_counter,j,nbStep,to;
|
|
|
|
IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1);
|
|
Point startP;
|
|
Int dx[CPU_GRP_SIZE / 2 + 1];
|
|
Point pts[CPU_GRP_SIZE];
|
|
Int dy,dyn,_s,_p;
|
|
Point pp,pn;
|
|
|
|
int i,bloom_bP_index,hLength = (CPU_GRP_SIZE / 2 - 1) ,threadid;
|
|
tt = (struct bPload *)vargp;
|
|
Int km((uint64_t)(tt->from + 1));
|
|
threadid = tt->threadid;
|
|
//if(FLAGDEBUG) printf("[D] thread %i from %" PRIu64 " to %" PRIu64 "\n",threadid,tt->from,tt->to);
|
|
|
|
i_counter = tt->from;
|
|
|
|
nbStep = (tt->to - tt->from) / CPU_GRP_SIZE;
|
|
|
|
if( ((tt->to - tt->from) % CPU_GRP_SIZE ) != 0) {
|
|
nbStep++;
|
|
}
|
|
//if(FLAGDEBUG) printf("[D] thread %i nbStep %" PRIu64 "\n",threadid,nbStep);
|
|
to = tt->to;
|
|
|
|
km.Add((uint64_t)(CPU_GRP_SIZE / 2));
|
|
startP = secp->ComputePublicKey(&km);
|
|
grp->Set(dx);
|
|
for(uint64_t s=0;s<nbStep;s++) {
|
|
for(i = 0; i < hLength; i++) {
|
|
dx[i].ModSub(&Gn[i].x,&startP.x);
|
|
}
|
|
dx[i].ModSub(&Gn[i].x,&startP.x); // For the first point
|
|
dx[i + 1].ModSub(&_2Gn.x,&startP.x);// For the next center point
|
|
// Grouped ModInv
|
|
grp->ModInv();
|
|
|
|
// We use the fact that P + i*G and P - i*G has the same deltax, so the same inverse
|
|
// We compute key in the positive and negative way from the center of the group
|
|
// center point
|
|
|
|
pts[CPU_GRP_SIZE / 2] = startP; //Center point
|
|
|
|
for(i = 0; i<hLength; i++) {
|
|
pp = startP;
|
|
pn = startP;
|
|
|
|
// P = startP + i*G
|
|
dy.ModSub(&Gn[i].y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&Gn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
#if 0
|
|
pp.y.ModSub(&Gn[i].x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&Gn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
#endif
|
|
|
|
// P = startP - i*G , if (x,y) = i*G then (x,-y) = -i*G
|
|
dyn.Set(&Gn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&Gn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
#if 0
|
|
pn.y.ModSub(&Gn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&Gn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
#endif
|
|
|
|
pts[CPU_GRP_SIZE / 2 + (i + 1)] = pp;
|
|
pts[CPU_GRP_SIZE / 2 - (i + 1)] = pn;
|
|
}
|
|
|
|
// First point (startP - (GRP_SZIE/2)*G)
|
|
pn = startP;
|
|
dyn.Set(&Gn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&Gn[i].x);
|
|
|
|
#if 0
|
|
pn.y.ModSub(&Gn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&Gn[i].y);
|
|
#endif
|
|
|
|
pts[0] = pn;
|
|
for(j=0;j<CPU_GRP_SIZE;j++) {
|
|
pts[j].x.Get32Bytes((unsigned char*)rawvalue);
|
|
bloom_bP_index = (uint8_t)rawvalue[0];
|
|
if(i_counter < bsgs_m3) {
|
|
if(!FLAGREADEDFILE3) {
|
|
memcpy(bPtable[i_counter].value,rawvalue+16,BSGS_XVALUE_RAM);
|
|
bPtable[i_counter].index = i_counter;
|
|
}
|
|
if(!FLAGREADEDFILE4) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(bloom_bPx3rd_mutex[bloom_bP_index], INFINITE);
|
|
bloom_add(&bloom_bPx3rd[bloom_bP_index], rawvalue, BSGS_BUFFERXPOINTLENGTH);
|
|
ReleaseMutex(bloom_bPx3rd_mutex[bloom_bP_index]);
|
|
#else
|
|
pthread_mutex_lock(&bloom_bPx3rd_mutex[bloom_bP_index]);
|
|
bloom_add(&bloom_bPx3rd[bloom_bP_index], rawvalue, BSGS_BUFFERXPOINTLENGTH);
|
|
pthread_mutex_unlock(&bloom_bPx3rd_mutex[bloom_bP_index]);
|
|
#endif
|
|
}
|
|
}
|
|
if(i_counter < bsgs_m2 && !FLAGREADEDFILE2) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(bloom_bPx2nd_mutex[bloom_bP_index], INFINITE);
|
|
bloom_add(&bloom_bPx2nd[bloom_bP_index], rawvalue, BSGS_BUFFERXPOINTLENGTH);
|
|
ReleaseMutex(bloom_bPx2nd_mutex[bloom_bP_index]);
|
|
#else
|
|
pthread_mutex_lock(&bloom_bPx2nd_mutex[bloom_bP_index]);
|
|
bloom_add(&bloom_bPx2nd[bloom_bP_index], rawvalue, BSGS_BUFFERXPOINTLENGTH);
|
|
pthread_mutex_unlock(&bloom_bPx2nd_mutex[bloom_bP_index]);
|
|
#endif
|
|
}
|
|
if(i_counter < to && !FLAGREADEDFILE1 ) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(bloom_bP_mutex[bloom_bP_index], INFINITE);
|
|
bloom_add(&bloom_bP[bloom_bP_index], rawvalue ,BSGS_BUFFERXPOINTLENGTH);
|
|
ReleaseMutex(bloom_bP_mutex[bloom_bP_index);
|
|
#else
|
|
pthread_mutex_lock(&bloom_bP_mutex[bloom_bP_index]);
|
|
bloom_add(&bloom_bP[bloom_bP_index], rawvalue ,BSGS_BUFFERXPOINTLENGTH);
|
|
pthread_mutex_unlock(&bloom_bP_mutex[bloom_bP_index]);
|
|
#endif
|
|
}
|
|
i_counter++;
|
|
}
|
|
// Next start point (startP + GRP_SIZE*G)
|
|
pp = startP;
|
|
dy.ModSub(&_2Gn.y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i + 1]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&_2Gn.x);
|
|
|
|
pp.y.ModSub(&_2Gn.x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&_2Gn.y);
|
|
startP = pp;
|
|
}
|
|
delete grp;
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(bPload_mutex[threadid], INFINITE);
|
|
tt->finished = 1;
|
|
ReleaseMutex(bPload_mutex[threadid]);
|
|
#else
|
|
pthread_mutex_lock(&bPload_mutex[threadid]);
|
|
tt->finished = 1;
|
|
pthread_mutex_unlock(&bPload_mutex[threadid]);
|
|
pthread_exit(NULL);
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
DWORD WINAPI thread_bPload_2blooms(LPVOID vargp) {
|
|
#else
|
|
void *thread_bPload_2blooms(void *vargp) {
|
|
#endif
|
|
char rawvalue[32];
|
|
struct bPload *tt;
|
|
uint64_t i_counter,j,nbStep; //,to;
|
|
IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1);
|
|
Point startP;
|
|
Int dx[CPU_GRP_SIZE / 2 + 1];
|
|
Point pts[CPU_GRP_SIZE];
|
|
Int dy,dyn,_s,_p;
|
|
Point pp,pn;
|
|
int i,bloom_bP_index,hLength = (CPU_GRP_SIZE / 2 - 1) ,threadid;
|
|
tt = (struct bPload *)vargp;
|
|
Int km((uint64_t)(tt->from +1 ));
|
|
threadid = tt->threadid;
|
|
|
|
i_counter = tt->from;
|
|
|
|
nbStep = (tt->to - (tt->from)) / CPU_GRP_SIZE;
|
|
|
|
if( ((tt->to - (tt->from)) % CPU_GRP_SIZE ) != 0) {
|
|
nbStep++;
|
|
}
|
|
//to = tt->to;
|
|
|
|
km.Add((uint64_t)(CPU_GRP_SIZE / 2));
|
|
startP = secp->ComputePublicKey(&km);
|
|
grp->Set(dx);
|
|
for(uint64_t s=0;s<nbStep;s++) {
|
|
for(i = 0; i < hLength; i++) {
|
|
dx[i].ModSub(&Gn[i].x,&startP.x);
|
|
}
|
|
dx[i].ModSub(&Gn[i].x,&startP.x); // For the first point
|
|
dx[i + 1].ModSub(&_2Gn.x,&startP.x);// For the next center point
|
|
// Grouped ModInv
|
|
grp->ModInv();
|
|
|
|
// We use the fact that P + i*G and P - i*G has the same deltax, so the same inverse
|
|
// We compute key in the positive and negative way from the center of the group
|
|
// center point
|
|
|
|
pts[CPU_GRP_SIZE / 2] = startP; //Center point
|
|
|
|
for(i = 0; i<hLength; i++) {
|
|
pp = startP;
|
|
pn = startP;
|
|
|
|
// P = startP + i*G
|
|
dy.ModSub(&Gn[i].y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&Gn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
#if 0
|
|
pp.y.ModSub(&Gn[i].x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&Gn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
#endif
|
|
|
|
// P = startP - i*G , if (x,y) = i*G then (x,-y) = -i*G
|
|
dyn.Set(&Gn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&Gn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
#if 0
|
|
pn.y.ModSub(&Gn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&Gn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
#endif
|
|
|
|
pts[CPU_GRP_SIZE / 2 + (i + 1)] = pp;
|
|
pts[CPU_GRP_SIZE / 2 - (i + 1)] = pn;
|
|
}
|
|
|
|
// First point (startP - (GRP_SZIE/2)*G)
|
|
pn = startP;
|
|
dyn.Set(&Gn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&Gn[i].x);
|
|
|
|
#if 0
|
|
pn.y.ModSub(&Gn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&Gn[i].y);
|
|
#endif
|
|
|
|
pts[0] = pn;
|
|
for(j=0;j<CPU_GRP_SIZE;j++) {
|
|
pts[j].x.Get32Bytes((unsigned char*)rawvalue);
|
|
bloom_bP_index = (uint8_t)rawvalue[0];
|
|
if(i_counter < bsgs_m3) {
|
|
if(!FLAGREADEDFILE3) {
|
|
memcpy(bPtable[i_counter].value,rawvalue+16,BSGS_XVALUE_RAM);
|
|
bPtable[i_counter].index = i_counter;
|
|
}
|
|
if(!FLAGREADEDFILE4) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(bloom_bPx3rd_mutex[bloom_bP_index], INFINITE);
|
|
bloom_add(&bloom_bPx3rd[bloom_bP_index], rawvalue, BSGS_BUFFERXPOINTLENGTH);
|
|
ReleaseMutex(bloom_bPx3rd_mutex[bloom_bP_index]);
|
|
#else
|
|
pthread_mutex_lock(&bloom_bPx3rd_mutex[bloom_bP_index]);
|
|
bloom_add(&bloom_bPx3rd[bloom_bP_index], rawvalue, BSGS_BUFFERXPOINTLENGTH);
|
|
pthread_mutex_unlock(&bloom_bPx3rd_mutex[bloom_bP_index]);
|
|
#endif
|
|
}
|
|
}
|
|
if(i_counter < bsgs_m2 && !FLAGREADEDFILE2) {
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(bloom_bPx2nd_mutex[bloom_bP_index], INFINITE);
|
|
bloom_add(&bloom_bPx2nd[bloom_bP_index], rawvalue, BSGS_BUFFERXPOINTLENGTH);
|
|
ReleaseMutex(bloom_bPx2nd_mutex[bloom_bP_index]);
|
|
#else
|
|
pthread_mutex_lock(&bloom_bPx2nd_mutex[bloom_bP_index]);
|
|
bloom_add(&bloom_bPx2nd[bloom_bP_index], rawvalue, BSGS_BUFFERXPOINTLENGTH);
|
|
pthread_mutex_unlock(&bloom_bPx2nd_mutex[bloom_bP_index]);
|
|
#endif
|
|
}
|
|
i_counter++;
|
|
}
|
|
// Next start point (startP + GRP_SIZE*G)
|
|
pp = startP;
|
|
dy.ModSub(&_2Gn.y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i + 1]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&_2Gn.x);
|
|
|
|
pp.y.ModSub(&_2Gn.x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&_2Gn.y);
|
|
startP = pp;
|
|
}
|
|
delete grp;
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(bPload_mutex[threadid], INFINITE);
|
|
tt->finished = 1;
|
|
ReleaseMutex(bPload_mutex[threadid]);
|
|
#else
|
|
pthread_mutex_lock(&bPload_mutex[threadid]);
|
|
tt->finished = 1;
|
|
pthread_mutex_unlock(&bPload_mutex[threadid]);
|
|
pthread_exit(NULL);
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
/* This function perform the KECCAK Opetation
|
|
void KECCAK_256(uint8_t *source, size_t size,uint8_t *dst) {
|
|
SHA3_256_CTX ctx;
|
|
SHA3_256_Init(&ctx);
|
|
SHA3_256_Update(&ctx,source,size);
|
|
KECCAK_256_Final(dst,&ctx);
|
|
}
|
|
*/
|
|
|
|
/* This function takes in two parameters:
|
|
|
|
publickey: a reference to a Point object representing a public key.
|
|
dst_address: a pointer to an unsigned char array where the generated binary address will be stored.
|
|
The function is designed to generate a binary address for Ethereum using the given public key.
|
|
It first extracts the x and y coordinates of the public key as 32-byte arrays, and concatenates them
|
|
to form a 64-byte array called bin_publickey. Then, it applies the KECCAK-256 hashing algorithm to
|
|
bin_publickey to generate the binary address, which is stored in dst_address. */
|
|
|
|
void generate_binaddress_eth(Point &publickey,unsigned char *dst_address) {
|
|
unsigned char bin_publickey[64];
|
|
publickey.x.Get32Bytes(bin_publickey);
|
|
publickey.y.Get32Bytes(bin_publickey+32);
|
|
keccak(bin_publickey, 64, bin_publickey);
|
|
memcpy(dst_address,bin_publickey+12,20);
|
|
}
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
DWORD WINAPI thread_process_bsgs_dance(LPVOID vargp) {
|
|
#else
|
|
void *thread_process_bsgs_dance(void *vargp) {
|
|
#endif
|
|
|
|
FILE *filekey;
|
|
struct tothread *tt;
|
|
char xpoint_raw[32],*aux_c,*hextemp;
|
|
Int base_key,keyfound;
|
|
Point base_point,point_aux,point_found;
|
|
uint32_t k,l,r,salir,thread_number,entrar,cycles;
|
|
|
|
IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1);
|
|
Point startP;
|
|
|
|
int hLength = (CPU_GRP_SIZE / 2 - 1);
|
|
|
|
Int dx[CPU_GRP_SIZE / 2 + 1];
|
|
Point pts[CPU_GRP_SIZE];
|
|
|
|
Int dy;
|
|
Int dyn;
|
|
Int _s;
|
|
Int _p;
|
|
Int km,intaux;
|
|
Point pp;
|
|
Point pn;
|
|
grp->Set(dx);
|
|
|
|
|
|
tt = (struct tothread *)vargp;
|
|
thread_number = tt->nt;
|
|
free(tt);
|
|
|
|
cycles = bsgs_aux / 1024;
|
|
if(bsgs_aux % 1024 != 0) {
|
|
cycles++;
|
|
}
|
|
|
|
intaux.Set(&BSGS_M_double);
|
|
intaux.Mult(CPU_GRP_SIZE/2);
|
|
intaux.Add(&BSGS_M);
|
|
|
|
entrar = 1;
|
|
|
|
/*
|
|
while base_key is less than n_range_end then:
|
|
*/
|
|
do {
|
|
r = rand() % 3;
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(bsgs_thread, INFINITE);
|
|
#else
|
|
pthread_mutex_lock(&bsgs_thread);
|
|
#endif
|
|
switch(r) {
|
|
case 0: //TOP
|
|
if(n_range_end.IsGreater(&BSGS_CURRENT)) {
|
|
/*
|
|
n_range_end.Sub(&BSGS_N);
|
|
n_range_end.Sub(&BSGS_N);
|
|
*/
|
|
n_range_end.Sub(&BSGS_N_double);
|
|
if(n_range_end.IsLower(&BSGS_CURRENT)) {
|
|
base_key.Set(&BSGS_CURRENT);
|
|
}
|
|
else {
|
|
base_key.Set(&n_range_end);
|
|
}
|
|
}
|
|
else {
|
|
entrar = 0;
|
|
}
|
|
break;
|
|
case 1: //BOTTOM
|
|
if(BSGS_CURRENT.IsLower(&n_range_end)) {
|
|
base_key.Set(&BSGS_CURRENT);
|
|
//BSGS_N_double
|
|
BSGS_CURRENT.Add(&BSGS_N_double);
|
|
/*
|
|
BSGS_CURRENT.Add(&BSGS_N);
|
|
BSGS_CURRENT.Add(&BSGS_N);
|
|
*/
|
|
}
|
|
else {
|
|
entrar = 0;
|
|
}
|
|
break;
|
|
case 2: //random - middle
|
|
base_key.Rand(&BSGS_CURRENT,&n_range_end);
|
|
break;
|
|
}
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
ReleaseMutex(bsgs_thread);
|
|
#else
|
|
pthread_mutex_unlock(&bsgs_thread);
|
|
#endif
|
|
|
|
if(entrar == 0)
|
|
break;
|
|
|
|
if(FLAGMATRIX) {
|
|
aux_c = base_key.GetBase16();
|
|
printf("[+] Thread 0x%s \n",aux_c);
|
|
fflush(stdout);
|
|
free(aux_c);
|
|
}
|
|
else {
|
|
if(FLAGQUIET == 0){
|
|
aux_c = base_key.GetBase16();
|
|
printf("\r[+] Thread 0x%s \r",aux_c);
|
|
fflush(stdout);
|
|
free(aux_c);
|
|
THREADOUTPUT = 1;
|
|
}
|
|
}
|
|
|
|
base_point = secp->ComputePublicKey(&base_key);
|
|
|
|
km.Set(&base_key);
|
|
km.Neg();
|
|
|
|
km.Add(&secp->order);
|
|
km.Sub(&intaux);
|
|
point_aux = secp->ComputePublicKey(&km);
|
|
|
|
for(k = 0; k < bsgs_point_number ; k++) {
|
|
if(bsgs_found[k] == 0) {
|
|
startP = secp->AddDirect(OriginalPointsBSGS[k],point_aux);
|
|
uint32_t j = 0;
|
|
while( j < cycles && bsgs_found[k]== 0 ) {
|
|
int i;
|
|
for(i = 0; i < hLength; i++) {
|
|
dx[i].ModSub(&GSn[i].x,&startP.x);
|
|
}
|
|
dx[i].ModSub(&GSn[i].x,&startP.x); // For the first point
|
|
dx[i+1].ModSub(&_2GSn.x,&startP.x); // For the next center point
|
|
|
|
// Grouped ModInv
|
|
grp->ModInv();
|
|
|
|
/*
|
|
We use the fact that P + i*G and P - i*G has the same deltax, so the same inverse
|
|
We compute key in the positive and negative way from the center of the group
|
|
*/
|
|
|
|
// center point
|
|
pts[CPU_GRP_SIZE / 2] = startP;
|
|
|
|
for(i = 0; i<hLength; i++) {
|
|
|
|
pp = startP;
|
|
pn = startP;
|
|
|
|
// P = startP + i*G
|
|
dy.ModSub(&GSn[i].y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&GSn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
#if 0
|
|
pp.y.ModSub(&GSn[i].x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&GSn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
#endif
|
|
|
|
// P = startP - i*G , if (x,y) = i*G then (x,-y) = -i*G
|
|
dyn.Set(&GSn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&GSn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
#if 0
|
|
pn.y.ModSub(&GSn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&GSn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
#endif
|
|
|
|
|
|
pts[CPU_GRP_SIZE / 2 + (i + 1)] = pp;
|
|
pts[CPU_GRP_SIZE / 2 - (i + 1)] = pn;
|
|
|
|
}
|
|
|
|
// First point (startP - (GRP_SZIE/2)*G)
|
|
pn = startP;
|
|
dyn.Set(&GSn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&GSn[i].x);
|
|
|
|
#if 0
|
|
pn.y.ModSub(&GSn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&GSn[i].y);
|
|
#endif
|
|
|
|
pts[0] = pn;
|
|
|
|
for(int i = 0; i<CPU_GRP_SIZE && bsgs_found[k]== 0; i++) {
|
|
pts[i].x.Get32Bytes((unsigned char*)xpoint_raw);
|
|
r = bloom_check(&bloom_bP[((unsigned char)xpoint_raw[0])],xpoint_raw,32);
|
|
if(r) {
|
|
r = bsgs_secondcheck(&base_key,((j*1024) + i),k,&keyfound);
|
|
if(r) {
|
|
hextemp = keyfound.GetBase16();
|
|
printf("[+] Thread Key found privkey %s \n",hextemp);
|
|
point_found = secp->ComputePublicKey(&keyfound);
|
|
aux_c = secp->GetPublicKeyHex(OriginalPointsBSGScompressed[k],point_found);
|
|
printf("[+] Publickey %s\n",aux_c);
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(write_keys, INFINITE);
|
|
#else
|
|
pthread_mutex_lock(&write_keys);
|
|
#endif
|
|
|
|
filekey = fopen("KEYFOUNDKEYFOUND.txt","a");
|
|
if(filekey != NULL) {
|
|
fprintf(filekey,"Key found privkey %s\nPublickey %s\n",hextemp,aux_c);
|
|
fclose(filekey);
|
|
}
|
|
free(hextemp);
|
|
free(aux_c);
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
ReleaseMutex(write_keys);
|
|
#else
|
|
pthread_mutex_unlock(&write_keys);
|
|
#endif
|
|
|
|
bsgs_found[k] = 1;
|
|
salir = 1;
|
|
for(l = 0; l < bsgs_point_number && salir; l++) {
|
|
salir &= bsgs_found[l];
|
|
}
|
|
if(salir) {
|
|
printf("All points were found\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
} //End if second check
|
|
}//End if first check
|
|
|
|
}// For for pts variable
|
|
|
|
// Next start point (startP += (bsSize*GRP_SIZE).G)
|
|
|
|
pp = startP;
|
|
dy.ModSub(&_2GSn.y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i + 1]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&_2GSn.x);
|
|
|
|
pp.y.ModSub(&_2GSn.x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&_2GSn.y);
|
|
startP = pp;
|
|
|
|
j++;
|
|
}//while all the aMP points
|
|
}// End if
|
|
}
|
|
steps[thread_number]+=2;
|
|
}while(1);
|
|
ends[thread_number] = 1;
|
|
return NULL;
|
|
}
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
DWORD WINAPI thread_process_bsgs_backward(LPVOID vargp) {
|
|
#else
|
|
void *thread_process_bsgs_backward(void *vargp) {
|
|
#endif
|
|
FILE *filekey;
|
|
struct tothread *tt;
|
|
char xpoint_raw[32],*aux_c,*hextemp;
|
|
Int base_key,keyfound;
|
|
Point base_point,point_aux,point_found;
|
|
uint32_t k,l,r,salir,thread_number,entrar,cycles;
|
|
|
|
IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1);
|
|
Point startP;
|
|
|
|
int hLength = (CPU_GRP_SIZE / 2 - 1);
|
|
|
|
Int dx[CPU_GRP_SIZE / 2 + 1];
|
|
Point pts[CPU_GRP_SIZE];
|
|
|
|
Int dy;
|
|
Int dyn;
|
|
Int _s;
|
|
Int _p;
|
|
Int km,intaux;
|
|
Point pp;
|
|
Point pn;
|
|
grp->Set(dx);
|
|
|
|
tt = (struct tothread *)vargp;
|
|
thread_number = tt->nt;
|
|
free(tt);
|
|
|
|
cycles = bsgs_aux / 1024;
|
|
if(bsgs_aux % 1024 != 0) {
|
|
cycles++;
|
|
}
|
|
|
|
intaux.Set(&BSGS_M_double);
|
|
intaux.Mult(CPU_GRP_SIZE/2);
|
|
intaux.Add(&BSGS_M);
|
|
|
|
entrar = 1;
|
|
/*
|
|
while base_key is less than n_range_end then:
|
|
*/
|
|
do {
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(bsgs_thread, INFINITE);
|
|
#else
|
|
pthread_mutex_lock(&bsgs_thread);
|
|
#endif
|
|
if(n_range_end.IsGreater(&n_range_start)) {
|
|
n_range_end.Sub(&BSGS_N_double);
|
|
if(n_range_end.IsLower(&n_range_start)) {
|
|
base_key.Set(&n_range_start);
|
|
}
|
|
else {
|
|
base_key.Set(&n_range_end);
|
|
}
|
|
}
|
|
else {
|
|
entrar = 0;
|
|
}
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
ReleaseMutex(bsgs_thread);
|
|
#else
|
|
pthread_mutex_unlock(&bsgs_thread);
|
|
#endif
|
|
if(entrar == 0)
|
|
break;
|
|
|
|
if(FLAGMATRIX) {
|
|
aux_c = base_key.GetBase16();
|
|
printf("[+] Thread 0x%s \n",aux_c);
|
|
fflush(stdout);
|
|
free(aux_c);
|
|
}
|
|
else {
|
|
if(FLAGQUIET == 0){
|
|
aux_c = base_key.GetBase16();
|
|
printf("\r[+] Thread 0x%s \r",aux_c);
|
|
fflush(stdout);
|
|
free(aux_c);
|
|
THREADOUTPUT = 1;
|
|
}
|
|
}
|
|
|
|
base_point = secp->ComputePublicKey(&base_key);
|
|
|
|
km.Set(&base_key);
|
|
km.Neg();
|
|
|
|
km.Add(&secp->order);
|
|
km.Sub(&intaux);
|
|
point_aux = secp->ComputePublicKey(&km);
|
|
|
|
for(k = 0; k < bsgs_point_number ; k++) {
|
|
if(bsgs_found[k] == 0) {
|
|
startP = secp->AddDirect(OriginalPointsBSGS[k],point_aux);
|
|
uint32_t j = 0;
|
|
while( j < cycles && bsgs_found[k]== 0 ) {
|
|
int i;
|
|
for(i = 0; i < hLength; i++) {
|
|
dx[i].ModSub(&GSn[i].x,&startP.x);
|
|
}
|
|
dx[i].ModSub(&GSn[i].x,&startP.x); // For the first point
|
|
dx[i+1].ModSub(&_2GSn.x,&startP.x); // For the next center point
|
|
|
|
// Grouped ModInv
|
|
grp->ModInv();
|
|
|
|
/*
|
|
We use the fact that P + i*G and P - i*G has the same deltax, so the same inverse
|
|
We compute key in the positive and negative way from the center of the group
|
|
*/
|
|
|
|
// center point
|
|
pts[CPU_GRP_SIZE / 2] = startP;
|
|
|
|
for(i = 0; i<hLength; i++) {
|
|
|
|
pp = startP;
|
|
pn = startP;
|
|
|
|
// P = startP + i*G
|
|
dy.ModSub(&GSn[i].y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&GSn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
#if 0
|
|
pp.y.ModSub(&GSn[i].x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&GSn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
#endif
|
|
|
|
// P = startP - i*G , if (x,y) = i*G then (x,-y) = -i*G
|
|
dyn.Set(&GSn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&GSn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
#if 0
|
|
pn.y.ModSub(&GSn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&GSn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
#endif
|
|
|
|
|
|
pts[CPU_GRP_SIZE / 2 + (i + 1)] = pp;
|
|
pts[CPU_GRP_SIZE / 2 - (i + 1)] = pn;
|
|
|
|
}
|
|
|
|
// First point (startP - (GRP_SZIE/2)*G)
|
|
pn = startP;
|
|
dyn.Set(&GSn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&GSn[i].x);
|
|
|
|
#if 0
|
|
pn.y.ModSub(&GSn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&GSn[i].y);
|
|
#endif
|
|
|
|
pts[0] = pn;
|
|
|
|
for(int i = 0; i<CPU_GRP_SIZE && bsgs_found[k]== 0; i++) {
|
|
pts[i].x.Get32Bytes((unsigned char*)xpoint_raw);
|
|
r = bloom_check(&bloom_bP[((unsigned char)xpoint_raw[0])],xpoint_raw,32);
|
|
if(r) {
|
|
r = bsgs_secondcheck(&base_key,((j*1024) + i),k,&keyfound);
|
|
if(r) {
|
|
hextemp = keyfound.GetBase16();
|
|
printf("[+] Thread Key found privkey %s \n",hextemp);
|
|
point_found = secp->ComputePublicKey(&keyfound);
|
|
aux_c = secp->GetPublicKeyHex(OriginalPointsBSGScompressed[k],point_found);
|
|
printf("[+] Publickey %s\n",aux_c);
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(write_keys, INFINITE);
|
|
#else
|
|
pthread_mutex_lock(&write_keys);
|
|
#endif
|
|
|
|
filekey = fopen("KEYFOUNDKEYFOUND.txt","a");
|
|
if(filekey != NULL) {
|
|
fprintf(filekey,"Key found privkey %s\nPublickey %s\n",hextemp,aux_c);
|
|
fclose(filekey);
|
|
}
|
|
free(hextemp);
|
|
free(aux_c);
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
ReleaseMutex(write_keys);
|
|
#else
|
|
pthread_mutex_unlock(&write_keys);
|
|
#endif
|
|
|
|
bsgs_found[k] = 1;
|
|
salir = 1;
|
|
for(l = 0; l < bsgs_point_number && salir; l++) {
|
|
salir &= bsgs_found[l];
|
|
}
|
|
if(salir) {
|
|
printf("All points were found\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
} //End if second check
|
|
}//End if first check
|
|
|
|
}// For for pts variable
|
|
|
|
// Next start point (startP += (bsSize*GRP_SIZE).G)
|
|
|
|
pp = startP;
|
|
dy.ModSub(&_2GSn.y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i + 1]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&_2GSn.x);
|
|
|
|
pp.y.ModSub(&_2GSn.x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&_2GSn.y);
|
|
startP = pp;
|
|
j++;
|
|
}//while all the aMP points
|
|
}// End if
|
|
}
|
|
steps[thread_number]+=2;
|
|
}while(1);
|
|
ends[thread_number] = 1;
|
|
return NULL;
|
|
}
|
|
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
DWORD WINAPI thread_process_bsgs_both(LPVOID vargp) {
|
|
#else
|
|
void *thread_process_bsgs_both(void *vargp) {
|
|
#endif
|
|
FILE *filekey;
|
|
struct tothread *tt;
|
|
char xpoint_raw[32],*aux_c,*hextemp;
|
|
Int base_key,keyfound;
|
|
Point base_point,point_aux,point_found;
|
|
uint32_t k,l,r,salir,thread_number,entrar,cycles;
|
|
|
|
IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1);
|
|
Point startP;
|
|
|
|
int hLength = (CPU_GRP_SIZE / 2 - 1);
|
|
|
|
Int dx[CPU_GRP_SIZE / 2 + 1];
|
|
Point pts[CPU_GRP_SIZE];
|
|
|
|
Int dy;
|
|
Int dyn;
|
|
Int _s;
|
|
Int _p;
|
|
Int km,intaux;
|
|
Point pp;
|
|
Point pn;
|
|
grp->Set(dx);
|
|
|
|
|
|
tt = (struct tothread *)vargp;
|
|
thread_number = tt->nt;
|
|
free(tt);
|
|
|
|
cycles = bsgs_aux / 1024;
|
|
if(bsgs_aux % 1024 != 0) {
|
|
cycles++;
|
|
}
|
|
|
|
intaux.Set(&BSGS_M_double);
|
|
intaux.Mult(CPU_GRP_SIZE/2);
|
|
intaux.Add(&BSGS_M);
|
|
|
|
entrar = 1;
|
|
/*
|
|
while BSGS_CURRENT is less than n_range_end
|
|
*/
|
|
do {
|
|
|
|
r = rand() % 2;
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(bsgs_thread, INFINITE);
|
|
#else
|
|
pthread_mutex_lock(&bsgs_thread);
|
|
#endif
|
|
switch(r) {
|
|
case 0: //TOP
|
|
if(n_range_end.IsGreater(&BSGS_CURRENT)) {
|
|
n_range_end.Sub(&BSGS_N_double);
|
|
/*
|
|
n_range_end.Sub(&BSGS_N);
|
|
n_range_end.Sub(&BSGS_N);
|
|
*/
|
|
if(n_range_end.IsLower(&BSGS_CURRENT)) {
|
|
base_key.Set(&BSGS_CURRENT);
|
|
}
|
|
else {
|
|
base_key.Set(&n_range_end);
|
|
}
|
|
}
|
|
else {
|
|
entrar = 0;
|
|
}
|
|
break;
|
|
case 1: //BOTTOM
|
|
if(BSGS_CURRENT.IsLower(&n_range_end)) {
|
|
base_key.Set(&BSGS_CURRENT);
|
|
//BSGS_N_double
|
|
BSGS_CURRENT.Add(&BSGS_N_double);
|
|
/*
|
|
BSGS_CURRENT.Add(&BSGS_N);
|
|
BSGS_CURRENT.Add(&BSGS_N);
|
|
*/
|
|
}
|
|
else {
|
|
entrar = 0;
|
|
}
|
|
break;
|
|
}
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
ReleaseMutex(bsgs_thread);
|
|
#else
|
|
pthread_mutex_unlock(&bsgs_thread);
|
|
#endif
|
|
|
|
if(entrar == 0)
|
|
break;
|
|
|
|
if(FLAGMATRIX) {
|
|
aux_c = base_key.GetBase16();
|
|
printf("[+] Thread 0x%s \n",aux_c);
|
|
fflush(stdout);
|
|
free(aux_c);
|
|
}
|
|
else {
|
|
if(FLAGQUIET == 0){
|
|
aux_c = base_key.GetBase16();
|
|
printf("\r[+] Thread 0x%s \r",aux_c);
|
|
fflush(stdout);
|
|
free(aux_c);
|
|
THREADOUTPUT = 1;
|
|
}
|
|
}
|
|
|
|
base_point = secp->ComputePublicKey(&base_key);
|
|
|
|
km.Set(&base_key);
|
|
km.Neg();
|
|
|
|
km.Add(&secp->order);
|
|
km.Sub(&intaux);
|
|
point_aux = secp->ComputePublicKey(&km);
|
|
|
|
for(k = 0; k < bsgs_point_number ; k++) {
|
|
if(bsgs_found[k] == 0) {
|
|
startP = secp->AddDirect(OriginalPointsBSGS[k],point_aux);
|
|
uint32_t j = 0;
|
|
while( j < cycles && bsgs_found[k]== 0 ) {
|
|
int i;
|
|
for(i = 0; i < hLength; i++) {
|
|
dx[i].ModSub(&GSn[i].x,&startP.x);
|
|
}
|
|
dx[i].ModSub(&GSn[i].x,&startP.x); // For the first point
|
|
dx[i+1].ModSub(&_2GSn.x,&startP.x); // For the next center point
|
|
|
|
// Grouped ModInv
|
|
grp->ModInv();
|
|
|
|
/*
|
|
We use the fact that P + i*G and P - i*G has the same deltax, so the same inverse
|
|
We compute key in the positive and negative way from the center of the group
|
|
*/
|
|
|
|
// center point
|
|
pts[CPU_GRP_SIZE / 2] = startP;
|
|
|
|
for(i = 0; i<hLength; i++) {
|
|
|
|
pp = startP;
|
|
pn = startP;
|
|
|
|
// P = startP + i*G
|
|
dy.ModSub(&GSn[i].y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&GSn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
#if 0
|
|
pp.y.ModSub(&GSn[i].x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&GSn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
#endif
|
|
|
|
// P = startP - i*G , if (x,y) = i*G then (x,-y) = -i*G
|
|
dyn.Set(&GSn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]); // s = (p2.y-p1.y)*inverse(p2.x-p1.x);
|
|
_p.ModSquareK1(&_s); // _p = pow2(s)
|
|
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&GSn[i].x); // rx = pow2(s) - p1.x - p2.x;
|
|
|
|
#if 0
|
|
pn.y.ModSub(&GSn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&GSn[i].y); // ry = - p2.y - s*(ret.x-p2.x);
|
|
#endif
|
|
|
|
|
|
pts[CPU_GRP_SIZE / 2 + (i + 1)] = pp;
|
|
pts[CPU_GRP_SIZE / 2 - (i + 1)] = pn;
|
|
|
|
}
|
|
|
|
// First point (startP - (GRP_SZIE/2)*G)
|
|
pn = startP;
|
|
dyn.Set(&GSn[i].y);
|
|
dyn.ModNeg();
|
|
dyn.ModSub(&pn.y);
|
|
|
|
_s.ModMulK1(&dyn,&dx[i]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pn.x.ModNeg();
|
|
pn.x.ModAdd(&_p);
|
|
pn.x.ModSub(&GSn[i].x);
|
|
|
|
#if 0
|
|
pn.y.ModSub(&GSn[i].x,&pn.x);
|
|
pn.y.ModMulK1(&_s);
|
|
pn.y.ModAdd(&GSn[i].y);
|
|
#endif
|
|
|
|
pts[0] = pn;
|
|
|
|
for(int i = 0; i<CPU_GRP_SIZE && bsgs_found[k]== 0; i++) {
|
|
pts[i].x.Get32Bytes((unsigned char*)xpoint_raw);
|
|
r = bloom_check(&bloom_bP[((unsigned char)xpoint_raw[0])],xpoint_raw,32);
|
|
if(r) {
|
|
r = bsgs_secondcheck(&base_key,((j*1024) + i),k,&keyfound);
|
|
if(r) {
|
|
hextemp = keyfound.GetBase16();
|
|
printf("[+] Thread Key found privkey %s \n",hextemp);
|
|
point_found = secp->ComputePublicKey(&keyfound);
|
|
aux_c = secp->GetPublicKeyHex(OriginalPointsBSGScompressed[k],point_found);
|
|
printf("[+] Publickey %s\n",aux_c);
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(write_keys, INFINITE);
|
|
#else
|
|
pthread_mutex_lock(&write_keys);
|
|
#endif
|
|
|
|
filekey = fopen("KEYFOUNDKEYFOUND.txt","a");
|
|
if(filekey != NULL) {
|
|
fprintf(filekey,"Key found privkey %s\nPublickey %s\n",hextemp,aux_c);
|
|
fclose(filekey);
|
|
}
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
ReleaseMutex(write_keys);
|
|
#else
|
|
pthread_mutex_unlock(&write_keys);
|
|
#endif
|
|
|
|
free(hextemp);
|
|
free(aux_c);
|
|
bsgs_found[k] = 1;
|
|
salir = 1;
|
|
for(l = 0; l < bsgs_point_number && salir; l++) {
|
|
salir &= bsgs_found[l];
|
|
}
|
|
if(salir) {
|
|
printf("All points were found\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
} //End if second check
|
|
}//End if first check
|
|
|
|
}// For for pts variable
|
|
|
|
// Next start point (startP += (bsSize*GRP_SIZE).G)
|
|
|
|
pp = startP;
|
|
dy.ModSub(&_2GSn.y,&pp.y);
|
|
|
|
_s.ModMulK1(&dy,&dx[i + 1]);
|
|
_p.ModSquareK1(&_s);
|
|
|
|
pp.x.ModNeg();
|
|
pp.x.ModAdd(&_p);
|
|
pp.x.ModSub(&_2GSn.x);
|
|
|
|
pp.y.ModSub(&_2GSn.x,&pp.x);
|
|
pp.y.ModMulK1(&_s);
|
|
pp.y.ModSub(&_2GSn.y);
|
|
startP = pp;
|
|
|
|
j++;
|
|
}//while all the aMP points
|
|
}// End if
|
|
}
|
|
steps[thread_number]+=2;
|
|
}while(1);
|
|
ends[thread_number] = 1;
|
|
return NULL;
|
|
}
|
|
|
|
/* This function takes in three parameters:
|
|
|
|
buffer: a pointer to a char array where the minikey will be stored.
|
|
rawbuffer: a pointer to a char array that contains the raw data.
|
|
length: an integer representing the length of the raw data.
|
|
The function is designed to convert the raw data using a lookup table (Ccoinbuffer) and store the result in the buffer.
|
|
*/
|
|
void set_minikey(char *buffer,char *rawbuffer,int length) {
|
|
for(int i = 0; i < length; i++) {
|
|
buffer[i] = Ccoinbuffer[(uint8_t)rawbuffer[i]];
|
|
}
|
|
}
|
|
|
|
/* This function takes in three parameters:
|
|
|
|
buffer: a pointer to a char array where the minikey will be stored.
|
|
rawbuffer: a pointer to a char array that contains the raw data.
|
|
index: an integer representing the index of the raw data array to be incremented.
|
|
The function is designed to increment the value at the specified index in the raw data array,
|
|
and update the corresponding value in the buffer using a lookup table (Ccoinbuffer).
|
|
If the value at the specified index exceeds 57, it is reset to 0x00 and the function recursively
|
|
calls itself to increment the value at the previous index, unless the index is already 0, in which
|
|
case the function returns false. The function returns true otherwise.
|
|
*/
|
|
|
|
bool increment_minikey_index(char *buffer,char *rawbuffer,int index) {
|
|
if(rawbuffer[index] < 57){
|
|
rawbuffer[index]++;
|
|
buffer[index] = Ccoinbuffer[(uint8_t)rawbuffer[index]];
|
|
}
|
|
else {
|
|
rawbuffer[index] = 0x00;
|
|
buffer[index] = Ccoinbuffer[0];
|
|
if(index>0) {
|
|
return increment_minikey_index(buffer,rawbuffer,index-1);
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/* This function takes in a single parameter:
|
|
|
|
rawbuffer: a pointer to a char array that contains the raw data.
|
|
The function is designed to increment the values in the raw data array
|
|
using a lookup table (minikeyN), while also handling carry-over to the
|
|
previous element in the array if necessary. The maximum number of iterations
|
|
is limited by minikey_n_limit.
|
|
|
|
|
|
*/
|
|
void increment_minikey_N(char *rawbuffer) {
|
|
int i = 20,j = 0;
|
|
while( i > 0 && j < minikey_n_limit) {
|
|
rawbuffer[i] = rawbuffer[i] + minikeyN[i];
|
|
if(rawbuffer[i] > 57) { // Handling carry-over if value exceeds 57
|
|
rawbuffer[i] = rawbuffer[i] % 58;
|
|
rawbuffer[i-1]++;
|
|
}
|
|
i--;
|
|
j++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
#define BUFFMINIKEY(buff,src) \
|
|
(buff)[ 0] = (uint32_t)src[ 0] << 24 | (uint32_t)src[ 1] << 16 | (uint32_t)src[ 2] << 8 | (uint32_t)src[ 3]; \
|
|
(buff)[ 1] = (uint32_t)src[ 4] << 24 | (uint32_t)src[ 5] << 16 | (uint32_t)src[ 6] << 8 | (uint32_t)src[ 7]; \
|
|
(buff)[ 2] = (uint32_t)src[ 8] << 24 | (uint32_t)src[ 9] << 16 | (uint32_t)src[10] << 8 | (uint32_t)src[11]; \
|
|
(buff)[ 3] = (uint32_t)src[12] << 24 | (uint32_t)src[13] << 16 | (uint32_t)src[14] << 8 | (uint32_t)src[15]; \
|
|
(buff)[ 4] = (uint32_t)src[16] << 24 | (uint32_t)src[17] << 16 | (uint32_t)src[18] << 8 | (uint32_t)src[19]; \
|
|
(buff)[ 5] = (uint32_t)src[20] << 24 | (uint32_t)src[21] << 16 | 0x8000; \
|
|
(buff)[ 6] = 0; \
|
|
(buff)[ 7] = 0; \
|
|
(buff)[ 8] = 0; \
|
|
(buff)[ 9] = 0; \
|
|
(buff)[10] = 0; \
|
|
(buff)[11] = 0; \
|
|
(buff)[12] = 0; \
|
|
(buff)[13] = 0; \
|
|
(buff)[14] = 0; \
|
|
(buff)[15] = 0xB0; //176 bits => 22 BYTES
|
|
*/
|
|
|
|
void sha256sse_22(uint8_t *src0, uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *dst0, uint8_t *dst1, uint8_t *dst2, uint8_t *dst3) {
|
|
sha256(src0,22,dst0);
|
|
sha256(src1,22,dst1);
|
|
sha256(src2,22,dst2);
|
|
sha256(src3,22,dst3);
|
|
}
|
|
|
|
/*
|
|
#define BUFFMINIKEYCHECK(buff,src) \
|
|
(buff)[ 0] = (uint32_t)src[ 0] << 24 | (uint32_t)src[ 1] << 16 | (uint32_t)src[ 2] << 8 | (uint32_t)src[ 3]; \
|
|
(buff)[ 1] = (uint32_t)src[ 4] << 24 | (uint32_t)src[ 5] << 16 | (uint32_t)src[ 6] << 8 | (uint32_t)src[ 7]; \
|
|
(buff)[ 2] = (uint32_t)src[ 8] << 24 | (uint32_t)src[ 9] << 16 | (uint32_t)src[10] << 8 | (uint32_t)src[11]; \
|
|
(buff)[ 3] = (uint32_t)src[12] << 24 | (uint32_t)src[13] << 16 | (uint32_t)src[14] << 8 | (uint32_t)src[15]; \
|
|
(buff)[ 4] = (uint32_t)src[16] << 24 | (uint32_t)src[17] << 16 | (uint32_t)src[18] << 8 | (uint32_t)src[19]; \
|
|
(buff)[ 5] = (uint32_t)src[20] << 24 | (uint32_t)src[21] << 16 | (uint32_t)src[22] << 8 | 0x80; \
|
|
(buff)[ 6] = 0; \
|
|
(buff)[ 7] = 0; \
|
|
(buff)[ 8] = 0; \
|
|
(buff)[ 9] = 0; \
|
|
(buff)[10] = 0; \
|
|
(buff)[11] = 0; \
|
|
(buff)[12] = 0; \
|
|
(buff)[13] = 0; \
|
|
(buff)[14] = 0; \
|
|
(buff)[15] = 0xB8; */ //184 bits => 23 BYTES
|
|
|
|
|
|
|
|
|
|
void sha256sse_23(uint8_t *src0, uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *dst0, uint8_t *dst1, uint8_t *dst2, uint8_t *dst3) {
|
|
sha256(src0,23,dst0);
|
|
sha256(src1,23,dst1);
|
|
sha256(src2,23,dst2);
|
|
sha256(src3,23,dst3);
|
|
}
|
|
|
|
void menu() {
|
|
printf("\nUsage:\n");
|
|
printf("-h show this help\n");
|
|
printf("-B Mode BSGS now have some modes <sequential, backward, both, random, dance>\n");
|
|
printf("-b bits For some puzzles you only need some numbers of bits in the test keys.\n");
|
|
printf("-c crypto Search for specific crypto. <btc, eth> valid only w/ -m address\n");
|
|
printf("-C mini Set the minikey Base only 22 character minikeys, ex: SRPqx8QiwnW4WNWnTVa2W5\n");
|
|
printf("-8 alpha Set the bas58 alphabet for minikeys\n");
|
|
printf("-e Enable endomorphism search (Only for address, rmd160 and vanity)\n");
|
|
printf("-f file Specify file name with addresses or xpoints or uncompressed public keys\n");
|
|
printf("-I stride Stride for xpoint, rmd160 and address, this option don't work with bsgs\n");
|
|
printf("-k value Use this only with bsgs mode, k value is factor for M, more speed but more RAM use wisely\n");
|
|
printf("-l look What type of address/hash160 are you looking for <compress, uncompress, both> Only for rmd160 and address\n");
|
|
printf("-m mode mode of search for cryptos. (bsgs, xpoint, rmd160, address, vanity) default: address\n");
|
|
printf("-M Matrix screen, feel like a h4x0r, but performance will dropped\n");
|
|
printf("-n number Check for N sequential numbers before the random chosen, this only works with -R option\n");
|
|
printf(" Use -n to set the N for the BSGS process. Bigger N more RAM needed\n");
|
|
printf("-q Quiet the thread output\n");
|
|
printf("-r SR:EN StarRange:EndRange, the end range can be omitted for search from start range to N-1 ECC value\n");
|
|
printf("-R Random, this is the default behavior\n");
|
|
printf("-s ns Number of seconds for the stats output, 0 to omit output.\n");
|
|
printf("-S S is for SAVING in files BSGS data (Bloom filters and bPtable)\n");
|
|
printf("-t tn Threads number, must be a positive integer\n");
|
|
printf("-v value Search for vanity Address, only with -m address and rmd160\n");
|
|
printf("-z value Bloom size multiplier, only address,rmd160,vanity, xpoint, value >= 1\n");
|
|
printf("\nExample:\n\n");
|
|
printf("./keyhunt -m rmd160 -f tests/unsolvedpuzzles.rmd -b 66 -l compress -R -q -t 8\n\n");
|
|
printf("This line runs the program with 8 threads from the range 20000000000000000 to 40000000000000000 without stats output\n\n");
|
|
printf("Developed by AlbertoBSD\tTips BTC: 1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW\n");
|
|
printf("Thanks to Iceland always helping and sharing his ideas.\nTips to Iceland: bc1q39meky2mn5qjq704zz0nnkl0v7kj4uz6r529at\n\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
bool vanityrmdmatch(unsigned char *rmdhash) {
|
|
bool r = false;
|
|
int i,j,cmpA,cmpB,result;
|
|
result = bloom_check(vanity_bloom,rmdhash,vanity_rmd_minimun_bytes_check_length);
|
|
switch(result) {
|
|
case -1:
|
|
fprintf(stderr,"[E] Bloom is not initialized\n");
|
|
exit(EXIT_FAILURE);
|
|
break;
|
|
case 1:
|
|
for(i = 0; i < vanity_rmd_targets && !r;i++) {
|
|
for(j = 0; j < vanity_rmd_limits[i] && !r; j++) {
|
|
cmpA = memcmp(vanity_rmd_limit_values_A[i][j],rmdhash,20);
|
|
cmpB = memcmp(vanity_rmd_limit_values_B[i][j],rmdhash,20);
|
|
if(cmpA <= 0 && cmpB >= 0) {
|
|
//if(FLAGDEBUG ) printf("\n\n[D] cmpA = %i, cmpB = %i \n\n",cmpA,cmpB);
|
|
r = true;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
r = false;
|
|
break;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
void writevanitykey(bool compressed,Int *key) {
|
|
Point publickey;
|
|
FILE *keys;
|
|
char *hextemp,*hexrmd,public_key_hex[131],address[50],rmdhash[20];
|
|
hextemp = key->GetBase16();
|
|
publickey = secp->ComputePublicKey(key);
|
|
secp->GetPublicKeyHex(compressed,publickey,public_key_hex);
|
|
|
|
secp->GetHash160(P2PKH,compressed,publickey,(uint8_t*)rmdhash);
|
|
hexrmd = tohex(rmdhash,20);
|
|
rmd160toaddress_dst(rmdhash,address);
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(write_keys, INFINITE);
|
|
#else
|
|
pthread_mutex_lock(&write_keys);
|
|
#endif
|
|
keys = fopen("VANITYKEYFOUND.txt","a+");
|
|
if(keys != NULL) {
|
|
fprintf(keys,"Vanity Private Key: %s\npubkey: %s\nAddress %s\nrmd160 %s\n",hextemp,public_key_hex,address,hexrmd);
|
|
fclose(keys);
|
|
}
|
|
printf("\nVanity Private Key: %s\npubkey: %s\nAddress %s\nrmd160 %s\n",hextemp,public_key_hex,address,hexrmd);
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
ReleaseMutex(write_keys);
|
|
#else
|
|
pthread_mutex_unlock(&write_keys);
|
|
#endif
|
|
free(hextemp);
|
|
free(hexrmd);
|
|
}
|
|
|
|
|
|
int addvanity(char *target) {
|
|
unsigned char raw_value_A[50],raw_value_B[50];
|
|
char target_copy[50];
|
|
int stringsize,targetsize,j,r = 0;
|
|
size_t raw_value_length;
|
|
int values_A_size = 0,values_B_size = 0,minimun_bytes;
|
|
raw_value_length = 50;
|
|
targetsize = strlen(target);
|
|
stringsize = targetsize;
|
|
memset(raw_value_A,0,50);
|
|
memset(target_copy,0,50);
|
|
if(targetsize >= 30 ) {
|
|
return 0;
|
|
}
|
|
memcpy(target_copy,target,targetsize);
|
|
j = 0;
|
|
vanity_address_targets = (char**) realloc(vanity_address_targets,(vanity_rmd_targets+1) * sizeof(char*));
|
|
vanity_address_targets[vanity_rmd_targets] = NULL;
|
|
checkpointer((void *)vanity_address_targets,__FILE__,"realloc","vanity_address_targets" ,__LINE__ -1 );
|
|
vanity_rmd_limits = (int*) realloc(vanity_rmd_limits,(vanity_rmd_targets+1) * sizeof(int));
|
|
vanity_rmd_limits[vanity_rmd_targets] = 0;
|
|
checkpointer((void *)vanity_rmd_limits,__FILE__,"realloc","vanity_rmd_limits" ,__LINE__ -1 );
|
|
vanity_rmd_limit_values_A = (uint8_t***)realloc(vanity_rmd_limit_values_A,(vanity_rmd_targets+1) * sizeof(unsigned char *));
|
|
checkpointer((void *)vanity_rmd_limit_values_A,__FILE__,"realloc","vanity_rmd_limit_values_A" ,__LINE__ -1 );
|
|
vanity_rmd_limit_values_A[vanity_rmd_targets] = NULL;
|
|
vanity_rmd_limit_values_B = (uint8_t***)realloc(vanity_rmd_limit_values_B,(vanity_rmd_targets+1) * sizeof(unsigned char *));
|
|
checkpointer((void *)vanity_rmd_limit_values_B,__FILE__,"realloc","vanity_rmd_limit_values_B" ,__LINE__ -1 );
|
|
vanity_rmd_limit_values_B[vanity_rmd_targets] = NULL;
|
|
do {
|
|
raw_value_length = 50;
|
|
b58tobin(raw_value_A,&raw_value_length,target_copy,stringsize);
|
|
if(raw_value_length < 25) {
|
|
target_copy[stringsize] = '1';
|
|
stringsize++;
|
|
}
|
|
if(raw_value_length == 25) {
|
|
b58tobin(raw_value_A,&raw_value_length,target_copy,stringsize);
|
|
|
|
vanity_rmd_limit_values_A[vanity_rmd_targets] = (uint8_t**)realloc(vanity_rmd_limit_values_A[vanity_rmd_targets],(j+1) * sizeof(unsigned char *));
|
|
checkpointer((void *)vanity_rmd_limit_values_A[vanity_rmd_targets],__FILE__,"realloc","vanity_rmd_limit_values_A" ,__LINE__ -1 );
|
|
vanity_rmd_limit_values_A[vanity_rmd_targets][j] = (uint8_t*)calloc(20,1);
|
|
checkpointer((void *)vanity_rmd_limit_values_A[vanity_rmd_targets][j],__FILE__,"realloc","vanity_rmd_limit_values_A" ,__LINE__ -1 );
|
|
|
|
memcpy(vanity_rmd_limit_values_A[vanity_rmd_targets][j] ,raw_value_A +1,20);
|
|
|
|
j++;
|
|
values_A_size = j;
|
|
target_copy[stringsize] = '1';
|
|
stringsize++;
|
|
}
|
|
}while(raw_value_length <= 25);
|
|
|
|
stringsize = targetsize;
|
|
memset(raw_value_B,0,50);
|
|
memset(target_copy,0,50);
|
|
memcpy(target_copy,target,targetsize);
|
|
|
|
j = 0;
|
|
do {
|
|
raw_value_length = 50;
|
|
b58tobin(raw_value_B,&raw_value_length,target_copy,stringsize);
|
|
if(raw_value_length < 25) {
|
|
target_copy[stringsize] = 'z';
|
|
stringsize++;
|
|
}
|
|
if(raw_value_length == 25) {
|
|
|
|
b58tobin(raw_value_B,&raw_value_length,target_copy,stringsize);
|
|
vanity_rmd_limit_values_B[vanity_rmd_targets] = (uint8_t**)realloc(vanity_rmd_limit_values_B[vanity_rmd_targets],(j+1) * sizeof(unsigned char *));
|
|
checkpointer((void *)vanity_rmd_limit_values_B[vanity_rmd_targets],__FILE__,"realloc","vanity_rmd_limit_values_B" ,__LINE__ -1 );
|
|
checkpointer((void *)vanity_rmd_limit_values_B[vanity_rmd_targets],__FILE__,"realloc","vanity_rmd_limit_values_B" ,__LINE__ -1 );
|
|
vanity_rmd_limit_values_B[vanity_rmd_targets][j] = (uint8_t*)calloc(20,1);
|
|
checkpointer((void *)vanity_rmd_limit_values_B[vanity_rmd_targets][j],__FILE__,"calloc","vanity_rmd_limit_values_B" ,__LINE__ -1 );
|
|
memcpy(vanity_rmd_limit_values_B[vanity_rmd_targets][j],raw_value_B+1,20);
|
|
|
|
j++;
|
|
values_B_size = j;
|
|
|
|
target_copy[stringsize] = 'z';
|
|
stringsize++;
|
|
}
|
|
}while(raw_value_length <= 25);
|
|
|
|
if(values_A_size >= 1 && values_B_size >= 1) {
|
|
if(values_A_size != values_B_size) {
|
|
if(values_A_size > values_B_size)
|
|
r = values_B_size;
|
|
else
|
|
r = values_A_size;
|
|
}
|
|
else {
|
|
r = values_A_size;
|
|
}
|
|
for(j = 0; j < r; j++) {
|
|
minimun_bytes = minimum_same_bytes(vanity_rmd_limit_values_A[vanity_rmd_targets][j],vanity_rmd_limit_values_B[vanity_rmd_targets][j],20);
|
|
if(minimun_bytes < vanity_rmd_minimun_bytes_check_length) {
|
|
vanity_rmd_minimun_bytes_check_length = minimun_bytes;
|
|
}
|
|
}
|
|
vanity_address_targets[vanity_rmd_targets] = (char*) calloc(targetsize+1,sizeof(char));
|
|
checkpointer((void *)vanity_address_targets[vanity_rmd_targets],__FILE__,"calloc","vanity_address_targets" ,__LINE__ -1 );
|
|
memcpy(vanity_address_targets[vanity_rmd_targets],target,targetsize+1); // +1 to copy the null character
|
|
vanity_rmd_limits[vanity_rmd_targets] = r;
|
|
vanity_rmd_total+=r;
|
|
vanity_rmd_targets++;
|
|
}
|
|
else {
|
|
for(j = 0; j < values_A_size;j++) {
|
|
free(vanity_rmd_limit_values_A[vanity_rmd_targets][j]);
|
|
}
|
|
free(vanity_rmd_limit_values_A[vanity_rmd_targets]);
|
|
vanity_rmd_limit_values_A[vanity_rmd_targets] = NULL;
|
|
|
|
for(j = 0; j < values_B_size;j++) {
|
|
free(vanity_rmd_limit_values_B[vanity_rmd_targets][j]);
|
|
}
|
|
free(vanity_rmd_limit_values_B[vanity_rmd_targets]);
|
|
vanity_rmd_limit_values_B[vanity_rmd_targets] = NULL;
|
|
r = 0;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
|
|
/*
|
|
A and B are binary o string data pointers
|
|
length the max lenght to check.
|
|
|
|
Caller must by sure that the pointer are valid and have at least length bytes readebles witout causing overflow
|
|
*/
|
|
int minimum_same_bytes(unsigned char* A,unsigned char* B, int length) {
|
|
int minBytes = 0; // Assume initially that all bytes are the same
|
|
if(A == NULL || B == NULL) { // In case of some NULL pointer
|
|
return 0;
|
|
}
|
|
for (int i = 0; i < length; i++) {
|
|
if (A[i] != B[i]) {
|
|
break; // Exit the loop since we found a mismatch
|
|
}
|
|
minBytes++; // Update the minimum number of bytes where data is the same
|
|
}
|
|
|
|
return minBytes;
|
|
}
|
|
|
|
void checkpointer(void *ptr,const char *file,const char *function,const char *name,int line) {
|
|
if(ptr == NULL) {
|
|
fprintf(stderr,"[E] error in file %s, %s pointer %s on line %i\n",file,function,name,line);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
void writekey(bool compressed,Int *key) {
|
|
Point publickey;
|
|
FILE *keys;
|
|
char *hextemp,*hexrmd,public_key_hex[132],address[50],rmdhash[20];
|
|
memset(address,0,50);
|
|
memset(public_key_hex,0,132);
|
|
hextemp = key->GetBase16();
|
|
publickey = secp->ComputePublicKey(key);
|
|
secp->GetPublicKeyHex(compressed,publickey,public_key_hex);
|
|
secp->GetHash160(P2PKH,compressed,publickey,(uint8_t*)rmdhash);
|
|
hexrmd = tohex(rmdhash,20);
|
|
rmd160toaddress_dst(rmdhash,address);
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(write_keys, INFINITE);
|
|
#else
|
|
pthread_mutex_lock(&write_keys);
|
|
#endif
|
|
keys = fopen("KEYFOUNDKEYFOUND.txt","a+");
|
|
if(keys != NULL) {
|
|
fprintf(keys,"Private Key: %s\npubkey: %s\nAddress %s\nrmd160 %s\n",hextemp,public_key_hex,address,hexrmd);
|
|
fclose(keys);
|
|
}
|
|
printf("\nHit! Private Key: %s\npubkey: %s\nAddress %s\nrmd160 %s\n",hextemp,public_key_hex,address,hexrmd);
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
ReleaseMutex(write_keys);
|
|
#else
|
|
pthread_mutex_unlock(&write_keys);
|
|
#endif
|
|
free(hextemp);
|
|
free(hexrmd);
|
|
}
|
|
|
|
void writekeyeth(Int *key) {
|
|
Point publickey;
|
|
FILE *keys;
|
|
char *hextemp,address[43],hash[20];
|
|
hextemp = key->GetBase16();
|
|
publickey = secp->ComputePublicKey(key);
|
|
generate_binaddress_eth(publickey,(unsigned char*)hash);
|
|
address[0] = '0';
|
|
address[1] = 'x';
|
|
tohex_dst(hash,20,address+2);
|
|
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
WaitForSingleObject(write_keys, INFINITE);
|
|
#else
|
|
pthread_mutex_lock(&write_keys);
|
|
#endif
|
|
keys = fopen("KEYFOUNDKEYFOUND.txt","a+");
|
|
if(keys != NULL) {
|
|
fprintf(keys,"Private Key: %s\naddress: %s\n",hextemp,address);
|
|
fclose(keys);
|
|
}
|
|
printf("\n Hit!!!! Private Key: %s\naddress: %s\n",hextemp,address);
|
|
#if defined(_WIN64) && !defined(__CYGWIN__)
|
|
ReleaseMutex(write_keys);
|
|
#else
|
|
pthread_mutex_unlock(&write_keys);
|
|
#endif
|
|
free(hextemp);
|
|
}
|
|
|
|
bool isBase58(char c) {
|
|
// Define the base58 set
|
|
const char base58Set[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
// Check if the character is in the base58 set
|
|
return strchr(base58Set, c) != NULL;
|
|
}
|
|
|
|
bool isValidBase58String(char *str) {
|
|
int len = strlen(str);
|
|
bool continuar = true;
|
|
for (int i = 0; i < len && continuar; i++) {
|
|
continuar = isBase58(str[i]);
|
|
}
|
|
return continuar;
|
|
}
|
|
|
|
bool processOneVanity() {
|
|
int i,k;
|
|
if(vanity_rmd_targets == 0) {
|
|
fprintf(stderr,"[E] There aren't any vanity targets\n");
|
|
return false;
|
|
}
|
|
if(!initBloomFilter(vanity_bloom, vanity_rmd_total))
|
|
return false;
|
|
|
|
for(i = 0;i < vanity_rmd_targets;i++) {
|
|
for(k = 0; k < vanity_rmd_limits[i]; k++) {
|
|
bloom_add(vanity_bloom, vanity_rmd_limit_values_A[i][k] ,vanity_rmd_minimun_bytes_check_length);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool readFileVanity(char *fileName) {
|
|
FILE *fileDescriptor;
|
|
int i,k,len;
|
|
char aux[100],*hextemp;
|
|
|
|
fileDescriptor = fopen(fileName,"r");
|
|
if(fileDescriptor == NULL) {
|
|
if(vanity_rmd_targets == 0) {
|
|
fprintf(stderr,"[E] There aren't any vanity targets\n");
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
while(!feof(fileDescriptor)) {
|
|
hextemp = fgets(aux,100,fileDescriptor);
|
|
if(hextemp == aux) {
|
|
trim(aux," \t\n\r");
|
|
len = strlen(aux);
|
|
if(len > 0 && len < 36){
|
|
if(isValidBase58String(aux)) {
|
|
addvanity(aux);
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] the string \"%s\" is not valid Base58, omiting it\n",aux);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
fclose(fileDescriptor);
|
|
}
|
|
|
|
N = vanity_rmd_total;
|
|
if(!initBloomFilter(vanity_bloom,N))
|
|
return false;
|
|
|
|
|
|
for(i = 0;i < vanity_rmd_targets; i++) {
|
|
for(k = 0; k < vanity_rmd_limits[i]; k++) {
|
|
/*
|
|
if(FLAGDEBUG) {
|
|
printf("[D] i %i ; k %i\n",i,k);
|
|
hextemp = tohex((char*)vanity_rmd_limit_values_A[i][k],vanity_rmd_minimun_bytes_check_length);
|
|
printf("[D] Adding %s\n",hextemp);
|
|
fflush(stdout);
|
|
free(hextemp);
|
|
}
|
|
*/
|
|
bloom_add(vanity_bloom, vanity_rmd_limit_values_A[i][k] ,vanity_rmd_minimun_bytes_check_length);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool readFileAddress(char *fileName) {
|
|
FILE *fileDescriptor;
|
|
char fileBloomName[30]; /* Actually it is Bloom and Table but just to keep the variable name short*/
|
|
uint8_t checksum[32],hexPrefix[9];
|
|
char dataChecksum[32],bloomChecksum[32];
|
|
size_t bytesRead;
|
|
uint64_t dataSize;
|
|
/*
|
|
if the FLAGSAVEREADFILE is Set to 1 we need to the checksum and check if we have that information already saved
|
|
*/
|
|
if(FLAGSAVEREADFILE) { /* if the flag is set to REAd and SAVE the file firs we need to check it the file exist*/
|
|
if(!sha256_file((const char*)fileName,checksum)){
|
|
fprintf(stderr,"[E] sha256_file error line %i\n",__LINE__ - 1);
|
|
return false;
|
|
}
|
|
tohex_dst((char*)checksum,4,(char*)hexPrefix); // we save the prefix (last fourt bytes) hexadecimal value
|
|
snprintf(fileBloomName,30,"data_%s.dat",hexPrefix);
|
|
fileDescriptor = fopen(fileBloomName,"rb");
|
|
if(fileDescriptor != NULL) {
|
|
printf("[+] Reading file %s\n",fileBloomName);
|
|
|
|
//read bloom checksum (expected value to be checked)
|
|
//read bloom filter structure
|
|
//read bloom filter data
|
|
//calculate checksum of the current readed data
|
|
//Compare checksums
|
|
//read data checksum (expected value to be checked)
|
|
//read data size
|
|
//read data
|
|
//compare the expected datachecksum againts the current data checksum
|
|
//compare the expected bloom checksum againts the current bloom checksum
|
|
|
|
|
|
//read bloom checksum (expected value to be checked)
|
|
bytesRead = fread(bloomChecksum,1,32,fileDescriptor);
|
|
if(bytesRead != 32) {
|
|
fprintf(stderr,"[E] Errore reading file, code line %i\n",__LINE__ - 2);
|
|
fclose(fileDescriptor);
|
|
return false;
|
|
}
|
|
|
|
//read bloom filter structure
|
|
bytesRead = fread(&bloom,1,sizeof(struct bloom),fileDescriptor);
|
|
if(bytesRead != sizeof(struct bloom)) {
|
|
fprintf(stderr,"[E] Error reading file, code line %i\n",__LINE__ - 2);
|
|
fclose(fileDescriptor);
|
|
return false;
|
|
}
|
|
|
|
printf("[+] Bloom filter for %" PRIu64 " elements.\n",bloom.entries);
|
|
|
|
bloom.bf = (uint8_t*) malloc(bloom.bytes);
|
|
if(bloom.bf == NULL) {
|
|
fprintf(stderr,"[E] Error allocating memory, code line %i\n",__LINE__ - 2);
|
|
fclose(fileDescriptor);
|
|
return false;
|
|
}
|
|
|
|
//read bloom filter data
|
|
bytesRead = fread(bloom.bf,1,bloom.bytes,fileDescriptor);
|
|
if(bytesRead != bloom.bytes) {
|
|
fprintf(stderr,"[E] Error reading file, code line %i\n",__LINE__ - 2);
|
|
fclose(fileDescriptor);
|
|
return false;
|
|
}
|
|
if(FLAGSKIPCHECKSUM == 0){
|
|
|
|
//calculate checksum of the current readed data
|
|
sha256((uint8_t*)bloom.bf,bloom.bytes,(uint8_t*)checksum);
|
|
|
|
//Compare checksums
|
|
if(memcmp(checksum,bloomChecksum,32) != 0) {
|
|
fprintf(stderr,"[E] Error checksum mismatch, code line %i\n",__LINE__ - 2);
|
|
fclose(fileDescriptor);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bytesRead = fread(dataChecksum,1,32,fileDescriptor);
|
|
if(bytesRead != 32) {
|
|
fprintf(stderr,"[E] Errore reading file, code line %i\n",__LINE__ - 2);
|
|
fclose(fileDescriptor);
|
|
return false;
|
|
}
|
|
|
|
bytesRead = fread(&dataSize,1,sizeof(uint64_t),fileDescriptor);
|
|
if(bytesRead != sizeof(uint64_t)) {
|
|
fprintf(stderr,"[E] Errore reading file, code line %i\n",__LINE__ - 2);
|
|
fclose(fileDescriptor);
|
|
return false;
|
|
}
|
|
N = dataSize / sizeof(struct address_value);
|
|
|
|
printf("[+] Allocating memory for %" PRIu64 " elements: %.2f MB\n",N,(double)(((double) sizeof(struct address_value)*N)/(double)1048576));
|
|
|
|
addressTable = (struct address_value*) malloc(dataSize);
|
|
if(addressTable == NULL) {
|
|
fprintf(stderr,"[E] Error allocating memory, code line %i\n",__LINE__ - 2);
|
|
fclose(fileDescriptor);
|
|
return false;
|
|
}
|
|
|
|
bytesRead = fread(addressTable,1,dataSize,fileDescriptor);
|
|
if(bytesRead != dataSize) {
|
|
fprintf(stderr,"[E] Error reading file, code line %i\n",__LINE__ - 2);
|
|
fclose(fileDescriptor);
|
|
return false;
|
|
}
|
|
if(FLAGSKIPCHECKSUM == 0) {
|
|
|
|
sha256((uint8_t*)addressTable,dataSize,(uint8_t*)checksum);
|
|
if(memcmp(checksum,dataChecksum,32) != 0) {
|
|
fprintf(stderr,"[E] Error checksum mismatch, code line %i\n",__LINE__ - 2);
|
|
fclose(fileDescriptor);
|
|
return false;
|
|
}
|
|
}
|
|
//printf("[D] bloom.bf points to %p\n",bloom.bf);
|
|
FLAGREADEDFILE1 = 1; /* We mark the file as readed*/
|
|
fclose(fileDescriptor);
|
|
MAXLENGTHADDRESS = sizeof(struct address_value);
|
|
}
|
|
}
|
|
if(FLAGVANITY) {
|
|
processOneVanity();
|
|
}
|
|
if(!FLAGREADEDFILE1) {
|
|
/*
|
|
if the data_ file doesn't exist we need read it first:
|
|
*/
|
|
switch(FLAGMODE) {
|
|
case MODE_ADDRESS:
|
|
if(FLAGCRYPTO == CRYPTO_BTC) {
|
|
return forceReadFileAddress(fileName);
|
|
}
|
|
if(FLAGCRYPTO == CRYPTO_ETH) {
|
|
return forceReadFileAddressEth(fileName);
|
|
}
|
|
break;
|
|
case MODE_MINIKEYS:
|
|
case MODE_PUB2RMD:
|
|
case MODE_RMD160:
|
|
return forceReadFileAddress(fileName);
|
|
break;
|
|
case MODE_XPOINT:
|
|
return forceReadFileXPoint(fileName);
|
|
break;
|
|
default:
|
|
return false;
|
|
break;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool forceReadFileAddress(char *fileName) {
|
|
/* Here we read the original file as usual */
|
|
FILE *fileDescriptor;
|
|
bool validAddress;
|
|
uint64_t numberItems,i;
|
|
size_t r,raw_value_length;
|
|
uint8_t rawvalue[50];
|
|
char aux[100],*hextemp;
|
|
fileDescriptor = fopen(fileName,"r");
|
|
if(fileDescriptor == NULL) {
|
|
fprintf(stderr,"[E] Error opening the file %s, line %i\n",fileName,__LINE__ - 2);
|
|
return false;
|
|
}
|
|
|
|
/*Count lines in the file*/
|
|
numberItems = 0;
|
|
while(!feof(fileDescriptor)) {
|
|
hextemp = fgets(aux,100,fileDescriptor);
|
|
trim(aux," \t\n\r");
|
|
if(hextemp == aux) {
|
|
r = strlen(aux);
|
|
if(r > 20) {
|
|
numberItems++;
|
|
}
|
|
}
|
|
}
|
|
fseek(fileDescriptor,0,SEEK_SET);
|
|
MAXLENGTHADDRESS = 20; /*20 bytes beacuase we only need the data in binary*/
|
|
|
|
printf("[+] Allocating memory for %" PRIu64 " elements: %.2f MB\n",numberItems,(double)(((double) sizeof(struct address_value)*numberItems)/(double)1048576));
|
|
addressTable = (struct address_value*) malloc(sizeof(struct address_value)*numberItems);
|
|
checkpointer((void *)addressTable,__FILE__,"malloc","addressTable" ,__LINE__ -1 );
|
|
|
|
if(!initBloomFilter(&bloom,numberItems))
|
|
return false;
|
|
|
|
i = 0;
|
|
while(i < numberItems) {
|
|
validAddress = false;
|
|
memset(aux,0,100);
|
|
memset(addressTable[i].value,0,sizeof(struct address_value));
|
|
hextemp = fgets(aux,100,fileDescriptor);
|
|
trim(aux," \t\n\r");
|
|
r = strlen(aux);
|
|
if(r > 0 && r <= 40) {
|
|
if(r<40 && isValidBase58String(aux)) { //Address
|
|
raw_value_length = 25;
|
|
b58tobin(rawvalue,&raw_value_length,aux,r);
|
|
if(raw_value_length == 25) {
|
|
//hextemp = tohex((char*)rawvalue+1,20);
|
|
bloom_add(&bloom, rawvalue+1 ,sizeof(struct address_value));
|
|
memcpy(addressTable[i].value,rawvalue+1,sizeof(struct address_value));
|
|
i++;
|
|
validAddress = true;
|
|
}
|
|
}
|
|
if(r == 40 && isValidHex(aux)) { //RMD
|
|
hexs2bin(aux,rawvalue);
|
|
bloom_add(&bloom, rawvalue ,sizeof(struct address_value));
|
|
memcpy(addressTable[i].value,rawvalue,sizeof(struct address_value));
|
|
i++;
|
|
validAddress = true;
|
|
}
|
|
}
|
|
if(!validAddress) {
|
|
fprintf(stderr,"[I] Ommiting invalid line %s\n",aux);
|
|
numberItems--;
|
|
}
|
|
}
|
|
N = numberItems;
|
|
return true;
|
|
}
|
|
|
|
bool forceReadFileAddressEth(char *fileName) {
|
|
/* Here we read the original file as usual */
|
|
FILE *fileDescriptor;
|
|
bool validAddress;
|
|
uint64_t numberItems,i;
|
|
size_t r;
|
|
uint8_t rawvalue[50];
|
|
char aux[100],*hextemp;
|
|
fileDescriptor = fopen(fileName,"r");
|
|
if(fileDescriptor == NULL) {
|
|
fprintf(stderr,"[E] Error opening the file %s, line %i\n",fileName,__LINE__ - 2);
|
|
return false;
|
|
}
|
|
/*Count lines in the file*/
|
|
numberItems = 0;
|
|
while(!feof(fileDescriptor)) {
|
|
hextemp = fgets(aux,100,fileDescriptor);
|
|
trim(aux," \t\n\r");
|
|
if(hextemp == aux) {
|
|
r = strlen(aux);
|
|
if(r >= 40) {
|
|
numberItems++;
|
|
}
|
|
}
|
|
}
|
|
fseek(fileDescriptor,0,SEEK_SET);
|
|
|
|
MAXLENGTHADDRESS = 20; /*20 bytes beacuase we only need the data in binary*/
|
|
N = numberItems;
|
|
|
|
printf("[+] Allocating memory for %" PRIu64 " elements: %.2f MB\n",numberItems,(double)(((double) sizeof(struct address_value)*numberItems)/(double)1048576));
|
|
addressTable = (struct address_value*) malloc(sizeof(struct address_value)*numberItems);
|
|
checkpointer((void *)addressTable,__FILE__,"malloc","addressTable" ,__LINE__ -1 );
|
|
|
|
|
|
if(!initBloomFilter(&bloom,N))
|
|
return false;
|
|
|
|
i = 0;
|
|
while(i < numberItems) {
|
|
validAddress = false;
|
|
memset(aux,0,100);
|
|
memset(addressTable[i].value,0,sizeof(struct address_value));
|
|
hextemp = fgets(aux,100,fileDescriptor);
|
|
trim(aux," \t\n\r");
|
|
r = strlen(aux);
|
|
if(r >= 40 && r <= 42){
|
|
switch(r) {
|
|
case 40:
|
|
if(isValidHex(aux)){
|
|
hexs2bin(aux,rawvalue);
|
|
bloom_add(&bloom, rawvalue ,sizeof(struct address_value));
|
|
memcpy(addressTable[i].value,rawvalue,sizeof(struct address_value));
|
|
i++;
|
|
validAddress = true;
|
|
}
|
|
break;
|
|
case 42:
|
|
if(isValidHex(aux+2)){
|
|
hexs2bin(aux+2,rawvalue);
|
|
bloom_add(&bloom, rawvalue ,sizeof(struct address_value));
|
|
memcpy(addressTable[i].value,rawvalue,sizeof(struct address_value));
|
|
i++;
|
|
validAddress = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if(!validAddress) {
|
|
fprintf(stderr,"[I] Ommiting invalid line %s\n",aux);
|
|
numberItems--;
|
|
}
|
|
}
|
|
|
|
fclose(fileDescriptor);
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
bool forceReadFileXPoint(char *fileName) {
|
|
/* Here we read the original file as usual */
|
|
FILE *fileDescriptor;
|
|
uint64_t numberItems,i;
|
|
size_t r,lenaux;
|
|
uint8_t rawvalue[100];
|
|
char aux[1000],*hextemp;
|
|
Tokenizer tokenizer_xpoint; //tokenizer
|
|
fileDescriptor = fopen(fileName,"r");
|
|
if(fileDescriptor == NULL) {
|
|
fprintf(stderr,"[E] Error opening the file %s, line %i\n",fileName,__LINE__ - 2);
|
|
return false;
|
|
}
|
|
/*Count lines in the file*/
|
|
numberItems = 0;
|
|
while(!feof(fileDescriptor)) {
|
|
hextemp = fgets(aux,1000,fileDescriptor);
|
|
trim(aux," \t\n\r");
|
|
if(hextemp == aux) {
|
|
r = strlen(aux);
|
|
if(r >= 40) {
|
|
numberItems++;
|
|
}
|
|
}
|
|
}
|
|
fseek(fileDescriptor,0,SEEK_SET);
|
|
|
|
MAXLENGTHADDRESS = 20; /*20 bytes beacuase we only need the data in binary*/
|
|
|
|
printf("[+] Allocating memory for %" PRIu64 " elements: %.2f MB\n",numberItems,(double)(((double) sizeof(struct address_value)*numberItems)/(double)1048576));
|
|
addressTable = (struct address_value*) malloc(sizeof(struct address_value)*numberItems);
|
|
checkpointer((void *)addressTable,__FILE__,"malloc","addressTable" ,__LINE__ - 1);
|
|
|
|
N = numberItems;
|
|
|
|
if(!initBloomFilter(&bloom,N))
|
|
return false;
|
|
|
|
i = 0;
|
|
while(i < N) {
|
|
memset(aux,0,1000);
|
|
hextemp = fgets(aux,1000,fileDescriptor);
|
|
memset((void *)&addressTable[i],0,sizeof(struct address_value));
|
|
if(hextemp == aux) {
|
|
trim(aux," \t\n\r");
|
|
stringtokenizer(aux,&tokenizer_xpoint);
|
|
hextemp = nextToken(&tokenizer_xpoint);
|
|
lenaux = strlen(hextemp);
|
|
if(isValidHex(hextemp)) {
|
|
switch(lenaux) {
|
|
case 64: /*X value*/
|
|
r = hexs2bin(aux,(uint8_t*) rawvalue);
|
|
if(r) {
|
|
memcpy(addressTable[i].value,rawvalue,20);
|
|
bloom_add(&bloom,rawvalue,MAXLENGTHADDRESS);
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] error hexs2bin\n");
|
|
}
|
|
break;
|
|
case 66: /*Compress publickey*/
|
|
r = hexs2bin(aux+2, (uint8_t*)rawvalue);
|
|
if(r) {
|
|
memcpy(addressTable[i].value,rawvalue,20);
|
|
bloom_add(&bloom,rawvalue,MAXLENGTHADDRESS);
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] error hexs2bin\n");
|
|
}
|
|
break;
|
|
case 130: /* Uncompress publickey length*/
|
|
r = hexs2bin(aux, (uint8_t*) rawvalue);
|
|
if(r) {
|
|
memcpy(addressTable[i].value,rawvalue+2,20);
|
|
bloom_add(&bloom,rawvalue,MAXLENGTHADDRESS);
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] error hexs2bin\n");
|
|
}
|
|
break;
|
|
default:
|
|
fprintf(stderr,"[E] Omiting line unknow length size %li: %s\n",lenaux,aux);
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] Ignoring invalid hexvalue %s\n",aux);
|
|
}
|
|
freetokenizer(&tokenizer_xpoint);
|
|
}
|
|
else {
|
|
fprintf(stderr,"[E] Omiting line : %s\n",aux);
|
|
N--;
|
|
}
|
|
i++;
|
|
}
|
|
fclose(fileDescriptor);
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
I write this as a function because i have the same segment of code in 3 different functions
|
|
*/
|
|
|
|
bool initBloomFilter(struct bloom *bloom_arg,uint64_t items_bloom) {
|
|
bool r = true;
|
|
printf("[+] Bloom filter for %" PRIu64 " elements.\n",items_bloom);
|
|
if(items_bloom <= 10000) {
|
|
if(bloom_init2(bloom_arg,10000,0.000001) == 1){
|
|
fprintf(stderr,"[E] error bloom_init for 10000 elements.\n");
|
|
r = false;
|
|
}
|
|
}
|
|
else {
|
|
if(bloom_init2(bloom_arg,FLAGBLOOMMULTIPLIER*items_bloom,0.000001) == 1){
|
|
fprintf(stderr,"[E] error bloom_init for %" PRIu64 " elements.\n",items_bloom);
|
|
r = false;
|
|
}
|
|
}
|
|
printf("[+] Loading data to the bloomfilter total: %.2f MB\n",(double)(((double) bloom_arg->bytes)/(double)1048576));
|
|
return r;
|
|
}
|
|
|
|
void writeFileIfNeeded(const char *fileName) {
|
|
//printf("[D] FLAGSAVEREADFILE %i, FLAGREADEDFILE1 %i\n",FLAGSAVEREADFILE,FLAGREADEDFILE1);
|
|
if(FLAGSAVEREADFILE && !FLAGREADEDFILE1) {
|
|
FILE *fileDescriptor;
|
|
char fileBloomName[30];
|
|
uint8_t checksum[32],hexPrefix[9];
|
|
char dataChecksum[32],bloomChecksum[32];
|
|
size_t bytesWrite;
|
|
uint64_t dataSize;
|
|
if(!sha256_file((const char*)fileName,checksum)){
|
|
fprintf(stderr,"[E] sha256_file error line %i\n",__LINE__ - 1);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
tohex_dst((char*)checksum,4,(char*)hexPrefix); // we save the prefix (last fourt bytes) hexadecimal value
|
|
snprintf(fileBloomName,30,"data_%s.dat",hexPrefix);
|
|
fileDescriptor = fopen(fileBloomName,"wb");
|
|
dataSize = N * (sizeof(struct address_value));
|
|
printf("[D] size data %li\n",dataSize);
|
|
if(fileDescriptor != NULL) {
|
|
printf("[+] Writing file %s ",fileBloomName);
|
|
|
|
|
|
//calculate bloom checksum
|
|
//write bloom checksum (expected value to be checked)
|
|
//write bloom filter structure
|
|
//write bloom filter data
|
|
|
|
|
|
//calculate dataChecksum
|
|
//write data checksum (expected value to be checked)
|
|
//write data size
|
|
//write data
|
|
|
|
|
|
|
|
|
|
sha256((uint8_t*)bloom.bf,bloom.bytes,(uint8_t*)bloomChecksum);
|
|
printf(".");
|
|
bytesWrite = fwrite(bloomChecksum,1,32,fileDescriptor);
|
|
if(bytesWrite != 32) {
|
|
fprintf(stderr,"[E] Errore writing file, code line %i\n",__LINE__ - 2);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
printf(".");
|
|
|
|
bytesWrite = fwrite(&bloom,1,sizeof(struct bloom),fileDescriptor);
|
|
if(bytesWrite != sizeof(struct bloom)) {
|
|
fprintf(stderr,"[E] Error writing file, code line %i\n",__LINE__ - 2);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
printf(".");
|
|
|
|
bytesWrite = fwrite(bloom.bf,1,bloom.bytes,fileDescriptor);
|
|
if(bytesWrite != bloom.bytes) {
|
|
fprintf(stderr,"[E] Error writing file, code line %i\n",__LINE__ - 2);
|
|
fclose(fileDescriptor);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
printf(".");
|
|
|
|
|
|
sha256((uint8_t*)addressTable,dataSize,(uint8_t*)dataChecksum);
|
|
printf(".");
|
|
|
|
bytesWrite = fwrite(dataChecksum,1,32,fileDescriptor);
|
|
if(bytesWrite != 32) {
|
|
fprintf(stderr,"[E] Errore writing file, code line %i\n",__LINE__ - 2);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
printf(".");
|
|
|
|
bytesWrite = fwrite(&dataSize,1,sizeof(uint64_t),fileDescriptor);
|
|
if(bytesWrite != sizeof(uint64_t)) {
|
|
fprintf(stderr,"[E] Errore writing file, code line %i\n",__LINE__ - 2);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
printf(".");
|
|
|
|
bytesWrite = fwrite(addressTable,1,dataSize,fileDescriptor);
|
|
if(bytesWrite != dataSize) {
|
|
fprintf(stderr,"[E] Error writing file, code line %i\n",__LINE__ - 2);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
printf(".");
|
|
|
|
FLAGREADEDFILE1 = 1;
|
|
fclose(fileDescriptor);
|
|
printf("\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void calcualteindex(int i,Int *key) {
|
|
if(i == 0) {
|
|
key->Set(&BSGS_M3);
|
|
}
|
|
else {
|
|
key->SetInt32(i);
|
|
key->Mult(&BSGS_M3_double);
|
|
key->Add(&BSGS_M3);
|
|
}
|
|
}
|