From 8c455b543eb0faca665a8e30c991a072873d82f0 Mon Sep 17 00:00:00 2001 From: AlbertoBSD Date: Thu, 18 Mar 2021 11:00:36 +0100 Subject: [PATCH] Added mode rmd160, and param -l to seach exclusive compress or uncompress address/hash or bot (default behaivor) --- CHANGELOG.md | 4 + Makefile | 2 + TODO.md | 10 +- keyhunt.c | 2165 +++++++++++++++++++++++++++---------------------- sha3/keccak.c | 182 +++++ sha3/keccak.h | 34 + sha3/sha3.c | 674 +++++++++++++++ sha3/sha3.h | 88 ++ 8 files changed, 2186 insertions(+), 973 deletions(-) create mode 100644 sha3/keccak.c create mode 100644 sha3/keccak.h create mode 100644 sha3/sha3.c create mode 100644 sha3/sha3.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 42ef9cf..77b4ff5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +#Version 0.1.20210311 K*BSGS +- Added mode rmd160, this method works two times faster than Address method. This mode can search all the altcoins + + #Version 0.1.20210311 K*BSGS - Solved some bug when the publickeys in the input file was invalid but the program keeps running with 0 publickeys - Now publickeys can be compressed, not only uncompressed diff --git a/Makefile b/Makefile index 322c7e8..342e117 100644 --- a/Makefile +++ b/Makefile @@ -4,9 +4,11 @@ default: gcc -O3 -c sha256/sha256.c -o sha256.o gcc -O3 -c base58/base58.c -o base58.o gcc -O3 -c rmd160/rmd160.c -o rmd160.o + gcc -O3 -c sha3/sha3.c -o sha3.o gcc -O3 -c keyhunt.c -o keyhunt.o -lm gcc -o keyhunt keyhunt.o base58.o rmd160.o sha256.o bloom.o murmurhash2.o -lgmp -lm -lpthread gcc -O3 hexcharstoraw.c -o hexcharstoraw -lm gcc -o bPfile bPfile.c -lgmp -lm clean: rm -r *.o + diff --git a/TODO.md b/TODO.md index d464fd8..9be177c 100644 --- a/TODO.md +++ b/TODO.md @@ -1,17 +1,13 @@ #TODO -- Implement libkeccak at https://github.com/maandree/libkeccak - This is the only library that implement legacy keccak funtion (NOT SHA3) - See https://medium.com/@ConsenSys/are-you-really-using-sha-3-or-old-code-c5df31ad2b0 as reference - GPU support - Optimize Point Addition, maybe with a custom bignumber lib instead libgmp -- Fix a minor bug in Partition process of Introsort - fixing this will half the time of sorting data - Make a test files for All cases of input data with fixed ranges of search - address BTC legacy, bech32, ETH - - xpoint hexchars and binary - #DONE +- Added sha3 same files used by brainflayer +- Added mode rmd160 +- Fixed the bug in Partition process of Introsort - Fixed Quicksort edges cases (All data already sorted) To fix it Introsort was inmplement - Fixed bottleneck of Point - Scalar multiplication diff --git a/keyhunt.c b/keyhunt.c index 81e45a2..be3c563 100644 --- a/keyhunt.c +++ b/keyhunt.c @@ -16,6 +16,7 @@ email: alberto.bsd@gmail.com #include "rmd160/rmd160.h" #include "sha256/sha256.h" #include "bloom/bloom.h" +#include "sha3/sha3.h" #include "util.h" #define CRYPTO_NONE 0 @@ -26,6 +27,12 @@ email: alberto.bsd@gmail.com #define MODE_XPOINT 0 #define MODE_ADDRESS 1 #define MODE_BSGS 2 +#define MODE_RMD160 3 + +#define SEARCH_UNCOMPRESS 0 +#define SEARCH_COMPRESS 1 +#define SEARCH_BOTH 2 + struct Point { mpz_t x; @@ -34,7 +41,7 @@ struct Point { struct Elliptic_Curve { mpz_t p; - mpz_t n; + mpz_t n; }; struct bsgs_xvalue { @@ -43,12 +50,12 @@ struct bsgs_xvalue { }; struct tothread { - int nt; //Number thread - char *rs; //range start - char *rpt; //rng per thread + int nt; //Number thread + char *rs; //range start + char *rpt; //rng per thread }; -const char *version = "0.1.20210311 K*BSGS"; +const char *version = "0.1.20210318 K*BSGS"; const char *EC_constant_N = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"; const char *EC_constant_P = "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"; const char *EC_constant_Gx = "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"; @@ -66,7 +73,7 @@ void _insertionsort(char *arr, int n); void _introsort(char *arr,int depthLimit, int n); void swap(char *a,char *b); int partition(char *arr, int n); -void myheapsort(char *arr, int64_t n); +void myheapsort(char *arr, int64_t n); void heapify(char *arr, int n, int i); void bsgs_sort(struct bsgs_xvalue *arr,int64_t n); @@ -86,6 +93,7 @@ void *thread_process_bsgs(void *vargp); void *thread_process_bsgs_random(void *vargp); void init_doublingG(struct Point *P); +char *publickeytohashrmd160(char *pkey,int length); char *pubkeytopubaddress(char *pkey,int length); //char *pubkeytopubaddress_eth(char *pkey,int length); @@ -93,10 +101,11 @@ char *pubkeytopubaddress(char *pkey,int length); char *bit_range_str_min; char *bit_range_str_max; -const char *modes[3] = {"xpoint","address","bsgs"}; +const char *modes[4] = {"xpoint","address","bsgs","rmd160"}; const char *cryptos[3] = {"btc","eth","all"}; +const char *publicsearch[3] = {"compress","uncompress","both"}; const char *default_filename = "addresses.txt"; -const char *minus_params[2] = {"quiet","help"}; +//const char *minus_params[2] = {"quiet","help"}; pthread_t *tid = NULL; pthread_mutex_t write_keys; @@ -122,6 +131,7 @@ int KFACTOR = 1; int MAXLENGTHADDRESS = -1; int NTHREADS = 1; int OUTPUTSECONDS = 30; +int FLAGSEARCH = 2; int FLAGBITRANGE = 0; int FLAGRANGE = 0; int FLAGFILE = 0; @@ -129,7 +139,7 @@ int FLAGVANITY = 0; int FLAGMODE = MODE_ADDRESS; int FLAGCRYPTO = 0; int FLAGALREADYSORTED = 0; -int FLAGRAWDATA = 0; +int FLAGRAWDATA = 0; int FLAGRANDOM = 0; int FLAG_N = 0; int FLAGPRECALCUTED_P_FILE = 0; @@ -159,7 +169,7 @@ mpz_t BSGS_CURRENT; mpz_t BSGS_R; mpz_t BSGS_AUX; mpz_t BSGS_N; -mpz_t BSGS_M; //M is squareroot(N) +mpz_t BSGS_M; //M is squareroot(N) mpz_t TWO; mpz_t MPZAUX; struct Point BSGS_P; //Original P is actually G, but this P value change over time for calculations @@ -178,64 +188,63 @@ mpz_t n_range_r; int main(int argc, char **argv) { char temporal[65]; char rawvalue[32]; - struct tothread *tt; //tothread - Tokenizer t,tokenizerbsgs; //tokenizer - char *filename,*precalculated_p_filename,*precalculated_mp_filename; + struct tothread *tt; //tothread + Tokenizer t,tokenizerbsgs; //tokenizer + char *filename,*precalculated_p_filename,*precalculated_mp_filename; FILE *fd; - char *hextemp,*aux,*aux2,*pointx_str,*pointy_str; + char *hextemp,*aux,*aux2,*pointx_str,*pointy_str; uint64_t i; int64_t j; int readed,s,continue_flag,check_flag,r,lenaux,lendiff; - mpz_t total,pretotal,debugcount_mpz,Ysquared,mpz_aux,mpz_aux2; - + clock_t c_beging,c_ending; uint32_t seconds = 0; - int c; + int c; gmp_randinit_mt(state); gmp_randseed_ui(state, ((int)clock()) + ((int)time(NULL)) ); printf("[+] Version %s\n",version); - mpz_init_set_str(EC.p, EC_constant_P, 16); - mpz_init_set_str(EC.n, EC_constant_N, 16); + mpz_init_set_str(EC.p, EC_constant_P, 16); + mpz_init_set_str(EC.n, EC_constant_N, 16); mpz_init_set_str(G.x , EC_constant_Gx, 16); mpz_init_set_str(G.y , EC_constant_Gy, 16); init_doublingG(&G); mpz_init_set_ui(TWO,2); mpz_init(MPZAUX); - while ((c = getopt(argc, argv, "ehqRwb:c:f:g:k:m:n:p:r:s:t:v:-:")) != -1) { - switch(c) { + while ((c = getopt(argc, argv, "ehqRwb:c:f:g:k:l:m:n:p:r:s:t:v:-:")) != -1) { + switch(c) { case 'h': - printf("\nUsage:\n-h\t\tshow this help\n"); + printf("\nUsage:\n-h\t\tshow this help\n"); printf("-a file\t\tfile is a binary raw file with the aMP points precalculated. Just work with -m bsgs\n"); printf("-b bits\t\tFor some puzzles you only need some numbers of bits in the test keys.\n"); printf("\t\tThis option only is valid with the Random option -R\n"); printf("-c crypto\tSearch for specific crypo. < btc, eth, all > valid only w/ -m address \n"); - printf("\t\teth option is under develop sorry :(\n"); printf("-e\t\tThe file is already Sorted descendent. This skip the sorting process.\n"); printf("\t\tYour file MUST be sordted if no you are going to lose collisions\n"); - printf("-f file\t\tSpecify filename with addresses or xpoints or uncompressed public keys\n"); + printf("-f file\t\tSpecify filename with addresses or xpoints or uncompressed public keys\n"); printf("-g count\tJust for the stats, mark as counted every debugcount keys \n"); printf("-k value\tUse this with bsgs mode, k value is factor for M, more speed but more RAM use wisely\n"); - printf("-m mode\t\tmode of search for cryptos. < address, xpoint, bsgs > default: address (more slow)\n"); + printf("-l look\tWhat type of address/hash160 are you looking for < compress , uncompress , both>\n"); + printf("-m mode\t\tmode of search for cryptos. ( bsgs , xpoint , rmd160 , address ) default: address (more slow)\n"); printf("-n uptoN\tCheck for N secuential numbers before the random chossen this only work with -R option\n"); printf("\t\tUse -n to set the N for the BSGS process. Bigger N more RAM needed\n"); printf("-p file\t\tfile is a binary raw file with the bP points precalculated. Just work with -m bsgs\n"); printf("-q\t\tset quiet the thread output\n"); - printf("-r SR:EN\tStarRange:EndRange, the end range can be omited for search from start range to N-1 ECC value\n"); - printf("-R\t\tRandom/Secuential this is the default behaivor, can't use this with range option -r\n"); - printf("-s ns\t\tNumber of seconds for the stats output, 0 to omit output.\n"); - printf("-t tn\t\tThreads number, must be positive integer\n"); + printf("-r SR:EN\tStarRange:EndRange, the end range can be omited for search from start range to N-1 ECC value\n"); + printf("-R\t\tRandom this is the default behaivor\n"); + printf("-s ns\t\tNumber of seconds for the stats output, 0 to omit output.\n"); + printf("-t tn\t\tThreads number, must be positive integer\n"); printf("-v va\t\tSearch for vanity Address, only with -m address\n"); printf("-w\t\tMark the input file as RAW data xpoint fixed 32 byte each point. Valid only with -m xpoint\n"); printf("\t\tUse the hexcharstoraw tool to create a raw file from your current hexadecimal file\n"); - printf("\nExample\n\n"); - printf("%s -t 16 -r 00000001:FFFFFFFF -s 0\n\n",argv[0]); - printf("This line run the program with 16 threads from the range 00000001 to FFFFFFFF without stats output\n\n"); - printf("Developed by AlbertoBSD\tTips BTC: 1ABSD1rMTmNZHJrJP8AJhDNG1XbQjWcRz7\n"); + printf("\nExample\n\n"); + printf("%s -t 16 -r 00000001:FFFFFFFF -s 0\n\n",argv[0]); + printf("This line run the program with 16 threads from the range 00000001 to FFFFFFFF without stats output\n\n"); + printf("Developed by AlbertoBSD\tTips BTC: 1ABSD1rMTmNZHJrJP8AJhDNG1XbQjWcRz7\n"); printf("Thanks to Iceland always helping and sharing his ideas, Tips to Iceland: bc1q39meky2mn5qjq704zz0nnkl0v7kj4uz6r529at\n\n"); - exit(0); - break; + exit(0); + break; case 'a': FLAGPRECALCUTED_MP_FILE = 1; precalculated_mp_filename = optarg; @@ -258,44 +267,44 @@ int main(int argc, char **argv) { printf("[+] Max range: %s\n",bit_range_str_max); FLAGBITRANGE = 1; } - else { + else { fprintf(stderr,"[E] invalid bits param: %s.\n",optarg); } - break; - case 'c': - switch(indexOf(optarg,cryptos,3)) { - case 0: //btc - FLAGCRYPTO = CRYPTO_BTC; - printf("[+] Setting search for btc adddress.\n"); - break; - case 1: //eth - FLAGCRYPTO = CRYPTO_ETH; - printf("[+] Setting search for eth adddress.\n"); - break; - case 2: //all - FLAGCRYPTO = CRYPTO_ALL; - printf("[+] Setting search for all cryptocurrencies avaible [btc].\n"); - break; - default: - FLAGCRYPTO = CRYPTO_NONE; - fprintf(stderr,"[E] Unknow crypto value %s\n",optarg); - break; - } - break; + break; + case 'c': + switch(indexOf(optarg,cryptos,3)) { + case 0: //btc + FLAGCRYPTO = CRYPTO_BTC; + printf("[+] Setting search for btc adddress.\n"); + break; + case 1: //eth + FLAGCRYPTO = CRYPTO_ETH; + printf("[+] Setting search for eth adddress.\n"); + break; + case 2: //all + FLAGCRYPTO = CRYPTO_ALL; + printf("[+] Setting search for all cryptocurrencies avaible [btc].\n"); + break; + default: + FLAGCRYPTO = CRYPTO_NONE; + fprintf(stderr,"[E] Unknow crypto value %s\n",optarg); + break; + } + break; case 'e': FLAGALREADYSORTED = 1; break; case 'f': - FLAGFILE = 1; - filename = optarg; - break; + FLAGFILE = 1; + filename = optarg; + break; case 'g': - DEBUGCOUNT = strtol(optarg,NULL,10); + DEBUGCOUNT = strtol(optarg,NULL,10); if(DEBUGCOUNT == 0) { DEBUGCOUNT = 0x100000; fprintf(stderr,"[E] invalid -g option value: %s.\n",optarg); } - break; + break; case 'k': KFACTOR = (int)strtol(optarg,NULL,10); if(KFACTOR <= 0) { @@ -303,26 +312,47 @@ int main(int argc, char **argv) { } printf("[+] Setting k factor to %i\n",KFACTOR); break; - case 'm': - switch(indexOf(optarg,modes,3)) { - case MODE_XPOINT: //xpoint - FLAGMODE = MODE_XPOINT; - printf("[+] Setting mode xpoint\n"); - break; - case MODE_ADDRESS: //address - FLAGMODE = MODE_ADDRESS; - printf("[+] Setting mode address\n"); - 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': + switch(indexOf(optarg,modes,4)) { + case MODE_XPOINT: //xpoint + FLAGMODE = MODE_XPOINT; + printf("[+] Setting mode xpoint\n"); + break; + case MODE_ADDRESS: //address + FLAGMODE = MODE_ADDRESS; + printf("[+] Setting mode address\n"); + break; case MODE_BSGS: FLAGMODE = MODE_BSGS; printf("[+] Setting mode BSGS\n"); break; - default: - FLAGMODE = MODE_ADDRESS; - fprintf(stderr,"[+] Unknow mode value %s.\n",optarg); - break; - } - break; + case MODE_RMD160: + FLAGMODE = MODE_RMD160; + printf("[+] Setting mode rmd160\n"); + break; + default: + FLAGMODE = MODE_ADDRESS; + fprintf(stderr,"[+] Unknow mode value %s.\n",optarg); + break; + } + break; case 'n': FLAG_N = 1; N_SECUENTIAL_MAX = strtol(optarg,NULL,10); @@ -332,7 +362,7 @@ int main(int argc, char **argv) { } break; case 'q': - FLAGQUIET = 1; + FLAGQUIET = 1; printf("[+] Set quiet thread output\n"); break; case 'p': @@ -343,74 +373,74 @@ int main(int argc, char **argv) { FLAGRANDOM = 1; printf("[+] Setting random mode.\n"); 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 = (char*) EC_constant_N; - } - 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)) { - printf("[E] Invalid hexstring : %s\n",range_start); - } - else { - printf("[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 = strtol(optarg,NULL,10); - if(OUTPUTSECONDS < 0) { - OUTPUTSECONDS = 30; - } - if(OUTPUTSECONDS == 0) { - printf("[+] Turn off stats output\n"); - } - else { - printf("[+] Stats output every %u seconds\n",OUTPUTSECONDS); - } - 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 = (char*) EC_constant_N; + } + 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)) { + printf("[E] Invalid hexstring : %s\n",range_start); + } + else { + printf("[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 = strtol(optarg,NULL,10); + if(OUTPUTSECONDS < 0) { + OUTPUTSECONDS = 30; + } + if(OUTPUTSECONDS == 0) { + printf("[+] Turn off stats output\n"); + } + else { + printf("[+] Stats output every %u seconds\n",OUTPUTSECONDS); + } + break; case 't': - NTHREADS = strtol(optarg,NULL,10); - if(NTHREADS <= 0) { - NTHREADS = 1; - } - printf((NTHREADS > 1) ? "[+] Setting %u threads\n": "[+] Setting %u thread\n",NTHREADS); - break; + NTHREADS = strtol(optarg,NULL,10); + if(NTHREADS <= 0) { + NTHREADS = 1; + } + printf((NTHREADS > 1) ? "[+] Setting %u threads\n": "[+] Setting %u thread\n",NTHREADS); + break; case 'v': - FLAGVANITY = 1; - vanity = optarg; - len_vanity = strlen(optarg); + FLAGVANITY = 1; + vanity = optarg; + len_vanity = strlen(optarg); printf("[+] Added Vanity search : %s\n",vanity); - break; + break; case 'w': printf("[+] Data marked as RAW\n"); FLAGRAWDATA = 1; - break; + break; + /* case '-': switch(indexOf(optarg,minus_params,2)) { case 0: //--quiet - FLAGQUIET = 1; + FLAGQUIET = 1; printf("[+] Set quiet thread output\n"); break; case 1: // --help @@ -420,16 +450,17 @@ int main(int argc, char **argv) { break; } break; - default: - printf("[E] Unknow opcion %c\n",c); - break; - } - } + */ + default: + printf("[E] Unknow opcion %c\n",c); + break; + } + } - if(FLAGMODE != MODE_BSGS && FLAGRANDOM == 1) { + if(FLAGMODE != MODE_BSGS && FLAGRANDOM == 1) { FLAGRANGE = 0; } - if(DEBUGCOUNT > N_SECUENTIAL_MAX) { + if(DEBUGCOUNT > N_SECUENTIAL_MAX) { DEBUGCOUNT = N_SECUENTIAL_MAX - 1; } @@ -438,85 +469,121 @@ int main(int argc, char **argv) { } printf("[+] Opening file %s\n",filename); fd = fopen(filename,"rb"); - if(fd == NULL) { - fprintf(stderr,"[E] Can't open file %s\n",filename); - exit(0); - } - 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) { - mpz_init_set_str(n_range_start,range_start,16); - mpz_init_set_str(n_range_end,range_end,16); - if(mpz_cmp(n_range_start,n_range_end) != 0 ) { - if(mpz_cmp(n_range_start,EC.n) < 0 && mpz_cmp(n_range_end,EC.n) <= 0) { - if(mpz_cmp(n_range_start,n_range_end) > 0) { - fprintf(stderr,"[W] Opps, start and range can't be great than End range. Swapping them\n"); - mpz_init_set(n_range_aux,n_range_start); - mpz_set(n_range_start,n_range_end); - mpz_set(n_range_end,n_range_aux); - mpz_clear(n_range_aux); - } - mpz_init(n_range_per_threads); - mpz_init(n_range_diff); - mpz_init(n_range_r); - mpz_sub(n_range_diff,n_range_end,n_range_start); - mpz_fdiv_q_ui(n_range_per_threads,n_range_diff,NTHREADS); - mpz_mod_ui(n_range_r,n_range_diff,NTHREADS); - } - 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; - } - } - N =0; - if(FLAGMODE != MODE_BSGS) { - if(FLAGRAWDATA) { - aux = malloc(32); - if(aux == NULL) { - fprintf(stderr,"[E] error malloc()\n"); - } - while(!feof(fd)) { - if(fread(aux,1,32,fd) == 32) { - N++; + if(fd == NULL) { + fprintf(stderr,"[E] Can't open file %s\n",filename); + exit(0); + } + 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) { + mpz_init_set_str(n_range_start,range_start,16); + mpz_init_set_str(n_range_end,range_end,16); + if(mpz_cmp(n_range_start,n_range_end) != 0 ) { + if(mpz_cmp(n_range_start,EC.n) < 0 && mpz_cmp(n_range_end,EC.n) <= 0) { + if(mpz_cmp(n_range_start,n_range_end) > 0) { + fprintf(stderr,"[W] Opps, start and range can't be great than End range. Swapping them\n"); + mpz_init_set(n_range_aux,n_range_start); + mpz_set(n_range_start,n_range_end); + mpz_set(n_range_end,n_range_aux); + mpz_clear(n_range_aux); } + mpz_init(n_range_per_threads); + mpz_init(n_range_diff); + mpz_init(n_range_r); + mpz_sub(n_range_diff,n_range_end,n_range_start); + mpz_fdiv_q_ui(n_range_per_threads,n_range_diff,NTHREADS); + mpz_mod_ui(n_range_r,n_range_diff,NTHREADS); + } + else { + fprintf(stderr,"[E] Start and End range can't be great than N\nFallback to random mode!\n"); + FLAGRANGE = 0; } - free(aux); } else { - aux = malloc(1000); - if(aux == NULL) { - fprintf(stderr,"[E] error malloc()\n"); - } - while(!feof(fd)) { - hextemp = fgets(aux,1000,fd); - if(hextemp == aux) { - trim(aux," \t\n\r"); - r = strlen(aux); - if(r > 10) { //Any length for invalid Address? - if(r > MAXLENGTHADDRESS) { - MAXLENGTHADDRESS = r; - } - N++; - } + fprintf(stderr,"[E] Start and End range can't be the same\nFallback to random mode!\n"); + FLAGRANGE = 0; + } + } + N =0; + if(FLAGMODE != MODE_BSGS) { + aux = malloc(1000); + if(aux == NULL) { + fprintf(stderr,"[E] error malloc()\n"); + } + switch(FLAGMODE) { + case MODE_ADDRESS: + while(!feof(fd)) { + hextemp = fgets(aux,998,fd); + if(hextemp == aux) { + trim(aux," \t\n\r"); + r = strlen(aux); + if(r > 10) { //Any length for invalid Address? + if(r > MAXLENGTHADDRESS) { + MAXLENGTHADDRESS = r; + } + N++; + } + } } - } - free(aux); + MAXLENGTHADDRESS = 32; + break; + case MODE_RMD160: + if(FLAGRAWDATA) { + while(!feof(fd)) { + if(fread(aux,1,20,fd) == 20) { + N++; + } + } + } + else { + while(!feof(fd)) { + hextemp = fgets(aux,998,fd); + if(hextemp == aux) { + trim(aux," \t\n\r"); + r = strlen(aux); + if(r == 40) { //Any length for invalid Address? + N++; + } + } + } + } + MAXLENGTHADDRESS = 20; + break; + case MODE_XPOINT: + if(FLAGRAWDATA) { + while(!feof(fd)) { + if(fread(aux,1,32,fd) == 32) { + N++; + } + } + } + else { + while(!feof(fd)) { + hextemp = fgets(aux,998,fd); + if(hextemp == aux) { + trim(aux," \t\n\r"); + r = strlen(aux); + if(r > 10) { //Any length for invalid Address? + N++; + } + } + } + } + MAXLENGTHADDRESS = 32; + break; } - fseek(fd,0,SEEK_SET); - if(FLAGMODE == 0 || FLAGRAWDATA) { - MAXLENGTHADDRESS = 32; - } + free(aux); + if(N == 0) { + fprintf(stderr,"[E] There is no valid data in the file\n"); + exit(0); + } + fseek(fd,0,SEEK_SET); - printf("[+] Allocating memory for %u elements\n",N); + printf("[+] Allocating memory for %u elements: %.2f MB\n",N,(MAXLENGTHADDRESS*N)/1048576); i = 0; - do { + do { DATABUFFER = malloc(MAXLENGTHADDRESS*N); i++; } while(DATABUFFER == NULL && i < 10); @@ -524,109 +591,166 @@ int main(int argc, char **argv) { fprintf(stderr,"[E] Can't alloc memory for %u elements\n",N); exit(0); } - printf("[+] Initializing bloom filter for %u elements.\n",N); + printf("[+] Initializing bloom filter for %u elements.\n",N); if(N <= 10000) { - if(bloom_init2(&bloom,10000,0.00001) == 1){ + if(bloom_init2(&bloom,10000,0.00001) == 1){ fprintf(stderr,"[E] error bloom_init for 10000 elements.\n"); exit(0); } } else { - if(bloom_init2(&bloom,N,0.00001) == 1){ + if(bloom_init2(&bloom,N,0.00001) == 1){ fprintf(stderr,"[E] error bloom_init for %u elements.\n",N); fprintf(stderr,"[+] man enough is enough stop it\n"); exit(0); } } - printf("[+] Loading data to the bloomfilter\n"); + printf("[+] Loading data to the bloomfilter\n"); i = 0; - if(FLAGMODE == MODE_ADDRESS) { //Address - aux = malloc(2*MAXLENGTHADDRESS); - if(aux == NULL) { - fprintf(stderr,"[E] error malloc()\n"); - exit(0); - } - while(i < N) { - memset(aux,0,2*MAXLENGTHADDRESS); - memset(DATABUFFER + (i*MAXLENGTHADDRESS),0,MAXLENGTHADDRESS); - hextemp = fgets(aux,2*MAXLENGTHADDRESS,fd); - if(hextemp == aux) { - trim(aux," \t\n\r"); - bloom_add(&bloom, aux,MAXLENGTHADDRESS); - memcpy(DATABUFFER + (i*MAXLENGTHADDRESS),aux,MAXLENGTHADDRESS); - i++; - } - else { - trim(aux," \t\n\r"); - fprintf(stderr,"[E] Omiting line : %s\n",aux); - } - } - } - if(FLAGMODE == MODE_XPOINT) { - if(FLAGRAWDATA) { - aux = malloc(MAXLENGTHADDRESS); + switch (FLAGMODE) { + case MODE_ADDRESS: + aux = malloc(2*MAXLENGTHADDRESS); if(aux == NULL) { fprintf(stderr,"[E] error malloc()\n"); exit(0); } - while(i < N) { - if(fread(aux,1,MAXLENGTHADDRESS,fd) == 32) { - memcpy(DATABUFFER + (i*MAXLENGTHADDRESS),aux,MAXLENGTHADDRESS); + while(i < N) { + memset(aux,0,2*MAXLENGTHADDRESS); + memset(DATABUFFER + (i*MAXLENGTHADDRESS),0,MAXLENGTHADDRESS); + hextemp = fgets(aux,2*MAXLENGTHADDRESS,fd); + if(hextemp == aux) { + trim(aux," \t\n\r"); bloom_add(&bloom, aux,MAXLENGTHADDRESS); + memcpy(DATABUFFER + (i*MAXLENGTHADDRESS),aux,MAXLENGTHADDRESS); + i++; + } + else { + trim(aux," \t\n\r"); + fprintf(stderr,"[E] Omiting line : %s\n",aux); } - i++; } - } - else { - aux = malloc(3*MAXLENGTHADDRESS); - if(aux == NULL) { - fprintf(stderr,"[E] error malloc()\n"); - exit(0); + break; + case MODE_XPOINT: + if(FLAGRAWDATA) { + aux = malloc(MAXLENGTHADDRESS); + if(aux == NULL) { + fprintf(stderr,"[E] error malloc()\n"); + exit(0); + } + while(i < N) { + if(fread(aux,1,MAXLENGTHADDRESS,fd) == 32) { + memcpy(DATABUFFER + (i*MAXLENGTHADDRESS),aux,MAXLENGTHADDRESS); + bloom_add(&bloom, aux,MAXLENGTHADDRESS); + } + i++; + } } - while(i < N) { - memset(aux,0,3*MAXLENGTHADDRESS); - hextemp = fgets(aux,3*MAXLENGTHADDRESS,fd); - if(hextemp == aux) { - trim(aux," \t\n\r"); - lenaux = strlen(aux); + else { + aux = malloc(3*MAXLENGTHADDRESS); + if(aux == NULL) { + fprintf(stderr,"[E] error malloc()\n"); + exit(0); + } + while(i < N) { + memset(aux,0,3*MAXLENGTHADDRESS); + hextemp = fgets(aux,3*MAXLENGTHADDRESS,fd); memset(DATABUFFER + (i*MAXLENGTHADDRESS),0,MAXLENGTHADDRESS); - if(isValidHex(aux)) { - if(lenaux <= 64) { - if(lenaux < 64) { - aux2 = calloc(3*MAXLENGTHADDRESS,1); - lendiff = 64 - lenaux; - memcpy(aux2+lendiff,aux,lenaux); - memset(aux2,'0',lendiff); - memcpy(aux,aux2,3*MAXLENGTHADDRESS); - free(aux2); - } - if(hexs2bin(aux,(unsigned char*)(DATABUFFER + (uint64_t)(i*MAXLENGTHADDRESS)))) { - bloom_add(&bloom,(char*)( DATABUFFER + (uint64_t)(i*MAXLENGTHADDRESS)),MAXLENGTHADDRESS); + if(hextemp == aux) { + trim(aux," \t\n\r"); + lenaux = strlen(aux); + + if(isValidHex(aux)) { + if(lenaux <= 64) { + if(lenaux < 64) { + aux2 = calloc(3*MAXLENGTHADDRESS,1); + lendiff = 64 - lenaux; + memcpy(aux2+lendiff,aux,lenaux); + memset(aux2,'0',lendiff); + memcpy(aux,aux2,3*MAXLENGTHADDRESS); + free(aux2); + } + if(hexs2bin(aux,(unsigned char*)(DATABUFFER + (uint64_t)(i*MAXLENGTHADDRESS)))) { + bloom_add(&bloom,(char*)( DATABUFFER + (uint64_t)(i*MAXLENGTHADDRESS)),MAXLENGTHADDRESS); + } + else { + fprintf(stderr,"[E] error hexs2bin\n"); + } } else { - fprintf(stderr,"[E] error hexs2bin\n"); + fprintf(stderr,"[E] Omiting line : %s\n",aux); } } else { - fprintf(stderr,"[E] Omiting line : %s\n",aux); + fprintf(stderr,"[E] Ignoring invalid hexvalue %s\n",aux); } - } - else { - fprintf(stderr,"[E] Ignoring invalid hexvalue %s\n",aux); - } - i++; + } + else { + fprintf(stderr,"[E] Omiting line : %s\n",aux); + N--; + } + i++; } - else { - fprintf(stderr,"[E] Omiting line : %s\n",aux); + } + break; + case MODE_RMD160: + if(FLAGRAWDATA) { + aux = malloc(MAXLENGTHADDRESS); + if(aux == NULL) { + fprintf(stderr,"[E] error malloc()\n"); + exit(0); } - } - } - } + while(i < N) { + if(fread(aux,1,MAXLENGTHADDRESS,fd) == 20) { + memcpy(DATABUFFER + (i*MAXLENGTHADDRESS),aux,MAXLENGTHADDRESS); + bloom_add(&bloom, aux,MAXLENGTHADDRESS); + } + i++; + } + } + else { + aux = malloc(3*MAXLENGTHADDRESS); + if(aux == NULL) { + fprintf(stderr,"[E] error malloc()\n"); + exit(0); + } + while(i < N) { + memset(aux,0,3*MAXLENGTHADDRESS); + hextemp = fgets(aux,3*MAXLENGTHADDRESS,fd); + memset(DATABUFFER + (i*MAXLENGTHADDRESS),0,MAXLENGTHADDRESS); + if(hextemp == aux) { + trim(aux," \t\n\r"); + lenaux = strlen(aux); + if(isValidHex(aux)) { + if(lenaux == 40) { + if(hexs2bin(aux,(unsigned char*)(DATABUFFER + (uint64_t)(i*MAXLENGTHADDRESS)))) { + bloom_add(&bloom,(char*)( DATABUFFER + (uint64_t)(i*MAXLENGTHADDRESS)),MAXLENGTHADDRESS); + } + else { + fprintf(stderr,"[E] error hexs2bin\n"); + } + } + else { + fprintf(stderr,"[E] Ignoring invalid length line %s\n",aux); + } + } + else { + fprintf(stderr,"[E] Ignoring invalid hexvalue %s\n",aux); + } + } + else { + fprintf(stderr,"[E] Omiting line : %s\n",aux); + } + i++; + } + } + break; + } + free(aux); - fclose(fd); + fclose(fd); printf("[+] Bloomfilter completed\n"); if(FLAGALREADYSORTED) { - printf("[+] File mark already sorted, skipping sort proccess\n"); + printf("[+] File mark already sorted, skipping sort proccess\n"); printf("[+] %i values were loaded\n",N); _sort(DATABUFFER,N); _insertionsort(DATABUFFER,N); @@ -645,7 +769,7 @@ int main(int argc, char **argv) { fprintf(stderr,"[E] error malloc()\n"); exit(0); } - while(!feof(fd)) { + 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 @@ -675,7 +799,7 @@ int main(int argc, char **argv) { mpz_init(mpz_aux); mpz_init(mpz_aux2); i = 0; - while(!feof(fd)) { + while(!feof(fd)) { if(fgets(aux,1022,fd) == aux) { trim(aux," \t\n\r"); if(strlen(aux) >= 66) { @@ -840,13 +964,13 @@ int main(int argc, char **argv) { printf("[+] Setting N up to %llu.\n",(long long unsigned int)DEBUGCOUNT); if(bsgs_m > 1000) { - if(bloom_init2(&bloom_bPx,bsgs_m,0.00001) == 1){ + if(bloom_init2(&bloom_bPx,bsgs_m,0.00001) == 1){ fprintf(stderr,"[E] error bloom_init for %lu elements\n",bsgs_m); exit(0); } } else { - if(bloom_init2(&bloom_bPx,1000,0.00001) == 1){ + if(bloom_init2(&bloom_bPx,1000,0.00001) == 1){ fprintf(stderr,"[E] error bloom_init for 1000 elements\n"); exit(0); } @@ -935,15 +1059,7 @@ int main(int argc, char **argv) { if(fd != NULL) { while(!feof(fd) && i < bsgs_m ) { if(fread(rawvalue,1,32,fd) == 32) { - //memcpy(bPtable[i].value,rawvalue,BSGS_XVALUE_RAM); - bPtable[i].value[0] = rawvalue[6]; - bPtable[i].value[1] = rawvalue[7]; - bPtable[i].value[2] = rawvalue[14]; - bPtable[i].value[3] = rawvalue[15]; - bPtable[i].value[4] = rawvalue[22]; - bPtable[i].value[5] = rawvalue[23]; - bPtable[i].value[6] = rawvalue[30]; - bPtable[i].value[7] = rawvalue[31]; + memcpy(bPtable[i].value,rawvalue,BSGS_XVALUE_RAM); bPtable[i].index = j; bloom_add(&bloom_bPx, rawvalue, BSGS_BUFFERXPOINTLENGTH); @@ -964,16 +1080,7 @@ int main(int argc, char **argv) { mpz_set(point_temp.y,BSGS_P.y); gmp_sprintf(temporal,"%0.64Zx",BSGS_P.x); hexs2bin(temporal,rawvalue); - //memcpy(bPtable[i].value,rawvalue,4); - bPtable[i].value[0] = rawvalue[6]; - bPtable[i].value[1] = rawvalue[7]; - bPtable[i].value[2] = rawvalue[14]; - bPtable[i].value[3] = rawvalue[15]; - bPtable[i].value[4] = rawvalue[22]; - bPtable[i].value[5] = rawvalue[23]; - bPtable[i].value[6] = rawvalue[30]; - bPtable[i].value[7] = rawvalue[31]; - + memcpy(bPtable[i].value,rawvalue,BSGS_XVALUE_RAM); bPtable[i].index = j; bloom_add(&bloom_bPx, rawvalue,BSGS_BUFFERXPOINTLENGTH); Point_Addition(&G,&point_temp,&BSGS_P); @@ -989,15 +1096,7 @@ int main(int argc, char **argv) { mpz_set(point_temp.y,BSGS_P.y); gmp_sprintf(temporal,"%0.64Zx",BSGS_P.x); hexs2bin(temporal, rawvalue ); - //memcpy(bPtable[i].value,rawvalue,BSGS_XVALUE_RAM); - bPtable[i].value[0] = rawvalue[6]; - bPtable[i].value[1] = rawvalue[7]; - bPtable[i].value[2] = rawvalue[14]; - bPtable[i].value[3] = rawvalue[15]; - bPtable[i].value[4] = rawvalue[22]; - bPtable[i].value[5] = rawvalue[23]; - bPtable[i].value[6] = rawvalue[30]; - bPtable[i].value[7] = rawvalue[31]; + memcpy(bPtable[i].value,rawvalue,BSGS_XVALUE_RAM); bPtable[i].index = j; bloom_add(&bloom_bPx, rawvalue ,BSGS_BUFFERXPOINTLENGTH); Point_Addition(&G,&point_temp,&BSGS_P); @@ -1006,15 +1105,20 @@ int main(int argc, char **argv) { } while( i < bsgs_m ); } printf("[+] Sorting %lu elements\n",bsgs_m); + c_beging = clock(); bsgs_sort(bPtable,bsgs_m); + c_ending = clock(); + double time_spent = (double)(c_ending-c_beging) / CLOCKS_PER_SEC; + printf("[+] Sorted %lu elements in %f seconds\n",bsgs_m ,time_spent); + i = 0; steps = (unsigned int *) calloc(NTHREADS,sizeof(int)); - ends = (unsigned int *) calloc(NTHREADS,sizeof(int)); + ends = (unsigned int *) calloc(NTHREADS,sizeof(int)); tid = (pthread_t *) calloc(NTHREADS,sizeof(pthread_t)); DEBUGCOUNT = (uint64_t)((uint64_t)bsgs_m * (uint64_t)bsgs_aux); //DEBUGCOUNT = (uint64_t)((uint64_t)bsgs_m * (uint64_t)bsgs_m); - for(i= 0;i < NTHREADS; i++) { + for(i= 0;i < NTHREADS; i++) { tt = malloc(sizeof(struct tothread)); tt->nt = i; if(FLAGRANDOM) { @@ -1024,7 +1128,7 @@ int main(int argc, char **argv) { s = pthread_create(&tid[i],NULL,thread_process_bsgs,(void *)tt); } - if(s != 0) { + if(s != 0) { fprintf(stderr,"[E] pthread_create thread_process\n"); exit(0); } @@ -1033,95 +1137,87 @@ int main(int argc, char **argv) { } if(FLAGMODE != MODE_BSGS) { steps = (unsigned int *) calloc(NTHREADS,sizeof(int)); - ends = (unsigned int *) calloc(NTHREADS,sizeof(int)); + ends = (unsigned int *) calloc(NTHREADS,sizeof(int)); tid = (pthread_t *) calloc(NTHREADS,sizeof(pthread_t)); - if(FLAGRANGE == 0) { - for(i= 0;i < NTHREADS; i++) { - tt = malloc(sizeof(struct tothread)); - tt->nt = i; - steps[i] = 0; - s = pthread_create(&tid[i],NULL,thread_process,(void *)tt); - if(s != 0) { - fprintf(stderr,"[E] pthread_create thread_process\n"); + if(FLAGRANGE == 0) { + for(i= 0;i < NTHREADS; i++) { + tt = malloc(sizeof(struct tothread)); + tt->nt = i; + steps[i] = 0; + s = pthread_create(&tid[i],NULL,thread_process,(void *)tt); + if(s != 0) { + fprintf(stderr,"[E] pthread_create thread_process\n"); exit(0); - } - } - } - else { - for(i= 0;i < NTHREADS; i++) { - if(i == (NTHREADS)-1) { - mpz_add(n_range_per_threads,n_range_per_threads,n_range_r); - } - tt = malloc(sizeof(struct tothread)); - tt->nt = i; - tt->rs = malloc(65); - mpz_get_str(tt->rs,16,n_range_start); - - tt->rpt = malloc(65); - mpz_get_str(tt->rpt,16,n_range_per_threads); - - steps[i] = 0; + } + } + } + else { + for(i= 0;i < NTHREADS; i++) { + if(i == (NTHREADS)-1) { + mpz_add(n_range_per_threads,n_range_per_threads,n_range_r); + } + tt = malloc(sizeof(struct tothread)); + tt->nt = i; + tt->rs = malloc(65); + mpz_get_str(tt->rs,16,n_range_start); + + tt->rpt = malloc(65); + mpz_get_str(tt->rpt,16,n_range_per_threads); + + steps[i] = 0; s = pthread_create(&tid[i],NULL,thread_process_range,(void *)tt); - if(s != 0) { - fprintf(stderr,"[E] pthread_create thread_process\n"); + if(s != 0) { + fprintf(stderr,"[E] pthread_create thread_process\n"); exit(0); - } - mpz_add(n_range_start,n_range_start,n_range_per_threads); - } - } - if(FLAGRANGE) { - mpz_clear(n_range_per_threads); - mpz_clear(n_range_start); - mpz_clear(n_range_end); - mpz_clear(n_range_diff); - mpz_clear(n_range_r); - } + } + mpz_add(n_range_start,n_range_start,n_range_per_threads); + } + } + if(FLAGRANGE) { + mpz_clear(n_range_per_threads); + mpz_clear(n_range_start); + mpz_clear(n_range_end); + mpz_clear(n_range_diff); + mpz_clear(n_range_r); + } } - continue_flag = 1; + continue_flag = 1; mpz_init(total); mpz_init(pretotal); mpz_init(debugcount_mpz); sprintf(temporal,"%llu",(long long unsigned int)DEBUGCOUNT); mpz_set_str(debugcount_mpz,temporal,10); - /* - printf("DEBUGCOUNT: %llu\n",DEBUGCOUNT); - gmp_printf("debugcount_mpz: %Zu\n",debugcount_mpz); - printf("NTHREADS: %i\n",NTHREADS); - */ - do { - sleep(1); - seconds+=1; - if(FLAGMODE != MODE_BSGS && FLAGRANGE) { - check_flag = 1; - pthread_mutex_lock(&threads_end); - for(i = 0; i 0){ - if(seconds % OUTPUTSECONDS == 0) { + + do { + sleep(1); + seconds+=1; + check_flag = 1; + for(i = 0; i 0){ + if(seconds % OUTPUTSECONDS == 0) { mpz_set_ui(total,0); mpz_set_ui(pretotal,0); - i = 0; - while(i < NTHREADS) { + i = 0; + while(i < NTHREADS) { mpz_mul_ui(pretotal,debugcount_mpz,steps[i]); mpz_add(total,total,pretotal); - i++; - } + i++; + } if(mpz_cmp_ui(total,0) > 0) { mpz_fdiv_q_ui(pretotal,total,seconds); pthread_mutex_lock(&bsgs_thread); gmp_printf("Total %Zu keys in %llu seconds: %Zu keys/s\n",total,seconds,pretotal); pthread_mutex_unlock(&bsgs_thread); } - } - } - }while(continue_flag); + } + } + }while(continue_flag); } void Point_Doubling(struct Point *P, struct Point *R) { @@ -1190,7 +1286,7 @@ void Point_Addition(struct Point *P, struct Point *Q, struct Point *R) { mpz_mod(PA_slope, PA_slope, EC.p); mpz_mul(R->x, PA_slope, PA_slope); //c*c mpz_sub(R->x, R->x, P->x); // c*c - A.x - mpz_sub(R->x, R->x, Q->x); //(c*c - A.x) - B.x + mpz_sub(R->x, R->x, Q->x); //(c*c - A.x) - B.x mpz_mod(R->x, R->x, EC.p); // Rx % p mpz_sub(PA_temp, P->x, R->x); mpz_mul(R->y, PA_slope, PA_temp); @@ -1279,13 +1375,14 @@ char *pubkeytopubaddress_eth(char *pkey,int length) { char *pubkeytopubaddress(char *pkey,int length) { char *pubaddress = calloc(MAXLENGTHADDRESS+10,1); - char *digest = malloc(60); + char *digest = calloc(60,1); long unsigned int pubaddress_size = MAXLENGTHADDRESS+10; if(pubaddress == NULL || digest == NULL) { fprintf(stderr,"error malloc()\n"); exit(0); } - memset(digest,0,60); + + //digest [000...0] sha256(pkey, length, digest); //digest [SHA256 32 bytes+000....0] @@ -1304,49 +1401,66 @@ char *pubkeytopubaddress(char *pkey,int length) { return pubaddress; // pubaddress need to be free by te caller funtion } +char *publickeytohashrmd160(char *pkey,int length) { + char *hash160 = malloc(20); + char *digest = malloc(32); + if(hash160 == NULL || digest == NULL) { + fprintf(stderr,"error malloc()\n"); + exit(0); + } + //digest [000...0] + sha256(pkey, length, digest); + //digest [SHA256 32 bytes] + RMD160Data((const unsigned char*)digest,32, hash160); + //hash160 [RMD160 20 bytes] + free(digest); + return hash160; // hash160 need to be free by te caller funtion +} + + int searchbinary(char *buffer,char *data,int length,int _N) { char *temp_read; - int r = 0,rcmp,current_offset,half,min,max,current; - min = 0; - current = 0; - max = _N; - half = _N; - while(!r && half >= 1) { - half = (max - min)/2; + int r = 0,rcmp,current_offset,half,min,max,current; + min = 0; + current = 0; + max = _N; + half = _N; + while(!r && half >= 1) { + half = (max - min)/2; temp_read = buffer + ((current+half) * length); - rcmp = memcmp(data,temp_read,length); - if(rcmp == 0) { - r = 1; //Found!! - } - else { - if(rcmp < 0) { //data < temp_read - max = (max-half); - } - else { // data > temp_read - min = (min+half); - } + rcmp = memcmp(data,temp_read,length); + 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; - } + } //c++; - } + } //printf("Searchs %i\n",c); - return r; + return r; } void *thread_process(void *vargp) { - struct tothread *tt; + struct tothread *tt; struct Point R,temporal; uint64_t count = 0; int r,thread_number,found; char *hexstrpoint; - char *public_key_compressed,*public_key_uncompressed; - char *hextemp,*public_key_compressed_hex,*public_key_uncompressed_hex; - char *eth_address; - char *public_address_compressed,*public_address_uncompressed; + char *public_key_compressed,*public_key_uncompressed,*publickeyhashrmd160_compress,*publickeyhashrmd160_uncompress; + char *hextemp,*public_key_compressed_hex,*public_key_uncompressed_hex; + char *eth_address; + char *public_address_compressed,*public_address_uncompressed; unsigned long longtemp; FILE *keys,*vanityKeys; - mpz_t random_key_mpz,mpz_bit_range_min,mpz_bit_range_max,mpz_bit_range_diff; - mpz_init(random_key_mpz); + mpz_t key_mpz,mpz_bit_range_min,mpz_bit_range_max,mpz_bit_range_diff; + mpz_init(key_mpz); mpz_init(R.x); mpz_init(R.y); mpz_init(temporal.x); @@ -1357,12 +1471,12 @@ void *thread_process(void *vargp) { mpz_init(mpz_bit_range_diff); mpz_sub(mpz_bit_range_diff,mpz_bit_range_max,mpz_bit_range_min); } - public_key_compressed = malloc(33); - public_key_uncompressed = malloc(65); + public_key_compressed = malloc(33); + public_key_uncompressed = malloc(65); hexstrpoint = malloc(65); - tt = (struct tothread *)vargp; - thread_number = tt->nt; - free(tt); + tt = (struct tothread *)vargp; + thread_number = tt->nt; + free(tt); if(public_key_compressed == NULL || public_key_uncompressed == NULL || hexstrpoint == NULL) { fprintf(stderr,"error malloc!\n"); exit(0); @@ -1371,21 +1485,20 @@ void *thread_process(void *vargp) { do { pthread_mutex_lock(&write_random); if(FLAGBITRANGE) { - mpz_urandomm(random_key_mpz,state,mpz_bit_range_diff); - mpz_add(random_key_mpz,random_key_mpz,mpz_bit_range_min); + mpz_urandomm(key_mpz,state,mpz_bit_range_diff); + mpz_add(key_mpz,key_mpz,mpz_bit_range_min); } else { - mpz_urandomm(random_key_mpz,state,EC.n); + mpz_urandomm(key_mpz,state,EC.n); } pthread_mutex_unlock(&write_random); - hextemp = malloc(65); - gmp_sprintf(hextemp,"%0.64Zx",random_key_mpz); + hextemp = malloc(65); + gmp_sprintf(hextemp,"%0.64Zx",key_mpz); printf("Thread %i : Setting up base key: %s\n",thread_number,hextemp); - free(hextemp); - Scalar_Multiplication(G, &R, random_key_mpz); - count = 0; - public_key_uncompressed[0] = 0x04; + Scalar_Multiplication(G, &R, key_mpz); + count = 0; + public_key_uncompressed[0] = 0x04; do { mpz_set(temporal.x,R.x); @@ -1394,147 +1507,227 @@ void *thread_process(void *vargp) { gmp_sprintf(hexstrpoint,"%0.64Zx",R.x); hexs2bin(hexstrpoint,(unsigned char*)(public_key_compressed+1)); - if(mpz_tstbit(R.y, 0) == 0) { // Even - public_key_compressed[0] = 0x02; - } - else { //Odd - public_key_compressed[0] = 0x03; - } - if(FLAGMODE ) { // FLAGMODE == 1 search for address but for what crypto ? - if( (FLAGCRYPTO & CRYPTO_BTC) != 0) { - memcpy(public_key_uncompressed+1,public_key_compressed+1,32); - gmp_sprintf(hexstrpoint,"%0.64Zx",R.y); - hexs2bin(hexstrpoint,(unsigned char*)(public_key_uncompressed+33)); - - public_address_compressed = pubkeytopubaddress(public_key_compressed,33); - public_address_uncompressed = pubkeytopubaddress(public_key_uncompressed,65); - - if(FLAGVANITY) { - if(strncmp(public_address_uncompressed,vanity,len_vanity) == 0) { - hextemp = malloc(65); - gmp_sprintf(hextemp,"%0.64Zx",random_key_mpz); - vanityKeys = fopen("vanitykeys.txt","a+"); - if(vanityKeys != NULL) { - fprintf(vanityKeys,"PrivKey: %s\nAddress uncompressed: %s\n",hextemp,public_address_uncompressed); - fclose(vanityKeys); - } - printf("Vanity privKey: %s\nAddress uncompressed: %s\n",hextemp,public_address_uncompressed); - free(hextemp); - } - if(strncmp(public_address_compressed,vanity,len_vanity) == 0) { - hextemp = malloc(65); - gmp_sprintf(hextemp,"%0.64Zx",random_key_mpz); - vanityKeys = fopen("vanitykeys.txt","a+"); - if(vanityKeys != NULL) { - fprintf(vanityKeys,"PrivKey: %s\nAddress compressed: %s\n",hextemp,public_address_compressed); - fclose(vanityKeys); - } - printf("Vanity privKey: %s\nAddress compressed: %s\n",hextemp,public_address_compressed); - free(hextemp); - } - } - r = bloom_check(&bloom,public_address_compressed,MAXLENGTHADDRESS); - if(r) { - r = searchbinary(DATABUFFER,public_address_compressed,MAXLENGTHADDRESS,N); - if(r) { - found++; - hextemp = malloc(65); - gmp_sprintf(hextemp,"%0.64Zx",random_key_mpz); - public_key_compressed_hex = tohex(public_key_compressed,33); - pthread_mutex_lock(&write_keys); - keys = fopen("keys.txt","a+"); - if(keys != NULL) { - fprintf(keys,"PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_compressed_hex,public_address_compressed); - fclose(keys); - } - printf("HIT!! PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_compressed_hex,public_address_compressed); - pthread_mutex_unlock(&write_keys); - free(public_key_compressed_hex); - free(hextemp); - } - } - - r = bloom_check(&bloom,public_address_uncompressed,MAXLENGTHADDRESS); - if(r) { - r = searchbinary(DATABUFFER,public_address_uncompressed,MAXLENGTHADDRESS,N); - if(r) { - found++; - hextemp = malloc(65); - gmp_sprintf(hextemp,"%0.64Zx",random_key_mpz); - public_key_uncompressed_hex = tohex(public_key_uncompressed,65); - pthread_mutex_lock(&write_keys); - keys = fopen("keys.txt","a+"); - if(keys != NULL) { - fprintf(keys,"PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); - fclose(keys); - } - printf("HIT!! PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); - pthread_mutex_unlock(&write_keys); - free(public_key_uncompressed_hex); - free(hextemp); - } - } - free(public_address_compressed); - free(public_address_uncompressed); - } - //printf("Resultado %i\n",FLAGCRYPTO & CRYPTO_ETH); - if( (FLAGCRYPTO & CRYPTO_ETH) != 0) { - /* - mpz_export((public_key_uncompressed+1),&longtemp,1,8,1,0,R.x); - mpz_export((public_key_uncompressed+33),&longtemp,1,8,1,0,R.y); - public_address_uncompressed = pubkeytopubaddress_eth(public_key_uncompressed+1,64); - //printf("Testing for %s\n",public_address_uncompressed); - r = bloom_check(&bloom,public_address_uncompressed,MAXLENGTHADDRESS); - if(r) { - r = searchbinary(DATABUFFER,public_address_uncompressed,MAXLENGTHADDRESS,N); - if(r) { - hextemp = malloc(65); - mpz_get_str(hextemp,16,random_key_mpz); - public_key_uncompressed_hex = tohex(public_key_uncompressed+1,64); - pthread_mutex_lock(&write_keys); - keys = fopen("keys.txt","a+"); - if(keys != NULL) { - fprintf(keys,"PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); - fclose(keys); - } - printf("HIT!! PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); - pthread_mutex_unlock(&write_keys); - free(public_key_uncompressed_hex); - free(hextemp); - } + if(mpz_tstbit(R.y, 0) == 0) { // Even + public_key_compressed[0] = 0x02; + } + else { //Odd + public_key_compressed[0] = 0x03; + } + memcpy(public_key_uncompressed+1,public_key_compressed+1,32); + gmp_sprintf(hexstrpoint,"%0.64Zx",R.y); + hexs2bin(hexstrpoint,(unsigned char*)(public_key_uncompressed+33)); + + switch(FLAGMODE) { + case MODE_ADDRESS: + switch(FLAGSEARCH) { + case SEARCH_UNCOMPRESS: + public_address_uncompressed = pubkeytopubaddress(public_key_uncompressed,65); + break; + case SEARCH_COMPRESS: + public_address_compressed = pubkeytopubaddress(public_key_compressed,33); + break; + case SEARCH_BOTH: + public_address_compressed = pubkeytopubaddress(public_key_compressed,33); + public_address_uncompressed = pubkeytopubaddress(public_key_uncompressed,65); + break; + } + if(FLAGVANITY) { + if(FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH){ + if(strncmp(public_address_uncompressed,vanity,len_vanity) == 0) { + hextemp = malloc(65); + gmp_sprintf(hextemp,"%0.64Zx",key_mpz); + vanityKeys = fopen("vanitykeys.txt","a+"); + if(vanityKeys != NULL) { + fprintf(vanityKeys,"PrivKey: %s\nAddress uncompressed: %s\n",hextemp,public_address_uncompressed); + fclose(vanityKeys); + } + printf("Vanity privKey: %s\nAddress uncompressed: %s\n",hextemp,public_address_uncompressed); + free(hextemp); + } + } + if(FLAGSEARCH == SEARCH_COMPRESS || FLAGSEARCH == SEARCH_BOTH){ + if(strncmp(public_address_compressed,vanity,len_vanity) == 0) { + hextemp = malloc(65); + gmp_sprintf(hextemp,"%0.64Zx",key_mpz); + vanityKeys = fopen("vanitykeys.txt","a+"); + if(vanityKeys != NULL) { + fprintf(vanityKeys,"PrivKey: %s\nAddress compressed: %s\n",hextemp,public_address_compressed); + fclose(vanityKeys); + } + printf("Vanity privKey: %s\nAddress compressed: %s\n",hextemp,public_address_compressed); + free(hextemp); + } + } + } + if(FLAGSEARCH == SEARCH_COMPRESS || FLAGSEARCH == SEARCH_BOTH){ + r = bloom_check(&bloom,public_address_compressed,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(DATABUFFER,public_address_compressed,MAXLENGTHADDRESS,N); + if(r) { + found++; + hextemp = malloc(65); + gmp_sprintf(hextemp,"%0.64Zx",key_mpz); + public_key_compressed_hex = tohex(public_key_compressed,33); + pthread_mutex_lock(&write_keys); + keys = fopen("KEYFOUNDKEYFOUND.txt","a+"); + if(keys != NULL) { + fprintf(keys,"PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_compressed_hex,public_address_compressed); + fclose(keys); + } + printf("HIT!! PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_compressed_hex,public_address_compressed); + pthread_mutex_unlock(&write_keys); + free(public_key_compressed_hex); + free(hextemp); + } + } + free(public_address_compressed); + } + + if(FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH){ + r = bloom_check(&bloom,public_address_uncompressed,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(DATABUFFER,public_address_uncompressed,MAXLENGTHADDRESS,N); + if(r) { + found++; + hextemp = malloc(65); + gmp_sprintf(hextemp,"%0.64Zx",key_mpz); + public_key_uncompressed_hex = tohex(public_key_uncompressed,65); + pthread_mutex_lock(&write_keys); + keys = fopen("KEYFOUNDKEYFOUND.txt","a+"); + if(keys != NULL) { + fprintf(keys,"PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); + fclose(keys); + } + printf("HIT!! PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); + pthread_mutex_unlock(&write_keys); + free(public_key_uncompressed_hex); + free(hextemp); + } + } free(public_address_uncompressed); + } + if( (FLAGCRYPTO & CRYPTO_ETH) != 0) { + /* + mpz_export((public_key_uncompressed+1),&longtemp,1,8,1,0,R.x); + mpz_export((public_key_uncompressed+33),&longtemp,1,8,1,0,R.y); + public_address_uncompressed = pubkeytopubaddress_eth(public_key_uncompressed+1,64); + //printf("Testing for %s\n",public_address_uncompressed); + r = bloom_check(&bloom,public_address_uncompressed,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(DATABUFFER,public_address_uncompressed,MAXLENGTHADDRESS,N); + if(r) { + hextemp = malloc(65); + mpz_get_str(hextemp,16,key_mpz); + public_key_uncompressed_hex = tohex(public_key_uncompressed+1,64); + pthread_mutex_lock(&write_keys); + keys = fopen("keys.txt","a+"); + if(keys != NULL) { + fprintf(keys,"PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); + fclose(keys); + } + printf("HIT!! PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); + pthread_mutex_unlock(&write_keys); + free(public_key_uncompressed_hex); + free(hextemp); + } + free(public_address_uncompressed); + } + */ + } + break; + case MODE_RMD160: + switch(FLAGSEARCH) { + case SEARCH_UNCOMPRESS: + publickeyhashrmd160_uncompress = publickeytohashrmd160(public_key_uncompressed,65); + break; + case SEARCH_COMPRESS: + publickeyhashrmd160_compress = publickeytohashrmd160(public_key_compressed,33); + break; + case SEARCH_BOTH: + publickeyhashrmd160_compress = publickeytohashrmd160(public_key_compressed,33); + publickeyhashrmd160_uncompress = publickeytohashrmd160(public_key_uncompressed,65); + break; + } + + if(FLAGSEARCH == SEARCH_COMPRESS || FLAGSEARCH == SEARCH_BOTH){ + r = bloom_check(&bloom,publickeyhashrmd160_compress,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(DATABUFFER,publickeyhashrmd160_compress,MAXLENGTHADDRESS,N); + if(r) { + found++; + hextemp = malloc(65); + gmp_sprintf(hextemp,"%0.64Zx",key_mpz); + public_key_compressed_hex = tohex(public_key_compressed,33); + pthread_mutex_lock(&write_keys); + keys = fopen("KEYFOUNDKEYFOUND.txt","a+"); + if(keys != NULL) { + fprintf(keys,"PrivKey: %s\npubkey: %s\n",hextemp,public_key_compressed_hex); + fclose(keys); + } + printf("HIT!! PrivKey: %s\npubkey: %s\n",hextemp,public_key_compressed_hex); + pthread_mutex_unlock(&write_keys); + free(public_key_compressed_hex); + free(hextemp); + } + } + free(publickeyhashrmd160_compress); + } + if(FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH){ + r = bloom_check(&bloom,publickeyhashrmd160_uncompress,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(DATABUFFER,publickeyhashrmd160_uncompress,MAXLENGTHADDRESS,N); + if(r) { + found++; + hextemp = malloc(65); + gmp_sprintf(hextemp,"%0.64Zx",key_mpz); + public_key_uncompressed_hex = tohex(public_key_uncompressed,65); + pthread_mutex_lock(&write_keys); + keys = fopen("KEYFOUNDKEYFOUND.txt","a+"); + if(keys != NULL) { + fprintf(keys,"PrivKey: %s\npubkey: %s\n",hextemp,public_key_uncompressed_hex); + fclose(keys); + } + printf("HIT!! PrivKey: %s\npubkey: %s\n",hextemp,public_key_uncompressed_hex); + pthread_mutex_unlock(&write_keys); + free(public_key_uncompressed_hex); + free(hextemp); + } + } + free(publickeyhashrmd160_uncompress); } - */ - } - } - else { //FLAGMODE == 0 - r = bloom_check(&bloom,public_key_compressed+1,MAXLENGTHADDRESS); - if(r) { - r = searchbinary(DATABUFFER,public_key_compressed+1,MAXLENGTHADDRESS,N); - if(r) { - found++; - hextemp = malloc(65); - gmp_sprintf(hextemp,"%0.64Zx",random_key_mpz); - public_key_compressed_hex = tohex(public_key_compressed,33); - pthread_mutex_lock(&write_keys); - keys = fopen("KEYFOUNDKEYFOUND.txt","a+"); - if(keys != NULL) { - fprintf(keys,"PrivKey: %s\npubkey: %s\n",hextemp,public_key_compressed_hex); - fclose(keys); - } - printf("HIT!! PrivKey: %s\npubkey: %s\n",hextemp,public_key_compressed_hex); - pthread_mutex_unlock(&write_keys); - free(public_key_compressed_hex); - free(hextemp); - } - } - } + + + + break; + case MODE_XPOINT: + r = bloom_check(&bloom,public_key_compressed+1,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(DATABUFFER,public_key_compressed+1,MAXLENGTHADDRESS,N); + if(r) { + found++; + hextemp = malloc(65); + gmp_sprintf(hextemp,"%0.64Zx",key_mpz); + public_key_compressed_hex = tohex(public_key_compressed,33); + pthread_mutex_lock(&write_keys); + keys = fopen("KEYFOUNDKEYFOUND.txt","a+"); + if(keys != NULL) { + fprintf(keys,"PrivKey: %s\npubkey: %s\n",hextemp,public_key_compressed_hex); + fclose(keys); + } + printf("HIT!! PrivKey: %s\npubkey: %s\n",hextemp,public_key_compressed_hex); + pthread_mutex_unlock(&write_keys); + free(public_key_compressed_hex); + free(hextemp); + } + } + break; + } count++; - if(count % DEBUGCOUNT == 0) { - steps[thread_number]++; + if(count % DEBUGCOUNT == 0) { + steps[thread_number]++; } - mpz_add_ui(random_key_mpz,random_key_mpz,1); + mpz_add_ui(key_mpz,key_mpz,1); Point_Addition(&temporal,&G,&R); }while(count <= N_SECUENTIAL_MAX); } while(1); @@ -1543,15 +1736,15 @@ void *thread_process(void *vargp) { } void *thread_process_range(void *vargp) { - struct tothread *tt; + struct tothread *tt; struct Point R,temporal; uint64_t count = 0; int r,thread_number,found = 0; char *hexstrpoint; - char *public_key_compressed,*public_key_uncompressed; - char *hextemp,*public_key_compressed_hex,*public_key_uncompressed_hex; - char *eth_address; - char *public_address_compressed,*public_address_uncompressed; + char *public_key_compressed,*public_key_uncompressed,*publickeyhashrmd160_compress,*publickeyhashrmd160_uncompress; + char *hextemp,*public_key_compressed_hex,*public_key_uncompressed_hex; + char *eth_address; + char *public_address_compressed,*public_address_uncompressed; unsigned long longtemp; FILE *keys,*range_file,*vanityKeys; mpz_t key_mpz,max_mpz; @@ -1559,15 +1752,15 @@ void *thread_process_range(void *vargp) { mpz_init(R.y); mpz_init(temporal.x); mpz_init(temporal.y); - tt = (struct tothread *) vargp; - thread_number = tt->nt; + tt = (struct tothread *) vargp; + thread_number = tt->nt; - mpz_init_set_str(key_mpz,tt->rs,16); - mpz_init_set_str(max_mpz,tt->rpt,16); - mpz_add(max_mpz,key_mpz,max_mpz); + mpz_init_set_str(key_mpz,tt->rs,16); + mpz_init_set_str(max_mpz,tt->rpt,16); + mpz_add(max_mpz,key_mpz,max_mpz); - public_key_compressed = malloc(33); - public_key_uncompressed = malloc(65); + public_key_compressed = malloc(33); + public_key_uncompressed = malloc(65); hexstrpoint = malloc(65); if(public_key_compressed == NULL || public_key_uncompressed == NULL || hexstrpoint == NULL) { @@ -1576,13 +1769,13 @@ void *thread_process_range(void *vargp) { } printf("Thread %i : Setting up base key: %s\n",thread_number,tt->rs); - free(tt->rs); - free(tt->rpt); - free(tt); - Scalar_Multiplication(G, &R, key_mpz); + free(tt->rs); + free(tt->rpt); + free(tt); + Scalar_Multiplication(G, &R, key_mpz); - public_key_uncompressed[0] = 0x04; - count = 0; + public_key_uncompressed[0] = 0x04; + count = 0; while(mpz_cmp(key_mpz,max_mpz) <= 0 ) { mpz_set(temporal.x,R.x); @@ -1597,344 +1790,418 @@ void *thread_process_range(void *vargp) { else { //ODD public_key_compressed[0] = 0x03; } - if(FLAGMODE) { // FLAGMODE == 1 - if( (FLAGCRYPTO & CRYPTO_BTC) != 0) { - memcpy(public_key_uncompressed+1,public_key_compressed+1,32); - gmp_sprintf(hexstrpoint,"%0.64Zx",R.y); - hexs2bin(hexstrpoint,(unsigned char*)(public_key_uncompressed+33)); - - public_address_compressed = pubkeytopubaddress(public_key_compressed,33); - public_address_uncompressed = pubkeytopubaddress(public_key_uncompressed,65); - /* - printf("Testing: %s\n",public_address_compressed); - printf("Testing: %s\n",public_address_uncompressed); - */ - if(FLAGVANITY) { - if(strncmp(public_address_uncompressed,vanity,len_vanity) == 0) { - hextemp = malloc(65); - gmp_sprintf(hextemp,"%0.64Zx",key_mpz); - vanityKeys = fopen("vanitykeys.txt","a+"); - if(vanityKeys != NULL) { - fprintf(vanityKeys,"PrivKey: %s\nAddress uncompressed: %s\n",hextemp,public_address_uncompressed); - fclose(vanityKeys); - } - printf("Vanity privKey: %s\nAddress uncompressed: %s\n",hextemp,public_address_uncompressed); - free(hextemp); - } - if(strncmp(public_address_compressed,vanity,len_vanity) == 0) { - hextemp = malloc(65); - gmp_sprintf(hextemp,"%0.64Zx",key_mpz); - vanityKeys = fopen("vanitykeys.txt","a+"); - if(vanityKeys != NULL) { - fprintf(vanityKeys,"PrivKey: %s\nAddress compressed: %s\n",hextemp,public_address_compressed); - fclose(vanityKeys); - } - printf("Vanity privKey: %s\nAddress compressed: %s\n",hextemp,public_address_compressed); - free(hextemp); - } - } - r = bloom_check(&bloom,public_address_compressed,MAXLENGTHADDRESS); - if(r) { - //printf("bloom_check: %i for %s\n",r,public_address_compressed); - r = searchbinary(DATABUFFER,public_address_compressed,MAXLENGTHADDRESS,N); - if(r) { - found++; - hextemp = malloc(65); - gmp_sprintf(hextemp,"%0.64Zx",key_mpz); - public_key_compressed_hex = tohex(public_key_compressed,33); - pthread_mutex_lock(&write_keys); - keys = fopen("keys.txt","a+"); - if(keys != NULL) { - fprintf(keys,"PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_compressed_hex,public_address_compressed); - fclose(keys); - } - printf("HIT!! PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_compressed_hex,public_address_compressed); - pthread_mutex_unlock(&write_keys); - free(public_key_compressed_hex); - free(hextemp); - } - } - r = bloom_check(&bloom,public_address_uncompressed,MAXLENGTHADDRESS); - - if(r) { - //printf("bloom_check: %i for %s\n",r,public_address_uncompressed); - r = searchbinary(DATABUFFER,public_address_uncompressed,MAXLENGTHADDRESS,N); - if(r) { - found++; - hextemp = malloc(65); - gmp_sprintf(hextemp,"%0.64Zx",key_mpz); - public_key_uncompressed_hex = tohex(public_key_uncompressed,65); - pthread_mutex_lock(&write_keys); - keys = fopen("keys.txt","a+"); - if(keys != NULL) { - fprintf(keys,"PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); - fclose(keys); - } - printf("HIT!! PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); - pthread_mutex_unlock(&write_keys); - free(public_key_uncompressed_hex); - free(hextemp); - } - } - free(public_address_compressed); - free(public_address_uncompressed); - } - if( ( FLAGCRYPTO & CRYPTO_ETH ) != 0) { - /* - mpz_export((public_key_uncompressed+1),&longtemp,1,8,1,0,R.x); - mpz_export((public_key_uncompressed+33),&longtemp,1,8,1,0,R.y); - public_address_uncompressed = pubkeytopubaddress_eth(public_key_uncompressed+1,64); - //printf("Testing for %s\n",public_address_uncompressed); - r = bloom_check(&bloom,public_address_uncompressed,MAXLENGTHADDRESS); + memcpy(public_key_uncompressed+1,public_key_compressed+1,32); + + gmp_sprintf(hexstrpoint,"%0.64Zx",R.y); + hexs2bin(hexstrpoint,(unsigned char*)(public_key_uncompressed+33)); + + switch(FLAGMODE) { + case MODE_ADDRESS: + if( (FLAGCRYPTO & CRYPTO_BTC) != 0) { + switch(FLAGSEARCH) { + case SEARCH_UNCOMPRESS: + public_address_uncompressed = pubkeytopubaddress(public_key_uncompressed,65); + break; + case SEARCH_COMPRESS: + public_address_compressed = pubkeytopubaddress(public_key_compressed,33); + break; + case SEARCH_BOTH: + public_address_compressed = pubkeytopubaddress(public_key_compressed,33); + public_address_uncompressed = pubkeytopubaddress(public_key_uncompressed,65); + break; + } + if(FLAGVANITY) { + if(FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH){ + if(strncmp(public_address_uncompressed,vanity,len_vanity) == 0) { + hextemp = malloc(65); + gmp_sprintf(hextemp,"%0.64Zx",key_mpz); + vanityKeys = fopen("vanitykeys.txt","a+"); + if(vanityKeys != NULL) { + fprintf(vanityKeys,"PrivKey: %s\nAddress uncompressed: %s\n",hextemp,public_address_uncompressed); + fclose(vanityKeys); + } + printf("Vanity privKey: %s\nAddress uncompressed: %s\n",hextemp,public_address_uncompressed); + free(hextemp); + } + } + if(FLAGSEARCH == SEARCH_COMPRESS || FLAGSEARCH == SEARCH_BOTH){ + if(strncmp(public_address_compressed,vanity,len_vanity) == 0) { + hextemp = malloc(65); + gmp_sprintf(hextemp,"%0.64Zx",key_mpz); + vanityKeys = fopen("vanitykeys.txt","a+"); + if(vanityKeys != NULL) { + fprintf(vanityKeys,"PrivKey: %s\nAddress compressed: %s\n",hextemp,public_address_compressed); + fclose(vanityKeys); + } + printf("Vanity privKey: %s\nAddress compressed: %s\n",hextemp,public_address_compressed); + free(hextemp); + } + } + } + if(FLAGSEARCH == SEARCH_COMPRESS || FLAGSEARCH == SEARCH_BOTH){ + r = bloom_check(&bloom,public_address_compressed,MAXLENGTHADDRESS); + if(r) { + //printf("bloom_check: %i for %s\n",r,public_address_compressed); + r = searchbinary(DATABUFFER,public_address_compressed,MAXLENGTHADDRESS,N); + if(r) { + found++; + hextemp = malloc(65); + gmp_sprintf(hextemp,"%0.64Zx",key_mpz); + public_key_compressed_hex = tohex(public_key_compressed,33); + pthread_mutex_lock(&write_keys); + keys = fopen("KEYFOUNDKEYFOUND.txt","a+"); + if(keys != NULL) { + fprintf(keys,"PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_compressed_hex,public_address_compressed); + fclose(keys); + } + printf("HIT!! PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_compressed_hex,public_address_compressed); + pthread_mutex_unlock(&write_keys); + free(public_key_compressed_hex); + free(hextemp); + } + } + free(public_address_compressed); + } + if(FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH){ + r = bloom_check(&bloom,public_address_uncompressed,MAXLENGTHADDRESS); + if(r) { + //printf("bloom_check: %i for %s\n",r,public_address_uncompressed); + r = searchbinary(DATABUFFER,public_address_uncompressed,MAXLENGTHADDRESS,N); + if(r) { + found++; + hextemp = malloc(65); + gmp_sprintf(hextemp,"%0.64Zx",key_mpz); + public_key_uncompressed_hex = tohex(public_key_uncompressed,65); + pthread_mutex_lock(&write_keys); + keys = fopen("KEYFOUNDKEYFOUND.txt","a+"); + if(keys != NULL) { + fprintf(keys,"PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); + fclose(keys); + } + printf("HIT!! PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); + pthread_mutex_unlock(&write_keys); + free(public_key_uncompressed_hex); + free(hextemp); + } + } + free(public_address_uncompressed); + } + + + } + + if( ( FLAGCRYPTO & CRYPTO_ETH ) != 0) { + /* + mpz_export((public_key_uncompressed+1),&longtemp,1,8,1,0,R.x); + mpz_export((public_key_uncompressed+33),&longtemp,1,8,1,0,R.y); + public_address_uncompressed = pubkeytopubaddress_eth(public_key_uncompressed+1,64); + //printf("Testing for %s\n",public_address_uncompressed); + r = bloom_check(&bloom,public_address_uncompressed,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(DATABUFFER,public_address_uncompressed,MAXLENGTHADDRESS,N); + if(r) { + hextemp = malloc(65); + mpz_get_str(hextemp,16,key_mpz); + public_key_uncompressed_hex = tohex(public_key_uncompressed+1,64); + pthread_mutex_lock(&write_keys); + keys = fopen("KEYFOUNDKEYFOUND.txt","a+"); + if(keys != NULL) { + fprintf(keys,"PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); + fclose(keys); + } + printf("HIT!! PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); + pthread_mutex_unlock(&write_keys); + free(public_key_uncompressed_hex); + free(hextemp); + } + free(public_address_uncompressed); + } + */ + } + break; + case MODE_RMD160: + switch(FLAGSEARCH) { + case SEARCH_UNCOMPRESS: + publickeyhashrmd160_uncompress = publickeytohashrmd160(public_key_uncompressed,65); + break; + case SEARCH_COMPRESS: + publickeyhashrmd160_compress = publickeytohashrmd160(public_key_compressed,33); + break; + case SEARCH_BOTH: + publickeyhashrmd160_compress = publickeytohashrmd160(public_key_compressed,33); + publickeyhashrmd160_uncompress = publickeytohashrmd160(public_key_uncompressed,65); + break; + } + if(FLAGSEARCH == SEARCH_COMPRESS || FLAGSEARCH == SEARCH_BOTH){ + r = bloom_check(&bloom,publickeyhashrmd160_compress,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(DATABUFFER,publickeyhashrmd160_compress,MAXLENGTHADDRESS,N); + if(r) { + found++; + hextemp = malloc(65); + gmp_sprintf(hextemp,"%0.64Zx",key_mpz); + public_key_compressed_hex = tohex(public_key_compressed,33); + pthread_mutex_lock(&write_keys); + keys = fopen("KEYFOUNDKEYFOUND.txt","a+"); + if(keys != NULL) { + fprintf(keys,"PrivKey: %s\npubkey: %s\n",hextemp,public_key_compressed_hex); + fclose(keys); + } + printf("HIT!! PrivKey: %s\npubkey: %s\n",hextemp,public_key_compressed_hex); + pthread_mutex_unlock(&write_keys); + free(public_key_compressed_hex); + free(hextemp); + } + } + } + if(FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH){ + r = bloom_check(&bloom,publickeyhashrmd160_uncompress,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(DATABUFFER,publickeyhashrmd160_uncompress,MAXLENGTHADDRESS,N); + if(r) { + found++; + hextemp = malloc(65); + gmp_sprintf(hextemp,"%0.64Zx",key_mpz); + public_key_uncompressed_hex = tohex(public_key_uncompressed,65); + pthread_mutex_lock(&write_keys); + keys = fopen("KEYFOUNDKEYFOUND.txt","a+"); + if(keys != NULL) { + fprintf(keys,"PrivKey: %s\npubkey: %s\n",hextemp,public_key_uncompressed_hex); + fclose(keys); + } + printf("HIT!! PrivKey: %s\npubkey: %s\n",hextemp,public_key_uncompressed_hex); + pthread_mutex_unlock(&write_keys); + free(public_key_uncompressed_hex); + free(hextemp); + } + } + } + + free(publickeyhashrmd160_compress); + free(publickeyhashrmd160_uncompress); + break; + case MODE_XPOINT: + r = bloom_check(&bloom,public_key_compressed+1,MAXLENGTHADDRESS); if(r) { - r = searchbinary(DATABUFFER,public_address_uncompressed,MAXLENGTHADDRESS,N); + r = searchbinary(DATABUFFER,public_key_compressed+1,MAXLENGTHADDRESS,N); if(r) { + found++; hextemp = malloc(65); - mpz_get_str(hextemp,16,key_mpz); - public_key_uncompressed_hex = tohex(public_key_uncompressed+1,64); + gmp_sprintf(hextemp,"%0.64Zx",key_mpz); + public_key_compressed_hex = tohex(public_key_compressed,33); pthread_mutex_lock(&write_keys); - keys = fopen("keys.txt","a+"); + keys = fopen("KEYFOUNDKEYFOUND.txt","a+"); if(keys != NULL) { - fprintf(keys,"PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); + fprintf(keys,"PrivKey: %s\npubkey: %s\n",hextemp,public_key_compressed_hex); fclose(keys); } - printf("HIT!! PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); + printf("HIT!! PrivKey: %s\npubkey: %s\n",hextemp,public_key_compressed_hex); pthread_mutex_unlock(&write_keys); - free(public_key_uncompressed_hex); + free(public_key_compressed_hex); free(hextemp); } - free(public_address_uncompressed); } - */ - } - } - else { // FLAGMODE == 0 - /* - public_key_compressed_hex = tohex(public_key_compressed+1,32); - printf("Buscando %s\n",public_key_compressed_hex); - free(public_key_compressed_hex); - */ - //printf("Checking: %s\n",hexstrpoint); - r = bloom_check(&bloom,public_key_compressed+1,MAXLENGTHADDRESS); - if(r) { - r = searchbinary(DATABUFFER,public_key_compressed+1,MAXLENGTHADDRESS,N); - if(r) { - found++; - hextemp = malloc(65); - gmp_sprintf(hextemp,"%0.64Zx",key_mpz); - public_key_compressed_hex = tohex(public_key_compressed,33); - pthread_mutex_lock(&write_keys); - keys = fopen("KEYFOUNDKEYFOUND.txt","a+"); - if(keys != NULL) { - fprintf(keys,"PrivKey: %s\npubkey: %s\n",hextemp,public_key_compressed_hex); - fclose(keys); - } - printf("HIT!! PrivKey: %s\npubkey: %s\n",hextemp,public_key_compressed_hex); - pthread_mutex_unlock(&write_keys); - free(public_key_compressed_hex); - free(hextemp); - } - } - } + break; + } count++; - if(count % DEBUGCOUNT == 0) { - steps[thread_number]++; + if(count % DEBUGCOUNT == 0) { + steps[thread_number]++; } mpz_add_ui(key_mpz,key_mpz,1); Point_Addition(&temporal,&G,&R); } printf("Testing Keys %lu\n",count); printf("Found %i\n",found); - ends[thread_number] = 1; + ends[thread_number] = 1; } -void swap(char *a,char *b) { - char t[MAXLENGTHADDRESS]; - memcpy(t,a,MAXLENGTHADDRESS); - memcpy(a,b,MAXLENGTHADDRESS); - memcpy(b,t,MAXLENGTHADDRESS); +void swap(char *a,char *b) { + char t[MAXLENGTHADDRESS]; + memcpy(t,a,MAXLENGTHADDRESS); + memcpy(a,b,MAXLENGTHADDRESS); + memcpy(b,t,MAXLENGTHADDRESS); } -void _sort(char *arr,int n) { - int depthLimit = ((int) ceil(log(n))) * 2; - _introsort(arr,depthLimit,n); +void _sort(char *arr,int n) { + int depthLimit = ((int) ceil(log(n))) * 2; + _introsort(arr,depthLimit,n); } void _introsort(char *arr,int depthLimit, int n) { - int p; - if(n > 1) { - if(n <= 16) { - _insertionsort(arr,n); - } - else { - if(depthLimit == 0) { - myheapsort(arr,n); - } - else { - p = partition(arr,n); - if(p >= 2) { - _introsort(arr , depthLimit-1 , p); - } - if((n - (p + 1)) >= 2 ) { - _introsort(arr + ((p+1) *MAXLENGTHADDRESS) , depthLimit-1 , n - (p + 1)); - } - } - } - } + int p; + if(n > 1) { + if(n <= 16) { + _insertionsort(arr,n); + } + else { + if(depthLimit == 0) { + myheapsort(arr,n); + } + else { + p = partition(arr,n); + if(p >= 2) { + _introsort(arr , depthLimit-1 , p); + } + if((n - (p + 1)) >= 2 ) { + _introsort(arr + ((p+1) *MAXLENGTHADDRESS) , depthLimit-1 , n - (p + 1)); + } + } + } + } } void _insertionsort(char *arr, int n) { int j,i; - char *arrj,*temp; - char key[MAXLENGTHADDRESS]; - for(i = 1; i < n ; i++ ) { - j= i-1; - memcpy(key,arr + (i*MAXLENGTHADDRESS),MAXLENGTHADDRESS); - arrj = arr + (j*MAXLENGTHADDRESS); - while(j >= 0 && memcmp(arrj,key,MAXLENGTHADDRESS) > 0) { - memcpy(arr + ((j+1)*MAXLENGTHADDRESS),arrj,MAXLENGTHADDRESS); - j--; + char *arrj,*temp; + char key[MAXLENGTHADDRESS]; + for(i = 1; i < n ; i++ ) { + j= i-1; + memcpy(key,arr + (i*MAXLENGTHADDRESS),MAXLENGTHADDRESS); + arrj = arr + (j*MAXLENGTHADDRESS); + while(j >= 0 && memcmp(arrj,key,MAXLENGTHADDRESS) > 0) { + memcpy(arr + ((j+1)*MAXLENGTHADDRESS),arrj,MAXLENGTHADDRESS); + j--; if(j >= 0) { - arrj = arr + (j*MAXLENGTHADDRESS); + arrj = arr + (j*MAXLENGTHADDRESS); } - } - memcpy(arr + ((j+1)*MAXLENGTHADDRESS),key,MAXLENGTHADDRESS); - } + } + memcpy(arr + ((j+1)*MAXLENGTHADDRESS),key,MAXLENGTHADDRESS); + } } -int partition(char *arr, int n) { - char pivot[MAXLENGTHADDRESS]; - int j,i,t, r = (int) n/2,jaux = -1,iaux = -1, iflag, jflag; - char *a,*b,*hextemp,*hextemp_pivot; - i = - 1; - memcpy(pivot,arr + (r*MAXLENGTHADDRESS),MAXLENGTHADDRESS); - i = 0; - j = n-1; - do { - iflag = 1; - jflag = 1; - t = memcmp(arr + (i*MAXLENGTHADDRESS),pivot,MAXLENGTHADDRESS); - iflag = (t <= 0); - while(i < j && iflag) { - i++; - t = memcmp(arr + (i*MAXLENGTHADDRESS),pivot,MAXLENGTHADDRESS); - iflag = (t <= 0); - } - t = memcmp(arr + (j*MAXLENGTHADDRESS),pivot,MAXLENGTHADDRESS); - jflag = (t > 0); - while(i < j && jflag) { - j--; - t = memcmp(arr + (j*MAXLENGTHADDRESS),pivot,MAXLENGTHADDRESS); - jflag = (t > 0); - } - if(i < j) { - if(i == r ) { - r = j; - } - else { - if(j == r ) { - r = i; - } - } - - swap(arr + (i*MAXLENGTHADDRESS),arr + (j*MAXLENGTHADDRESS) ); - jaux = j; - iaux = i; - j--; - i++; - } - - } while(j > i ); - if(jaux != -1 && iaux != -1) { - if(iflag || jflag) { - if(iflag) { - if(r != j) - swap(arr + (r*MAXLENGTHADDRESS),arr + ((j )*MAXLENGTHADDRESS) ); - jaux = j; - } - if(jflag) { - if(r != j-1) - swap(arr + (r*MAXLENGTHADDRESS),arr + ((j-1 )*MAXLENGTHADDRESS) ); - jaux = j-1; - } - } - else{ - if(r != j) - swap(arr + (r*MAXLENGTHADDRESS),arr + ((j )*MAXLENGTHADDRESS) ); - jaux = j; - } - } - else { - if(iflag && jflag) { - jaux = r; - } - else { - if(iflag ) { - swap(arr + (r*MAXLENGTHADDRESS),arr + ((j)*MAXLENGTHADDRESS) ); - jaux = j; - } - } - } - return jaux; +int partition(char *arr, int n) { + char pivot[MAXLENGTHADDRESS]; + int j,i,t, r = (int) n/2,jaux = -1,iaux = -1, iflag, jflag; + char *a,*b,*hextemp,*hextemp_pivot; + i = - 1; + memcpy(pivot,arr + (r*MAXLENGTHADDRESS),MAXLENGTHADDRESS); + i = 0; + j = n-1; + do { + iflag = 1; + jflag = 1; + t = memcmp(arr + (i*MAXLENGTHADDRESS),pivot,MAXLENGTHADDRESS); + iflag = (t <= 0); + while(i < j && iflag) { + i++; + t = memcmp(arr + (i*MAXLENGTHADDRESS),pivot,MAXLENGTHADDRESS); + iflag = (t <= 0); + } + t = memcmp(arr + (j*MAXLENGTHADDRESS),pivot,MAXLENGTHADDRESS); + jflag = (t > 0); + while(i < j && jflag) { + j--; + t = memcmp(arr + (j*MAXLENGTHADDRESS),pivot,MAXLENGTHADDRESS); + jflag = (t > 0); + } + if(i < j) { + if(i == r ) { + r = j; + } + else { + if(j == r ) { + r = i; + } + } + + swap(arr + (i*MAXLENGTHADDRESS),arr + (j*MAXLENGTHADDRESS) ); + jaux = j; + iaux = i; + j--; + i++; + } + + } while(j > i ); + if(jaux != -1 && iaux != -1) { + if(iflag || jflag) { + if(iflag) { + if(r != j) + swap(arr + (r*MAXLENGTHADDRESS),arr + ((j )*MAXLENGTHADDRESS) ); + jaux = j; + } + if(jflag) { + if(r != j-1) + swap(arr + (r*MAXLENGTHADDRESS),arr + ((j-1 )*MAXLENGTHADDRESS) ); + jaux = j-1; + } + } + else{ + if(r != j) + swap(arr + (r*MAXLENGTHADDRESS),arr + ((j )*MAXLENGTHADDRESS) ); + jaux = j; + } + } + else { + if(iflag && jflag) { + jaux = r; + } + else { + if(iflag ) { + swap(arr + (r*MAXLENGTHADDRESS),arr + ((j)*MAXLENGTHADDRESS) ); + jaux = j; + } + } + } + return jaux; } void heapify(char *arr, int n, int i) { - int largest = i; - int l = 2 * i + 1; - int r = 2 * i + 2; - if (l < n && memcmp(arr +(l*MAXLENGTHADDRESS),arr +(largest * MAXLENGTHADDRESS),MAXLENGTHADDRESS) > 0) - largest = l; - if (r < n && memcmp(arr +(r*MAXLENGTHADDRESS),arr +(largest *MAXLENGTHADDRESS),MAXLENGTHADDRESS) > 0) - largest = r; - if (largest != i) { - swap(arr +(i*MAXLENGTHADDRESS), arr +(largest*MAXLENGTHADDRESS)); - heapify(arr, n, largest); - } + int largest = i; + int l = 2 * i + 1; + int r = 2 * i + 2; + if (l < n && memcmp(arr +(l*MAXLENGTHADDRESS),arr +(largest * MAXLENGTHADDRESS),MAXLENGTHADDRESS) > 0) + largest = l; + if (r < n && memcmp(arr +(r*MAXLENGTHADDRESS),arr +(largest *MAXLENGTHADDRESS),MAXLENGTHADDRESS) > 0) + largest = r; + if (largest != i) { + swap(arr +(i*MAXLENGTHADDRESS), arr +(largest*MAXLENGTHADDRESS)); + heapify(arr, n, largest); + } } -void myheapsort(char *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 , arr +(i*MAXLENGTHADDRESS)); - heapify(arr, i, 0); - } +void myheapsort(char *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 , arr +(i*MAXLENGTHADDRESS)); + heapify(arr, i, 0); + } } /* OK */ -void bsgs_swap(struct bsgs_xvalue *a,struct bsgs_xvalue *b) { +void bsgs_swap(struct bsgs_xvalue *a,struct bsgs_xvalue *b) { struct bsgs_xvalue t; - t = *a; + t = *a; *a = *b; - *b = t; + *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); +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); + 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 */ @@ -1942,18 +2209,18 @@ 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++ ) { + 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) { + j= i-1; + while(j >= 0 && memcmp(arr[j].value,key.value,BSGS_XVALUE_RAM) > 0) { arr[j+1] = arr[j]; - j--; - } + j--; + } arr[j+1] = key; - } + } } -int64_t bsgs_partition(struct bsgs_xvalue *arr, int64_t n) { +int64_t bsgs_partition(struct bsgs_xvalue *arr, int64_t n) { struct bsgs_xvalue pivot; int64_t r,left,right; char *hextemp; @@ -1962,7 +2229,7 @@ int64_t bsgs_partition(struct bsgs_xvalue *arr, int64_t n) { left = 0; right = n-1; do { - while(left < right && memcmp(arr[left].value,pivot.value,BSGS_XVALUE_RAM) <= 0 ) { + 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) { @@ -1987,62 +2254,62 @@ int64_t bsgs_partition(struct bsgs_xvalue *arr, int64_t n) { } 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); - } + 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); +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); } - 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 _N,int64_t *r_value) { char *temp_read; int64_t min,max,half,current; - int r = 0,rcmp; - min = 0; - current = 0; - max = _N; - half = _N; - while(!r && half >= 1) { - half = (max - min)/2; - rcmp = memcmp(data,buffer[current+half].value,BSGS_XVALUE_RAM); - if(rcmp == 0) { + int r = 0,rcmp; + min = 0; + current = 0; + max = _N; + half = _N; + while(!r && half >= 1) { + half = (max - min)/2; + rcmp = memcmp(data,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); - } + } + else { + if(rcmp < 0) { + max = (max-half); + } + else { + min = (min+half); + } current = min; - } - } - return r; + } + } + return r; } void *thread_process_bsgs(void *vargp) { struct tothread *tt; - char pubkey[131],xpoint_str[65],xpoint_raw[32],tosearch[BSGS_XVALUE_RAM]; + char pubkey[131],xpoint_str[65],xpoint_raw[32]; char *aux_c; mpz_t base_key,keyfound; FILE *filekey; @@ -2133,7 +2400,7 @@ void *thread_process_bsgs(void *vargp) { /* We save our BSGS_S again in BSGS_Q This BSGS_Q value es now our "Normalize" Q point - or S in the next formula: S = Q - base_key*G + or S in the next formula: S = Q - base_key*G */ mpz_set(BSGS_Q[k].x,BSGS_S[k].x); mpz_set(BSGS_Q[k].y,BSGS_S[k].y); @@ -2162,15 +2429,7 @@ void *thread_process_bsgs(void *vargp) { r = bloom_check(&bloom_bPx,xpoint_raw,32); if(r) { /* Lookup for the xpoint_raw into the full sorted list*/ - tosearch[0] = xpoint_raw[6]; - tosearch[1] = xpoint_raw[7]; - tosearch[2] = xpoint_raw[14]; - tosearch[3] = xpoint_raw[15]; - tosearch[4] = xpoint_raw[22]; - tosearch[5] = xpoint_raw[23]; - tosearch[6] = xpoint_raw[30]; - tosearch[7] = xpoint_raw[31]; - r = bsgs_searchbinary(bPtable,tosearch,bsgs_m,&j); + r = bsgs_searchbinary(bPtable,xpoint_raw,bsgs_m,&j); if(r) { /* is the xpoint is in the sorted list we HIT one privkey*/ /* privkey = base_key + aM + b */ @@ -2241,16 +2500,6 @@ void *thread_process_bsgs(void *vargp) { exit(0); } } - /* - else { - - printf("[E] Something is wrong!\n"); - gmp_printf("[I] Basekey: 0x%Zx\n",base_key); - gmp_printf("[I] BSGS_M: 0x%Zx\n",BSGS_M); - printf("[I] a = %i , b = %li\n",i,j+1); - - } - */ } } } @@ -2288,7 +2537,7 @@ void *thread_process_bsgs(void *vargp) { void *thread_process_bsgs_random(void *vargp) { struct tothread *tt; - char pubkey[131],xpoint_str[65],xpoint_raw[32],tosearch[BSGS_XVALUE_RAM]; + char pubkey[131],xpoint_str[65],xpoint_raw[32]; char *aux_c; mpz_t base_key,keyfound; FILE *filekey; @@ -2340,15 +2589,15 @@ void *thread_process_bsgs_random(void *vargp) { */ } pthread_mutex_lock(&bsgs_thread); - /* | Start Range | End Range | - None | 1 | EC.N | --b bit | Min bit value |Max bit value | --r A:B | A | B | + /* | Start Range | End Range | + None | 1 | EC.N | +-b bit | Min bit value |Max bit value | +-r A:B | A | B | */ // set n_range_random = random(end_range - start range) mpz_urandomm (n_range_random,state,n_range_diff); - // base key = start + random value + // base key = start + random value mpz_add(base_key,n_range_start,n_range_random); pthread_mutex_unlock(&bsgs_thread); /* @@ -2389,7 +2638,7 @@ void *thread_process_bsgs_random(void *vargp) { /* We save our BSGS_S again in BSGS_Q This BSGS_Q value es now our "Normalize" Q point - or S in the next formula: S = Q - base_key*G + or S in the next formula: S = Q - base_key*G */ mpz_set(BSGS_Q[k].x,BSGS_S[k].x); mpz_set(BSGS_Q[k].y,BSGS_S[k].y); @@ -2416,15 +2665,7 @@ void *thread_process_bsgs_random(void *vargp) { if(r) { /* Lookup for the xpoint_raw into the full sorted list*/ - tosearch[0] = xpoint_raw[6]; - tosearch[1] = xpoint_raw[7]; - tosearch[2] = xpoint_raw[14]; - tosearch[3] = xpoint_raw[15]; - tosearch[4] = xpoint_raw[22]; - tosearch[5] = xpoint_raw[23]; - tosearch[6] = xpoint_raw[30]; - tosearch[7] = xpoint_raw[31]; - r = bsgs_searchbinary(bPtable,tosearch,bsgs_m,&j); + r = bsgs_searchbinary(bPtable,xpoint_raw,bsgs_m,&j); if(r) { /* is the xpoint is in the sorted list we HIT one privkey*/ /* privkey = base_key + aM + b */ @@ -2492,14 +2733,6 @@ void *thread_process_bsgs_random(void *vargp) { exit(0); } } - /* - else { - printf("[E] Something is wrong!\n"); - gmp_printf("[I] Basekey: 0x%Zx\n",base_key); - gmp_printf("[I] BSGS_M: 0x%Zx\n",BSGS_M); - printf("[I] a = %i , b = %li\n",i,j+1); - } - */ } } diff --git a/sha3/keccak.c b/sha3/keccak.c new file mode 100644 index 0000000..d680577 --- /dev/null +++ b/sha3/keccak.c @@ -0,0 +1,182 @@ +/*- + * Copyright (c) 2015 Taylor R. Campbell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define _POSIX_C_SOURCE 200809L + +#include + +#include "keccak.h" + +#define secret /* can't use in variable-time operations, should zero */ + +#define FOR5(X, STMT) do \ +{ \ + (X) = 0; (STMT); \ + (X) = 1; (STMT); \ + (X) = 2; (STMT); \ + (X) = 3; (STMT); \ + (X) = 4; (STMT); \ +} while (0) + +static inline secret uint64_t +rol64(secret uint64_t v, unsigned c) +{ + + return ((v << c) | (v >> (64 - c))); +} + +static inline void +keccakf1600_theta(secret uint64_t A[25]) +{ + secret uint64_t C0, C1, C2, C3, C4; + unsigned y; + + C0 = C1 = C2 = C3 = C4 = 0; +#pragma GCC diagnostic ignored "-Wpedantic" + FOR5(y, { + C0 ^= A[0 + 5*y]; + C1 ^= A[1 + 5*y]; + C2 ^= A[2 + 5*y]; + C3 ^= A[3 + 5*y]; + C4 ^= A[4 + 5*y]; + }); + FOR5(y, { + A[0 + 5*y] ^= C4 ^ rol64(C1, 1); + A[1 + 5*y] ^= C0 ^ rol64(C2, 1); + A[2 + 5*y] ^= C1 ^ rol64(C3, 1); + A[3 + 5*y] ^= C2 ^ rol64(C4, 1); + A[4 + 5*y] ^= C3 ^ rol64(C0, 1); + }); +#pragma GCC diagnostic pop +} + +static inline void +keccakf1600_rho_pi(secret uint64_t A[25]) +{ + secret uint64_t T, U; + + /* + * Permute by (x,y) |---> (y, 2x + 3y mod 5) starting at (1,0), + * rotate the ith element by (i + 1)(i + 2)/2 mod 64. + */ + U = A[ 1]; T = U; + U = A[10]; A[10] = rol64(T, 1); T = U; + U = A[ 7]; A[ 7] = rol64(T, 3); T = U; + U = A[11]; A[11] = rol64(T, 6); T = U; + U = A[17]; A[17] = rol64(T, 10); T = U; + U = A[18]; A[18] = rol64(T, 15); T = U; + U = A[ 3]; A[ 3] = rol64(T, 21); T = U; + U = A[ 5]; A[ 5] = rol64(T, 28); T = U; + U = A[16]; A[16] = rol64(T, 36); T = U; + U = A[ 8]; A[ 8] = rol64(T, 45); T = U; + U = A[21]; A[21] = rol64(T, 55); T = U; + U = A[24]; A[24] = rol64(T, 2); T = U; + U = A[ 4]; A[ 4] = rol64(T, 14); T = U; + U = A[15]; A[15] = rol64(T, 27); T = U; + U = A[23]; A[23] = rol64(T, 41); T = U; + U = A[19]; A[19] = rol64(T, 56); T = U; + U = A[13]; A[13] = rol64(T, 8); T = U; + U = A[12]; A[12] = rol64(T, 25); T = U; + U = A[ 2]; A[ 2] = rol64(T, 43); T = U; + U = A[20]; A[20] = rol64(T, 62); T = U; + U = A[14]; A[14] = rol64(T, 18); T = U; + U = A[22]; A[22] = rol64(T, 39); T = U; + U = A[ 9]; A[ 9] = rol64(T, 61); T = U; + U = A[ 6]; A[ 6] = rol64(T, 20); T = U; + A[ 1] = rol64(T, 44); +} + +static inline void +keccakf1600_chi(secret uint64_t A[25]) +{ + secret uint64_t B0, B1, B2, B3, B4; + unsigned y; + +#pragma GCC diagnostic ignored "-Wpedantic" + FOR5(y, { + B0 = A[0 + 5*y]; + B1 = A[1 + 5*y]; + B2 = A[2 + 5*y]; + B3 = A[3 + 5*y]; + B4 = A[4 + 5*y]; + A[0 + 5*y] ^= ~B1 & B2; + A[1 + 5*y] ^= ~B2 & B3; + A[2 + 5*y] ^= ~B3 & B4; + A[3 + 5*y] ^= ~B4 & B0; + A[4 + 5*y] ^= ~B0 & B1; + }); +#pragma GCC diagnostic pop +} + +static void +keccakf1600_round(secret uint64_t A[25]) +{ + + keccakf1600_theta(A); + keccakf1600_rho_pi(A); + keccakf1600_chi(A); +} + +void +keccakf1600(secret uint64_t A[25]) +{ + /* + * RC[i] = \sum_{j = 0,...,6} rc(j + 7i) 2^(2^j - 1), + * rc(t) = (x^t mod x^8 + x^6 + x^5 + x^4 + 1) mod x in GF(2)[x] + */ + static const uint64_t RC[24] = { + 0x0000000000000001ULL, + 0x0000000000008082ULL, + 0x800000000000808aULL, + 0x8000000080008000ULL, + 0x000000000000808bULL, + 0x0000000080000001ULL, + 0x8000000080008081ULL, + 0x8000000000008009ULL, + 0x000000000000008aULL, + 0x0000000000000088ULL, + 0x0000000080008009ULL, + 0x000000008000000aULL, + 0x000000008000808bULL, + 0x800000000000008bULL, + 0x8000000000008089ULL, + 0x8000000000008003ULL, + 0x8000000000008002ULL, + 0x8000000000000080ULL, + 0x000000000000800aULL, + 0x800000008000000aULL, + 0x8000000080008081ULL, + 0x8000000000008080ULL, + 0x0000000080000001ULL, + 0x8000000080008008ULL, + }; + unsigned i; + + for (i = 0; i < 24; i++) { + keccakf1600_round(A); + A[0] ^= RC[i]; + } +} diff --git a/sha3/keccak.h b/sha3/keccak.h new file mode 100644 index 0000000..51a8e02 --- /dev/null +++ b/sha3/keccak.h @@ -0,0 +1,34 @@ +/*- + * Copyright (c) 2015 Taylor R. Campbell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef KECCAK_H +#define KECCAK_H + +#include + +void keccakf1600(uint64_t A[25]); + +#endif /* KECCAK_H */ diff --git a/sha3/sha3.c b/sha3/sha3.c new file mode 100644 index 0000000..edee7a5 --- /dev/null +++ b/sha3/sha3.c @@ -0,0 +1,674 @@ +/*- + * Copyright (c) 2015 Taylor R. Campbell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * SHA-3: FIPS-202, Permutation-Based Hash and Extendable-Ouptut Functions + */ + +#define _POSIX_C_SOURCE 200809L + +#include +#include +#include +#include + +#include "keccak.h" + +#include "sha3.h" + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +void *(*volatile sha3_explicit_memset_impl)(void *, int, size_t) = &memset; +static void * +explicit_memset(void *buf, int c, size_t n) +{ + + return (*sha3_explicit_memset_impl)(buf, c, n); +} + +static inline uint64_t +le64dec(const void *buf) +{ + const uint8_t *p = buf; + + return (((uint64_t)p[0]) | + ((uint64_t)p[1] << 8) | + ((uint64_t)p[2] << 16) | + ((uint64_t)p[3] << 24) | + ((uint64_t)p[4] << 32) | + ((uint64_t)p[5] << 40) | + ((uint64_t)p[6] << 48) | + ((uint64_t)p[7] << 56)); +} + +static inline void +le64enc(void *buf, uint64_t v) +{ + uint8_t *p = buf; + + *p++ = v; v >>= 8; + *p++ = v; v >>= 8; + *p++ = v; v >>= 8; + *p++ = v; v >>= 8; + *p++ = v; v >>= 8; + *p++ = v; v >>= 8; + *p++ = v; v >>= 8; + *p++ = v; +} + +/* + * Common body. All the SHA-3 functions share code structure. They + * differ only in the size of the chunks they split the message into: + * for digest size d, they are split into chunks of 200 - d bytes. + */ + +static inline unsigned +sha3_rate(unsigned d) +{ + const unsigned cw = 2*d/8; /* capacity in words */ + + return 25 - cw; +} + +static void +sha3_init(struct sha3 *C, unsigned rw) +{ + unsigned iw; + + C->nb = 8*rw; + for (iw = 0; iw < 25; iw++) + C->A[iw] = 0; +} + +static void +sha3_update(struct sha3 *C, const uint8_t *data, size_t len, unsigned rw) +{ + uint64_t T; + unsigned ib, iw; /* index of byte/word */ + + assert(0 < C->nb); + + /* If there's a partial word, try to fill it. */ + if ((C->nb % 8) != 0) { + T = 0; + for (ib = 0; ib < MIN(len, C->nb % 8); ib++) + T |= (uint64_t)data[ib] << (8*ib); + C->A[rw - (C->nb + 7)/8] ^= T << (8*(8 - (C->nb % 8))); + C->nb -= ib; + data += ib; + len -= ib; + + /* If we filled the buffer, permute now. */ + if (C->nb == 0) { + keccakf1600(C->A); + C->nb = 8*rw; + } + + /* If that exhausted the input, we're done. */ + if (len == 0) + return; + } + + /* At a word boundary. Fill any partial buffer. */ + assert((C->nb % 8) == 0); + if (C->nb < 8*rw) { + for (iw = 0; iw < MIN(len, C->nb)/8; iw++) + C->A[rw - C->nb/8 + iw] ^= le64dec(data + 8*iw); + C->nb -= 8*iw; + data += 8*iw; + len -= 8*iw; + + /* If we filled the buffer, permute now. */ + if (C->nb == 0) { + keccakf1600(C->A); + C->nb = 8*rw; + } else { + /* Otherwise, less than a word left. */ + assert(len < 8); + goto partial; + } + } + + /* At a buffer boundary. Absorb input one buffer at a time. */ + assert(C->nb == 8*rw); + while (8*rw <= len) { + for (iw = 0; iw < rw; iw++) + C->A[iw] ^= le64dec(data + 8*iw); + keccakf1600(C->A); + data += 8*rw; + len -= 8*rw; + } + + /* Partially fill the buffer with as many words as we can. */ + for (iw = 0; iw < len/8; iw++) + C->A[rw - C->nb/8 + iw] ^= le64dec(data + 8*iw); + C->nb -= 8*iw; + data += 8*iw; + len -= 8*iw; + +partial: + /* Partially fill the last word with as many bytes as we can. */ + assert(len < 8); + assert(0 < C->nb); + assert((C->nb % 8) == 0); + T = 0; + for (ib = 0; ib < len; ib++) + T |= (uint64_t)data[ib] << (8*ib); + C->A[rw - C->nb/8] ^= T; + C->nb -= ib; + assert(0 < C->nb); +} + +static inline void +sha3_or_keccak_final(uint8_t *h, unsigned d, struct sha3 *C, unsigned rw, uint64_t padding) +{ + unsigned nw, iw; + + assert(d <= 8*25); + assert(0 < C->nb); + + /* Append 01, pad with 10*1 up to buffer boundary, LSB first. */ + nw = (C->nb + 7)/8; + assert(0 < nw); + assert(nw <= rw); + C->A[rw - nw] ^= padding << (8*(8*nw - C->nb)); + C->A[rw - 1] ^= 0x8000000000000000ULL; + + /* Permute one last time. */ + keccakf1600(C->A); + + /* Reveal the first 8d bits of state, forget 1600-8d of them. */ + for (iw = 0; iw < d/8; iw++) + le64enc(h + 8*iw, C->A[iw]); + h += 8*iw; + d -= 8*iw; + if (0 < d) { + /* For SHA3-224, we need to expose a partial word. */ + uint64_t T = C->A[iw]; + do { + *h++ = T & 0xff; + T >>= 8; + } while (--d); + } + (void)explicit_memset(C->A, 0, sizeof C->A); + C->nb = 0; +} + +static void +sha3_final(uint8_t *h, unsigned d, struct sha3 *C, unsigned rw) +{ + sha3_or_keccak_final(h, d, C, rw, 0x06); +} + +static void +keccak_final(uint8_t *h, unsigned d, struct sha3 *C, unsigned rw) +{ + sha3_or_keccak_final(h, d, C, rw, 0x01); +} + +static void +shake_final(uint8_t *h, unsigned d, struct sha3 *C, unsigned rw) +{ + unsigned nw, iw; + + assert(0 < C->nb); + + /* Append 1111, pad with 10*1 up to buffer boundary, LSB first. */ + nw = (C->nb + 7)/8; + assert(0 < nw); + assert(nw <= rw); + C->A[rw - nw] ^= (uint64_t)0x1f << (8*(8*nw - C->nb)); + C->A[rw - 1] ^= 0x8000000000000000ULL; + + /* Permute, reveal first rw words of state, repeat. */ + while (8*rw <= d) { + keccakf1600(C->A); + for (iw = 0; iw < rw; iw++) + le64enc(h + 8*iw, C->A[iw]); + h += 8*iw; + d -= 8*iw; + } + + /* + * If 8*rw (the output rate in bytes) does not divide d, more + * words are wanted: permute again and reveal a little more. + */ + if (0 < d) { + keccakf1600(C->A); + for (iw = 0; iw < d/8; iw++) + le64enc(h + 8*iw, C->A[iw]); + h += 8*iw; + d -= 8*iw; + + /* + * If 8 does not divide d, more bytes are wanted: + * reveal them. + */ + if (0 < d) { + uint64_t T = C->A[iw]; + do { + *h++ = T & 0xff; + T >>= 8; + } while (--d); + } + } + + (void)explicit_memset(C->A, 0, sizeof C->A); + C->nb = 0; +} + +void +SHA3_224_Init(SHA3_224_CTX *C) +{ + + sha3_init(&C->C224, sha3_rate(SHA3_224_DIGEST_LENGTH)); +} + +void +SHA3_224_Update(SHA3_224_CTX *C, const uint8_t *data, size_t len) +{ + + sha3_update(&C->C224, data, len, sha3_rate(SHA3_224_DIGEST_LENGTH)); +} + +void +SHA3_224_Final(uint8_t h[SHA3_224_DIGEST_LENGTH], SHA3_224_CTX *C) +{ + + sha3_final(h, SHA3_224_DIGEST_LENGTH, &C->C224, + sha3_rate(SHA3_224_DIGEST_LENGTH)); +} + +void +SHA3_256_Init(SHA3_256_CTX *C) +{ + + sha3_init(&C->C256, sha3_rate(SHA3_256_DIGEST_LENGTH)); +} + +void +SHA3_256_Update(SHA3_256_CTX *C, const uint8_t *data, size_t len) +{ + + sha3_update(&C->C256, data, len, sha3_rate(SHA3_256_DIGEST_LENGTH)); +} + +void +SHA3_256_Final(uint8_t h[SHA3_256_DIGEST_LENGTH], SHA3_256_CTX *C) +{ + + sha3_final(h, SHA3_256_DIGEST_LENGTH, &C->C256, + sha3_rate(SHA3_256_DIGEST_LENGTH)); +} + +void +SHA3_384_Init(SHA3_384_CTX *C) +{ + + sha3_init(&C->C384, sha3_rate(SHA3_384_DIGEST_LENGTH)); +} + +void +SHA3_384_Update(SHA3_384_CTX *C, const uint8_t *data, size_t len) +{ + + sha3_update(&C->C384, data, len, sha3_rate(SHA3_384_DIGEST_LENGTH)); +} + +void +SHA3_384_Final(uint8_t h[SHA3_384_DIGEST_LENGTH], SHA3_384_CTX *C) +{ + + sha3_final(h, SHA3_384_DIGEST_LENGTH, &C->C384, + sha3_rate(SHA3_384_DIGEST_LENGTH)); +} + +void +SHA3_512_Init(SHA3_512_CTX *C) +{ + + sha3_init(&C->C512, sha3_rate(SHA3_512_DIGEST_LENGTH)); +} + +void +SHA3_512_Update(SHA3_512_CTX *C, const uint8_t *data, size_t len) +{ + + sha3_update(&C->C512, data, len, sha3_rate(SHA3_512_DIGEST_LENGTH)); +} + +void +SHA3_512_Final(uint8_t h[SHA3_512_DIGEST_LENGTH], SHA3_512_CTX *C) +{ + + sha3_final(h, SHA3_512_DIGEST_LENGTH, &C->C512, + sha3_rate(SHA3_512_DIGEST_LENGTH)); +} + +void +SHAKE128_Init(SHAKE128_CTX *C) +{ + + sha3_init(&C->C128, sha3_rate(128/8)); +} + +void +SHAKE128_Update(SHAKE128_CTX *C, const uint8_t *data, size_t len) +{ + + sha3_update(&C->C128, data, len, sha3_rate(128/8)); +} + +void +SHAKE128_Final(uint8_t *h, size_t d, SHAKE128_CTX *C) +{ + + shake_final(h, d, &C->C128, sha3_rate(128/8)); +} + +void +SHAKE256_Init(SHAKE256_CTX *C) +{ + + sha3_init(&C->C256, sha3_rate(256/8)); +} + +void +SHAKE256_Update(SHAKE256_CTX *C, const uint8_t *data, size_t len) +{ + + sha3_update(&C->C256, data, len, sha3_rate(256/8)); +} + +void +SHAKE256_Final(uint8_t *h, size_t d, SHAKE256_CTX *C) +{ + + shake_final(h, d, &C->C256, sha3_rate(256/8)); +} + +void +KECCAK_256_Final(uint8_t h[SHA3_256_DIGEST_LENGTH], SHA3_256_CTX *C) +{ + + keccak_final(h, SHA3_256_DIGEST_LENGTH, &C->C256, + sha3_rate(SHA3_256_DIGEST_LENGTH)); +} + +void +KECCAK_384_Final(uint8_t h[SHA3_384_DIGEST_LENGTH], SHA3_384_CTX *C) +{ + + keccak_final(h, SHA3_384_DIGEST_LENGTH, &C->C384, + sha3_rate(SHA3_384_DIGEST_LENGTH)); +} + +void +KECCAK_512_Final(uint8_t h[SHA3_512_DIGEST_LENGTH], SHA3_512_CTX *C) +{ + + keccak_final(h, SHA3_512_DIGEST_LENGTH, &C->C512, + sha3_rate(SHA3_512_DIGEST_LENGTH)); +} + +static void +sha3_selftest_prng(void *buf, size_t len, uint32_t seed) +{ + uint8_t *p = buf; + size_t n = len; + uint32_t t, a, b; + + a = 0xdead4bad * seed; + b = 1; + + while (n--) { + t = a + b; + *p++ = t >> 24; + a = b; + b = t; + } +} + +int +SHA3_Selftest(void) +{ + const uint8_t d224_0[] = { /* SHA3-224(0-bit) */ + 0x6b,0x4e,0x03,0x42,0x36,0x67,0xdb,0xb7, + 0x3b,0x6e,0x15,0x45,0x4f,0x0e,0xb1,0xab, + 0xd4,0x59,0x7f,0x9a,0x1b,0x07,0x8e,0x3f, + 0x5b,0x5a,0x6b,0xc7, + }; + const uint8_t d256_0[] = { /* SHA3-256(0-bit) */ + 0xa7,0xff,0xc6,0xf8,0xbf,0x1e,0xd7,0x66, + 0x51,0xc1,0x47,0x56,0xa0,0x61,0xd6,0x62, + 0xf5,0x80,0xff,0x4d,0xe4,0x3b,0x49,0xfa, + 0x82,0xd8,0x0a,0x4b,0x80,0xf8,0x43,0x4a, + }; + const uint8_t d384_0[] = { /* SHA3-384(0-bit) */ + 0x0c,0x63,0xa7,0x5b,0x84,0x5e,0x4f,0x7d, + 0x01,0x10,0x7d,0x85,0x2e,0x4c,0x24,0x85, + 0xc5,0x1a,0x50,0xaa,0xaa,0x94,0xfc,0x61, + 0x99,0x5e,0x71,0xbb,0xee,0x98,0x3a,0x2a, + 0xc3,0x71,0x38,0x31,0x26,0x4a,0xdb,0x47, + 0xfb,0x6b,0xd1,0xe0,0x58,0xd5,0xf0,0x04, + }; + const uint8_t d512_0[] = { /* SHA3-512(0-bit) */ + 0xa6,0x9f,0x73,0xcc,0xa2,0x3a,0x9a,0xc5, + 0xc8,0xb5,0x67,0xdc,0x18,0x5a,0x75,0x6e, + 0x97,0xc9,0x82,0x16,0x4f,0xe2,0x58,0x59, + 0xe0,0xd1,0xdc,0xc1,0x47,0x5c,0x80,0xa6, + 0x15,0xb2,0x12,0x3a,0xf1,0xf5,0xf9,0x4c, + 0x11,0xe3,0xe9,0x40,0x2c,0x3a,0xc5,0x58, + 0xf5,0x00,0x19,0x9d,0x95,0xb6,0xd3,0xe3, + 0x01,0x75,0x85,0x86,0x28,0x1d,0xcd,0x26, + }; + const uint8_t shake128_0_41[] = { /* SHAKE128(0-bit, 41) */ + 0x7f,0x9c,0x2b,0xa4,0xe8,0x8f,0x82,0x7d, + 0x61,0x60,0x45,0x50,0x76,0x05,0x85,0x3e, + 0xd7,0x3b,0x80,0x93,0xf6,0xef,0xbc,0x88, + 0xeb,0x1a,0x6e,0xac,0xfa,0x66,0xef,0x26, + 0x3c,0xb1,0xee,0xa9,0x88,0x00,0x4b,0x93,0x10, + }; + const uint8_t shake256_0_73[] = { /* SHAKE256(0-bit, 73) */ + 0x46,0xb9,0xdd,0x2b,0x0b,0xa8,0x8d,0x13, + 0x23,0x3b,0x3f,0xeb,0x74,0x3e,0xeb,0x24, + 0x3f,0xcd,0x52,0xea,0x62,0xb8,0x1b,0x82, + 0xb5,0x0c,0x27,0x64,0x6e,0xd5,0x76,0x2f, + 0xd7,0x5d,0xc4,0xdd,0xd8,0xc0,0xf2,0x00, + 0xcb,0x05,0x01,0x9d,0x67,0xb5,0x92,0xf6, + 0xfc,0x82,0x1c,0x49,0x47,0x9a,0xb4,0x86, + 0x40,0x29,0x2e,0xac,0xb3,0xb7,0xc4,0xbe, + 0x14,0x1e,0x96,0x61,0x6f,0xb1,0x39,0x57,0x69, + }; + const uint8_t d224_1600[] = { /* SHA3-224(200 * 0xa3) */ + 0x93,0x76,0x81,0x6a,0xba,0x50,0x3f,0x72, + 0xf9,0x6c,0xe7,0xeb,0x65,0xac,0x09,0x5d, + 0xee,0xe3,0xbe,0x4b,0xf9,0xbb,0xc2,0xa1, + 0xcb,0x7e,0x11,0xe0, + }; + const uint8_t d256_1600[] = { /* SHA3-256(200 * 0xa3) */ + 0x79,0xf3,0x8a,0xde,0xc5,0xc2,0x03,0x07, + 0xa9,0x8e,0xf7,0x6e,0x83,0x24,0xaf,0xbf, + 0xd4,0x6c,0xfd,0x81,0xb2,0x2e,0x39,0x73, + 0xc6,0x5f,0xa1,0xbd,0x9d,0xe3,0x17,0x87, + }; + const uint8_t d384_1600[] = { /* SHA3-384(200 * 0xa3) */ + 0x18,0x81,0xde,0x2c,0xa7,0xe4,0x1e,0xf9, + 0x5d,0xc4,0x73,0x2b,0x8f,0x5f,0x00,0x2b, + 0x18,0x9c,0xc1,0xe4,0x2b,0x74,0x16,0x8e, + 0xd1,0x73,0x26,0x49,0xce,0x1d,0xbc,0xdd, + 0x76,0x19,0x7a,0x31,0xfd,0x55,0xee,0x98, + 0x9f,0x2d,0x70,0x50,0xdd,0x47,0x3e,0x8f, + }; + const uint8_t d512_1600[] = { /* SHA3-512(200 * 0xa3) */ + 0xe7,0x6d,0xfa,0xd2,0x20,0x84,0xa8,0xb1, + 0x46,0x7f,0xcf,0x2f,0xfa,0x58,0x36,0x1b, + 0xec,0x76,0x28,0xed,0xf5,0xf3,0xfd,0xc0, + 0xe4,0x80,0x5d,0xc4,0x8c,0xae,0xec,0xa8, + 0x1b,0x7c,0x13,0xc3,0x0a,0xdf,0x52,0xa3, + 0x65,0x95,0x84,0x73,0x9a,0x2d,0xf4,0x6b, + 0xe5,0x89,0xc5,0x1c,0xa1,0xa4,0xa8,0x41, + 0x6d,0xf6,0x54,0x5a,0x1c,0xe8,0xba,0x00, + }; + const uint8_t shake128_1600_41[] = { /* SHAKE128(200 * 0xa3, 41) */ + 0x13,0x1a,0xb8,0xd2,0xb5,0x94,0x94,0x6b, + 0x9c,0x81,0x33,0x3f,0x9b,0xb6,0xe0,0xce, + 0x75,0xc3,0xb9,0x31,0x04,0xfa,0x34,0x69, + 0xd3,0x91,0x74,0x57,0x38,0x5d,0xa0,0x37, + 0xcf,0x23,0x2e,0xf7,0x16,0x4a,0x6d,0x1e,0xb4, + }; + const uint8_t shake256_1600_73[] = { /* SHAKE256(200 * 0xa3, 73) */ + 0xcd,0x8a,0x92,0x0e,0xd1,0x41,0xaa,0x04, + 0x07,0xa2,0x2d,0x59,0x28,0x86,0x52,0xe9, + 0xd9,0xf1,0xa7,0xee,0x0c,0x1e,0x7c,0x1c, + 0xa6,0x99,0x42,0x4d,0xa8,0x4a,0x90,0x4d, + 0x2d,0x70,0x0c,0xaa,0xe7,0x39,0x6e,0xce, + 0x96,0x60,0x44,0x40,0x57,0x7d,0xa4,0xf3, + 0xaa,0x22,0xae,0xb8,0x85,0x7f,0x96,0x1c, + 0x4c,0xd8,0xe0,0x6f,0x0a,0xe6,0x61,0x0b, + 0x10,0x48,0xa7,0xf6,0x4e,0x10,0x74,0xcd,0x62, + }; + const uint8_t d0[] = { + 0x6c,0x02,0x1a,0xc6,0x65,0xaf,0x80,0xfb, + 0x52,0xe6,0x2d,0x27,0xe5,0x02,0x88,0x84, + 0xec,0x1c,0x0c,0xe7,0x0b,0x94,0x55,0x83, + 0x19,0xf2,0xbf,0x09,0x86,0xeb,0x1a,0xbb, + 0xc3,0x0d,0x1c,0xef,0x22,0xfe,0xc5,0x4c, + 0x45,0x90,0x66,0x14,0x00,0x6e,0xc8,0x79, + 0xdf,0x1e,0x02,0xbd,0x75,0xe9,0x60,0xd8, + 0x60,0x39,0x85,0xc9,0xc4,0xee,0x33,0xab, + }; + const unsigned mlen[6] = { 0, 3, 128, 129, 255, 1024 }; + uint8_t m[1024], d[73]; + SHA3_224_CTX sha3224; + SHA3_256_CTX sha3256; + SHA3_384_CTX sha3384; + SHA3_512_CTX sha3512; + SHAKE128_CTX shake128; + SHAKE256_CTX shake256; + SHA3_512_CTX ctx; + unsigned mi; + + /* + * NIST test vectors from + * : + * 0-bit, 1600-bit repeated 0xa3 (= 0b10100011). + */ + SHA3_224_Init(&sha3224); + SHA3_224_Final(d, &sha3224); + if (memcmp(d, d224_0, 28) != 0) + return -1; + SHA3_256_Init(&sha3256); + SHA3_256_Final(d, &sha3256); + if (memcmp(d, d256_0, 32) != 0) + return -1; + SHA3_384_Init(&sha3384); + SHA3_384_Final(d, &sha3384); + if (memcmp(d, d384_0, 48) != 0) + return -1; + SHA3_512_Init(&sha3512); + SHA3_512_Final(d, &sha3512); + if (memcmp(d, d512_0, 64) != 0) + return -1; + SHAKE128_Init(&shake128); + SHAKE128_Final(d, 41, &shake128); + if (memcmp(d, shake128_0_41, 41) != 0) + return -1; + SHAKE256_Init(&shake256); + SHAKE256_Final(d, 73, &shake256); + if (memcmp(d, shake256_0_73, 73) != 0) + return -1; + + (void)memset(m, 0xa3, 200); + SHA3_224_Init(&sha3224); + SHA3_224_Update(&sha3224, m, 200); + SHA3_224_Final(d, &sha3224); + if (memcmp(d, d224_1600, 28) != 0) + return -1; + SHA3_256_Init(&sha3256); + SHA3_256_Update(&sha3256, m, 200); + SHA3_256_Final(d, &sha3256); + if (memcmp(d, d256_1600, 32) != 0) + return -1; + SHA3_384_Init(&sha3384); + SHA3_384_Update(&sha3384, m, 200); + SHA3_384_Final(d, &sha3384); + if (memcmp(d, d384_1600, 48) != 0) + return -1; + SHA3_512_Init(&sha3512); + SHA3_512_Update(&sha3512, m, 200); + SHA3_512_Final(d, &sha3512); + if (memcmp(d, d512_1600, 64) != 0) + return -1; + SHAKE128_Init(&shake128); + SHAKE128_Update(&shake128, m, 200); + SHAKE128_Final(d, 41, &shake128); + if (memcmp(d, shake128_1600_41, 41) != 0) + return -1; + SHAKE256_Init(&shake256); + SHAKE256_Update(&shake256, m, 200); + SHAKE256_Final(d, 73, &shake256); + if (memcmp(d, shake256_1600_73, 73) != 0) + return -1; + + /* + * Hand-crufted test vectors with unaligned message lengths. + */ + SHA3_512_Init(&ctx); + for (mi = 0; mi < 6; mi++) { + sha3_selftest_prng(m, mlen[mi], (224/8)*mlen[mi]); + SHA3_224_Init(&sha3224); + SHA3_224_Update(&sha3224, m, mlen[mi]); + SHA3_224_Final(d, &sha3224); + SHA3_512_Update(&ctx, d, 224/8); + } + for (mi = 0; mi < 6; mi++) { + sha3_selftest_prng(m, mlen[mi], (256/8)*mlen[mi]); + SHA3_256_Init(&sha3256); + SHA3_256_Update(&sha3256, m, mlen[mi]); + SHA3_256_Final(d, &sha3256); + SHA3_512_Update(&ctx, d, 256/8); + } + for (mi = 0; mi < 6; mi++) { + sha3_selftest_prng(m, mlen[mi], (384/8)*mlen[mi]); + SHA3_384_Init(&sha3384); + SHA3_384_Update(&sha3384, m, mlen[mi]); + SHA3_384_Final(d, &sha3384); + SHA3_512_Update(&ctx, d, 384/8); + } + for (mi = 0; mi < 6; mi++) { + sha3_selftest_prng(m, mlen[mi], (512/8)*mlen[mi]); + SHA3_512_Init(&sha3512); + SHA3_512_Update(&sha3512, m, mlen[mi]); + SHA3_512_Final(d, &sha3512); + SHA3_512_Update(&ctx, d, 512/8); + } + SHA3_512_Final(d, &ctx); + if (memcmp(d, d0, 64) != 0) + return -1; + + return 0; +} diff --git a/sha3/sha3.h b/sha3/sha3.h new file mode 100644 index 0000000..8118d27 --- /dev/null +++ b/sha3/sha3.h @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 2015 Taylor R. Campbell + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef SHA3_H +#define SHA3_H + +#include +#include + +struct sha3 { + uint64_t A[25]; + unsigned nb; /* number of bytes remaining to fill buffer */ +}; + +typedef struct { struct sha3 C224; } SHA3_224_CTX; +typedef struct { struct sha3 C256; } SHA3_256_CTX; +typedef struct { struct sha3 C384; } SHA3_384_CTX; +typedef struct { struct sha3 C512; } SHA3_512_CTX; +typedef struct { struct sha3 C128; } SHAKE128_CTX; +typedef struct { struct sha3 C256; } SHAKE256_CTX; + +#define SHA3_224_DIGEST_LENGTH 28 +#define SHA3_256_DIGEST_LENGTH 32 +#define SHA3_384_DIGEST_LENGTH 48 +#define SHA3_512_DIGEST_LENGTH 64 + +void SHA3_224_Init(SHA3_224_CTX *); +void SHA3_224_Update(SHA3_224_CTX *, const uint8_t *, size_t); +void SHA3_224_Final(uint8_t[SHA3_224_DIGEST_LENGTH], SHA3_224_CTX *); + +void SHA3_256_Init(SHA3_256_CTX *); +void SHA3_256_Update(SHA3_256_CTX *, const uint8_t *, size_t); +void SHA3_256_Final(uint8_t[SHA3_256_DIGEST_LENGTH], SHA3_256_CTX *); + +void SHA3_384_Init(SHA3_384_CTX *); +void SHA3_384_Update(SHA3_384_CTX *, const uint8_t *, size_t); +void SHA3_384_Final(uint8_t[SHA3_384_DIGEST_LENGTH], SHA3_384_CTX *); + +void SHA3_512_Init(SHA3_512_CTX *); +void SHA3_512_Update(SHA3_512_CTX *, const uint8_t *, size_t); +void SHA3_512_Final(uint8_t[SHA3_512_DIGEST_LENGTH], SHA3_512_CTX *); + +void SHAKE128_Init(SHAKE128_CTX *); +void SHAKE128_Update(SHAKE128_CTX *, const uint8_t *, size_t); +void SHAKE128_Final(uint8_t *, size_t, SHAKE128_CTX *); + +void SHAKE256_Init(SHAKE256_CTX *); +void SHAKE256_Update(SHAKE256_CTX *, const uint8_t *, size_t); +void SHAKE256_Final(uint8_t *, size_t, SHAKE256_CTX *); + +#define KECCAK_256_Init SHA3_256_Init +#define KECCAK_256_Update SHA3_256_Update +void KECCAK_256_Final(uint8_t[SHA3_256_DIGEST_LENGTH], SHA3_256_CTX *); + +#define KECCAK_384_Init SHA3_384_Init +#define KECCAK_384_Update SHA3_384_Update +void KECCAK_384_Final(uint8_t[SHA3_384_DIGEST_LENGTH], SHA3_384_CTX *); + +#define KECCAK_512_Init SHA3_512_Init +#define KECCAK_512_Update SHA3_512_Update +void KECCAK_512_Final(uint8_t[SHA3_512_DIGEST_LENGTH], SHA3_512_CTX *); + +int SHA3_Selftest(void); + +#endif /* SHA3_H */