keyhunt/keyhunt.cpp
2023-05-19 22:01:18 -06:00

6690 lines
208 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 "rmd160/rmd160.h"
#include "oldbloom/oldbloom.h"
#include "bloom/bloom.h"
#include "sha3/sha3.h"
#include "util.h"
#include "secp256k1/SECP256k1.h"
#include "secp256k1/Point.h"
#include "secp256k1/Int.h"
#include "secp256k1/IntGroup.h"
#include "secp256k1/Random.h"
#include "hash/sha256.h"
#include "hash/ripemd160.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";
#define CPU_GRP_SIZE 1024
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);
#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);
#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 KECCAK_256(uint8_t *source, size_t size,uint8_t *dst);
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 = NULL;
#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 = NULL;
#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;
uint64_t 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 i,BASE,PERTHREAD_R,itemsbloom,itemsbloom2,itemsbloom3;
uint32_t finished;
int readed,continue_flag,check_flag,c,salir,index_value,j;
Int total,pretotal,debugcount_mpz,seconds,div_pretotal,int_aux,int_r,int_q,int58;
struct bPload *bPload_temp_ptr;
size_t rsize;
#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
srand(time(NULL));
secp = new Secp256K1();
secp->Init();
OUTPUTSECONDS.SetInt32(30);
ZERO.SetInt32(0);
ONE.SetInt32(1);
BSGS_GROUP_SIZE.SetInt32(CPU_GRP_SIZE);
#if defined(_WIN64) && !defined(__CYGWIN__)
//Any windows secure random source goes here
rseed(clock() + time(NULL) + rand());
#else
unsigned long rseedvalue;
int bytes_read = getrandom(&rseedvalue, sizeof(unsigned long), GRND_NONBLOCK);
if(bytes_read > 0) {
rseed(rseedvalue);
/*
In any case that seed is for a failsafe RNG, the default source on linux is getrandom function
See https://www.2uo.de/myths-about-urandom/
*/
}
else {
/*
what year is??
WTF linux without RNG ?
*/
fprintf(stderr,"[E] Error getrandom() ?\n");
exit(EXIT_FAILURE);
rseed(clock() + time(NULL) + rand()*rand());
}
#endif
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 was removed\n");
exit(0);
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( FLAGBSGSMODE == MODE_BSGS && FLAGENDOMORPHISM) {
fprintf(stderr,"[E] Endomorphism doesn't work with BSGS\n");
exit(EXIT_FAILURE);
}
if( FLAGBSGSMODE == MODE_BSGS && FLAGSTRIDE) {
fprintf(stderr,"[E] Stride doesn't work with BSGS\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);
}
init_generator();
if(FLAGMODE == MODE_BSGS ) {
printf("[+] Mode BSGS %s\n",bsgs_modes[FLAGBSGSMODE]);
}
if(FLAGFILE == 0) {
fileName =(char*) default_fileName;
}
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(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(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_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(FLAGMODE != MODE_VANITY && !FLAGREADEDFILE1) {
printf("[+] Sorting data ...");
_sort(addressTable,N);
printf(" done! %" PRIu64 " values were loaded and sorted\n",N);
writeFileIfNeeded(fileName);
}
}
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.reserve(N);
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 _ [%" PRIu64 "]\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 _ [%" PRIu64 "]\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 [%" PRIu64 "]\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);
BSGS_AMP2.reserve(32);
BSGS_AMP3.reserve(32);
GSn.reserve(CPU_GRP_SIZE/2);
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[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(j = 0; j < NTHREADS; j++) {
#if defined(_WIN64) && !defined(__CYGWIN__)
bPload_mutex[j] = CreateMutex(NULL, FALSE, NULL);
#else
pthread_mutex_init(&bPload_mutex[j],NULL);
#endif
}
do {
for(j = 0; j < NTHREADS && !salir; j++) {
if(bPload_threads_available[j] && !salir) {
bPload_threads_available[j] = 0;
bPload_temp_ptr[j].from = BASE;
bPload_temp_ptr[j].threadid = j;
bPload_temp_ptr[j].finished = 0;
if( THREADCOUNTER < THREADCYCLES-1) {
bPload_temp_ptr[j].to = BASE + THREADBPWORKLOAD;
bPload_temp_ptr[j].workload = THREADBPWORKLOAD;
}
else {
bPload_temp_ptr[j].to = BASE + THREADBPWORKLOAD + PERTHREAD_R;
bPload_temp_ptr[j].workload = THREADBPWORKLOAD + PERTHREAD_R;
salir = 1;
}
#if defined(_WIN64) && !defined(__CYGWIN__)
tid[j] = CreateThread(NULL, 0, thread_bPload_2blooms, (void*) &bPload_temp_ptr[j], 0, &s);
#else
s = pthread_create(&tid[j],NULL,thread_bPload_2blooms,(void*) &bPload_temp_ptr[j]);
pthread_detach(tid[j]);
#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(j = 0 ; j < NTHREADS ; j++) {
#if defined(_WIN64) && !defined(__CYGWIN__)
WaitForSingleObject(bPload_mutex[j], INFINITE);
finished = bPload_temp_ptr[j].finished;
ReleaseMutex(bPload_mutex[j]);
#else
pthread_mutex_lock(&bPload_mutex[j]);
finished = bPload_temp_ptr[j].finished;
pthread_mutex_unlock(&bPload_mutex[j]);
#endif
if(finished) {
bPload_temp_ptr[j].finished = 0;
bPload_threads_available[j] = 1;
FINISHED_ITEMS += bPload_temp_ptr[j].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(j = 0; j < NTHREADS; j++) {
#if defined(_WIN64) && !defined(__CYGWIN__)
bPload_mutex = CreateMutex(NULL, FALSE, NULL);
#else
pthread_mutex_init(&bPload_mutex[j],NULL);
#endif
}
do {
for(j = 0; j < NTHREADS && !salir; j++) {
if(bPload_threads_available[j] && !salir) {
bPload_threads_available[j] = 0;
bPload_temp_ptr[j].from = BASE;
bPload_temp_ptr[j].threadid = j;
bPload_temp_ptr[j].finished = 0;
if( THREADCOUNTER < THREADCYCLES-1) {
bPload_temp_ptr[j].to = BASE + THREADBPWORKLOAD;
bPload_temp_ptr[j].workload = THREADBPWORKLOAD;
}
else {
bPload_temp_ptr[j].to = BASE + THREADBPWORKLOAD + PERTHREAD_R;
bPload_temp_ptr[j].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[j] = CreateThread(NULL, 0, thread_bPload, (void*) &bPload_temp_ptr[j], 0, &s);
#else
s = pthread_create(&tid[j],NULL,thread_bPload,(void*) &bPload_temp_ptr[j]);
pthread_detach(tid[j]);
#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(j = 0 ; j < NTHREADS ; j++) {
#if defined(_WIN64) && !defined(__CYGWIN__)
WaitForSingleObject(bPload_mutex[j], INFINITE);
finished = bPload_temp_ptr[j].finished;
ReleaseMutex(bPload_mutex[j]);
#else
pthread_mutex_lock(&bPload_mutex[j]);
finished = bPload_temp_ptr[j].finished;
pthread_mutex_unlock(&bPload_mutex[j]);
#endif
if(finished) {
bPload_temp_ptr[j].finished = 0;
bPload_threads_available[j] = 1;
FINISHED_ITEMS += bPload_temp_ptr[j].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(j= 0;j < NTHREADS; j++) {
tt = (tothread*) malloc(sizeof(struct tothread));
checkpointer((void *)tt,__FILE__,"malloc","tt" ,__LINE__ -1 );
tt->nt = j;
steps[j] = 0;
s = 0;
switch(FLAGBSGSMODE) {
#if defined(_WIN64) && !defined(__CYGWIN__)
case 0:
tid[j] = CreateThread(NULL, 0, thread_process_bsgs, (void*)tt, 0, &s);
break;
case 1:
tid[j] = CreateThread(NULL, 0, thread_process_bsgs_backward, (void*)tt, 0, &s);
break;
case 2:
tid[j] = CreateThread(NULL, 0, thread_process_bsgs_both, (void*)tt, 0, &s);
break;
case 3:
tid[j] = CreateThread(NULL, 0, thread_process_bsgs_random, (void*)tt, 0, &s);
break;
case 4:
tid[j] = CreateThread(NULL, 0, thread_process_bsgs_dance, (void*)tt, 0, &s);
break;
}
#else
case 0:
s = pthread_create(&tid[j],NULL,thread_process_bsgs,(void *)tt);
break;
case 1:
s = pthread_create(&tid[j],NULL,thread_process_bsgs_backward,(void *)tt);
break;
case 2:
s = pthread_create(&tid[j],NULL,thread_process_bsgs_both,(void *)tt);
break;
case 3:
s = pthread_create(&tid[j],NULL,thread_process_bsgs_random,(void *)tt);
break;
case 4:
s = pthread_create(&tid[j],NULL,thread_process_bsgs_dance,(void *)tt);
break;
#endif
}
#if defined(_WIN64) && !defined(__CYGWIN__)
if (tid[j] == NULL) {
#else
if(s != 0) {
#endif
fprintf(stderr,"[E] thread thread_process\n");
exit(EXIT_FAILURE);
}
}
free(aux);
}
if(FLAGMODE != MODE_BSGS) {
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(j= 0;j < NTHREADS; j++) {
tt = (tothread*) malloc(sizeof(struct tothread));
checkpointer((void *)tt,__FILE__,"malloc","tt" ,__LINE__ -1 );
tt->nt = j;
steps[j] = 0;
s = 0;
switch(FLAGMODE) {
#if defined(_WIN64) && !defined(__CYGWIN__)
case MODE_ADDRESS:
case MODE_XPOINT:
case MODE_RMD160:
tid[j] = CreateThread(NULL, 0, thread_process, (void*)tt, 0, &s);
break;
case MODE_MINIKEYS:
tid[j] = CreateThread(NULL, 0, thread_process_minikeys, (void*)tt, 0, &s);
break;
case MODE_VANITY:
tid[j] = CreateThread(NULL, 0, thread_process_vanity, (void*)tt, 0, &s);
break;
#else
case MODE_ADDRESS:
case MODE_XPOINT:
case MODE_RMD160:
s = pthread_create(&tid[j],NULL,thread_process,(void *)tt);
break;
case MODE_MINIKEYS:
s = pthread_create(&tid[j],NULL,thread_process_minikeys,(void *)tt);
break;
case MODE_VANITY:
s = pthread_create(&tid[j],NULL,thread_process_vanity,(void *)tt);
break;
#endif
}
if(s != 0) {
fprintf(stderr,"[E] pthread_create thread_process\n");
exit(EXIT_FAILURE);
}
}
}
for(j =0; j < 7; j++) {
int_limits[j].SetBase10((char*)str_limits[j]);
}
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(j = 0; j <NTHREADS && check_flag; j++) {
check_flag &= ends[j];
}
if(check_flag) {
continue_flag = 0;
}
if(OUTPUTSECONDS.IsGreater(&ZERO) ){
MPZAUX.Set(&seconds);
MPZAUX.Mod(&OUTPUTSECONDS);
if(MPZAUX.IsZero()) {
total.SetInt32(0);
for(j = 0; j < NTHREADS; j++) {
pretotal.Set(&debugcount_mpz);
pretotal.Mult(steps[j]);
total.Add(&pretotal);
}
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);
RMD160Data((const unsigned char*)digest,32, 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]
RMD160Data((const unsigned char*)digest,32, 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 address[4][40],minikey[4][24],minikeys[8][24],buffer_b58[21],minikey2check[24],rawvalue[4][32];
char *hextemp,*rawbuffer;
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) {
counter.Rand(256);
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 );
counter.Rand(256);
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 i,l,pp_offset,pn_offset,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 || FLAGCRYPTO == CRYPTO_ETH;
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);
}
/*
if(FLAGDEBUG) {
printf("\n[D] thread_process %i\n",__LINE__ -1 );
fflush(stdout);
}
*/
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 l,pp_offset,pn_offset,i,hLength = (CPU_GRP_SIZE / 2 - 1);
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);
}
}
/*
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);
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);
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-related variables
FILE* filekey;
struct tothread* tt;
// Character variables
char xpoint_raw[32], *aux_c, *hextemp;
// Integer variables
Int base_key, keyfound;
IntGroup* grp = new IntGroup(CPU_GRP_SIZE / 2 + 1);
Int dx[CPU_GRP_SIZE / 2 + 1];
Int dy, dyn, _s, _p, km, intaux;
// Point variables
Point base_point, point_aux, point_found;
Point startP;
Point pp, pn;
Point pts[CPU_GRP_SIZE];
// Unsigned integer variables
uint32_t k, l, r, salir, thread_number, cycles;
// Other variables
int hLength = (CPU_GRP_SIZE / 2 - 1);
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);
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
}
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 l,k,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);
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
}
void init_generator() {
Point G = secp->ComputePublicKey(&stride);
Point g;
g.Set(G);
Gn.reserve(CPU_GRP_SIZE / 2);
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(FLAGDEBUG){
tohex_dst(rawvalue,32,hexraw);
printf("%i : %s : %i\n",i_counter,hexraw,bloom_bP_index);
}
*/
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++;
}
//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
}
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_256(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
Point pts[CPU_GRP_SIZE];
Int dx[CPU_GRP_SIZE / 2 + 1];
Point pp,pn,startP,base_point,point_aux,point_found;
FILE *filekey;
struct tothread *tt;
char xpoint_raw[32],*aux_c,*hextemp;
Int base_key,keyfound,dy,dyn,_s,_p,km,intaux;
IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1);
uint32_t k,l,r,salir,thread_number,entrar,cycles;
int hLength = (CPU_GRP_SIZE / 2 - 1);
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);
}
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;
}
/* 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) {
uint32_t b0[16];
uint32_t b1[16];
uint32_t b2[16];
uint32_t b3[16];
BUFFMINIKEY(b0, src0);
BUFFMINIKEY(b1, src1);
BUFFMINIKEY(b2, src2);
BUFFMINIKEY(b3, src3);
sha256sse_1B(b0, b1, b2, b3, dst0, dst1, dst2, 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) {
uint32_t b0[16];
uint32_t b1[16];
uint32_t b2[16];
uint32_t b3[16];
BUFFMINIKEYCHECK(b0, src0);
BUFFMINIKEYCHECK(b1, src1);
BUFFMINIKEYCHECK(b2, src2);
BUFFMINIKEYCHECK(b3, src3);
sha256sse_1B(b0, b1, b2, b3, dst0, dst1, dst2, 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("-6 to skip sha256 Checksum on data files");
printf("-t tn Threads number, must be a positive integer\n");
printf("-v value Search for vanity Address, only with -m vanity\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++) {
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(FLAGDEBUG) {
hextemp = tohex((char*)checksum,32);
printf("[D] Current Bloom checksum %s\n",hextemp);
free(hextemp);
}
*/
if(memcmp(checksum,bloomChecksum,32) != 0) {
fprintf(stderr,"[E] Error checksum mismatch, code line %i\n",__LINE__ - 2);
fclose(fileDescriptor);
return false;
}
}
/*
if(FLAGDEBUG) {
hextemp = tohex((char*)bloom.bf,32);
printf("[D] first 32 bytes of the bloom : %s\n",hextemp);
bloom_print(&bloom);
printf("[D] bloom.bf points to %p\n",bloom.bf);
}
*/
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_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(".");
/*
if(FLAGDEBUG) {
hextemp = tohex((char*)bloom.bf,32);
printf("\n[D] first 32 bytes bloom : %s\n",hextemp);
bloom_print(&bloom);
free(hextemp);
}
*/
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);
}
}