diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dce851..124cc06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,8 @@ - fixed some variables names - fixed bug in addvanity (realloc problem with dirty memory) - Added option -6 to skip SHA256 checksum when you read the files (Improved startup process) -- Added warning when you Endomorphism and BSGS, THEY DON'T WORK together! +- Added warning when you Endomorphism and BSGS, THEY DON'T WORK together! +- Legacy version for ARM processor and other systems # Version 0.2.230430 Satoshi Quest - fixed typos in README diff --git a/Makefile b/Makefile index 0274009..8c2b94e 100644 --- a/Makefile +++ b/Makefile @@ -20,4 +20,19 @@ default: g++ -m64 -march=native -mtune=native -mssse3 -Wno-unused-result -Wno-write-strings -Ofast -ftree-vectorize -o keyhunt keyhunt.cpp base58.o rmd160.o hash/ripemd160.o hash/ripemd160_sse.o hash/sha256.o hash/sha256_sse.o bloom.o oldbloom.o xxhash.o util.o Int.o Point.o SECP256K1.o IntMod.o Random.o IntGroup.o sha3.o keccak.o -lm -lpthread rm -r *.o clean: - rm keyhunt \ No newline at end of file + rm keyhunt +legacy: + g++ -m64 -march=native -mtune=native -mssse3 -Wall -Wextra -Ofast -ftree-vectorize -flto -c oldbloom/bloom.cpp -o oldbloom.o + g++ -m64 -march=native -mtune=native -mssse3 -Wall -Wextra -Ofast -ftree-vectorize -flto -c bloom/bloom.cpp -o bloom.o + gcc -m64 -march=native -mtune=native -mssse3 -Wno-unused-result -Ofast -ftree-vectorize -c base58/base58.c -o base58.o + gcc -m64 -march=native -mtune=native -mssse3 -Wall -Wextra -Ofast -ftree-vectorize -c xxhash/xxhash.c -o xxhash.o + g++ -m64 -march=native -mtune=native -mssse3 -Wall -Wextra -Ofast -ftree-vectorize -c util.c -o util.o + g++ -m64 -march=native -mtune=native -mssse3 -Wall -Wextra -Ofast -ftree-vectorize -c hashing.c -o hashing.o -lcrypto + g++ -m64 -march=native -mtune=native -mssse3 -Wall -Wextra -Ofast -ftree-vectorize -c gmp256k1/Int.cpp -o Int.o -lgmp + g++ -m64 -march=native -mtune=native -mssse3 -Wall -Wextra -Ofast -ftree-vectorize -c gmp256k1/Point.cpp -o Point.o -lgmp + g++ -m64 -march=native -mtune=native -mssse3 -Wall -Wextra -Ofast -ftree-vectorize -c gmp256k1/GMP256K1.cpp -o GMP256K1.o -lgmp + g++ -m64 -march=native -mtune=native -mssse3 -Wall -Wextra -Ofast -ftree-vectorize -c gmp256k1/IntMod.cpp -o IntMod.o -lgmp + g++ -m64 -march=native -mtune=native -mssse3 -Wall -Wextra -Ofast -ftree-vectorize -flto -c gmp256k1/Random.cpp -o Random.o -lgmp + g++ -m64 -march=native -mtune=native -mssse3 -Wall -Wextra -Ofast -ftree-vectorize -flto -c gmp256k1/IntGroup.cpp -o IntGroup.o -lgmp + g++ -m64 -march=native -mtune=native -mssse3 -Wall -Wextra -Ofast -ftree-vectorize -o keyhunt keyhunt_legacy.cpp base58.o bloom.o oldbloom.o xxhash.o util.o Int.o Point.o GMP256K1.o IntMod.o IntGroup.o Random.o hashing.o -lm -lpthread -lcrypto -lgmp + rm -r *.o diff --git a/README.md b/README.md index e38c386..ccbf4c2 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,11 @@ Please install on your system - git - build-essential +for legacy version also you are going to need: + +- libssl-dev +- libgmp-dev + On Debian based systems, run this commands to update your current enviroment and install the tools needed to compile it @@ -72,6 +77,8 @@ and install the tools needed to compile it apt update && apt upgrade apt install git -y apt install build-essential -y +apt install libssl-dev -y +apt install libgmp-dev -y ``` To clone the repository @@ -92,6 +99,13 @@ First compile: make ``` +if you have problems compiling the `main` version you can compile the `legacy` version + +``` +make legacy +``` + + and then execute with `-h` to see the help ``` diff --git a/bloom/bloom.cpp b/bloom/bloom.cpp index 81a4ed5..324bd2b 100644 --- a/bloom/bloom.cpp +++ b/bloom/bloom.cpp @@ -136,7 +136,6 @@ int bloom_check(struct bloom * bloom, const void * buffer, int len) uint64_t b = XXH64(buffer, len, a); uint64_t x; uint8_t i; - int r; for (i = 0; i < bloom->hashes; i++) { x = (a + b*i) % bloom->bits; if (test_bit(bloom->bf, x)) { diff --git a/gmp256k1/GMP256K1.cpp b/gmp256k1/GMP256K1.cpp new file mode 100644 index 0000000..37bfc9d --- /dev/null +++ b/gmp256k1/GMP256K1.cpp @@ -0,0 +1,599 @@ + +#include +#include +#include +#include "GMP256K1.h" +#include "Point.h" +#include "../util.h" +#include "../hashing.h" + +Secp256K1::Secp256K1() { +} + +void Secp256K1::Init() { + // Prime for the finite field + P.SetBase16("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"); + + // Set up field + Int::SetupField(&P); + + // Generator point and order + G.x.SetBase16("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"); + G.y.SetBase16("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"); + G.z.SetInt32(1); + order.SetBase16("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"); + + Int::InitK1(&order); + + // Compute Generator table + Point N(G); + for(int i = 0; i < 32; i++) { + GTable[i * 256] = N; + N = DoubleDirect(N); + for (int j = 1; j < 255; j++) { + GTable[i * 256 + j] = N; + N = AddDirect(N, GTable[i * 256]); + } + GTable[i * 256 + 255] = N; // Dummy point for check function + } + +} + +Secp256K1::~Secp256K1() { +} + +Point Secp256K1::Negation(Point &p) { + Point Q; + Q.Clear(); + Q.x.Set(&p.x); + Q.y.Set(&this->P); + Q.y.Sub(&p.y); + Q.z.SetInt32(1); + return Q; +} + +Point Secp256K1::DoubleDirect(Point &p) { + Int _s; + Int _p; + Int a; + Point r; + r.z.SetInt32(1); + _s.ModMulK1(&p.x,&p.x); + _p.ModAdd(&_s,&_s); + _p.ModAdd(&_s); + + a.ModAdd(&p.y,&p.y); + a.ModInv(); + _s.ModMulK1(&_p,&a); // s = (3*pow2(p.x))*inverse(2*p.y); + + _p.ModMulK1(&_s,&_s); + a.ModAdd(&p.x,&p.x); + a.ModNeg(); + r.x.ModAdd(&a,&_p); // rx = pow2(s) + neg(2*p.x); + + a.ModSub(&r.x,&p.x); + + _p.ModMulK1(&a,&_s); + r.y.ModAdd(&_p,&p.y); + r.y.ModNeg(); // ry = neg(p.y + s*(ret.x+neg(p.x))); + return r; +} + +Int Secp256K1::GetY(Int x,bool isEven) { + Int y; + mpz_t _s,_p,y2; + mpz_inits(_s,_p,y2,NULL); + mpz_pow_ui(_s,x.num,3); + mpz_add_ui(y2,_s,7); + mpz_mod(y2,y2,P.num); + mpz_add_ui(_s,P.num,1); + mpz_fdiv_q_ui(_p,_s,4); + mpz_powm(y.num,y2,_p,P.num); + mpz_sub(_s,P.num,y.num); + if(mpz_tstbit(y.num, 0) == 1 && isEven){ + mpz_set(y.num,_s); + }else if (mpz_tstbit(y.num, 0) == 0 && !isEven) { + mpz_set(y.num,_s); + } + mpz_clears(_s,_p,y2,NULL); + return y; +} + +Point Secp256K1::ComputePublicKey(Int *privKey) { + //char *hextemp; + uint8_t buffer[32]; + int i = 0; + uint8_t b; + Point Q; + + Q.Clear(); + privKey->Get32Bytes(buffer); + for (i = 0; i < 32; i++) { + b = buffer[i]; + if(b) + break; + } + if(i == 32) + return Q; + Q = GTable[256 * (31 - i) + (b-1)]; + i++; + for(; i < 32; i++) { + b = buffer[i]; + if(b) + Q = Add2(Q, GTable[256 * (31 - i) + (b-1)]); + } + Q.Reduce(); + return Q; +} + +Point Secp256K1::NextKey(Point &key) { + // Input key must be reduced and different from G + // in order to use AddDirect + return AddDirect(key,G); +} + +bool Secp256K1::EC(Point &p) { + Int _s; + Int _p; + _s.ModSquareK1(&p.x); + _p.ModMulK1(&_s,&p.x); + _p.ModAdd(7); + _s.ModMulK1(&p.y,&p.y); + _s.ModSub(&_p); + return _s.IsZero(); // ( ((pow2(y) - (pow3(x) + 7)) % P) == 0 ); +} + + +bool Secp256K1::ParsePublicKeyHex(char *str,Point &ret,bool &isCompressed) { + char tempbuffer[65]; + int len = strlen(str); + ret.Clear(); + if (len < 2) { + printf("ParsePublicKeyHex: Error invalid public key specified (66 or 130 character length)\n"); + return false; + } + uint8_t type = GetByte(str, 0); + switch (type) { + case 0x02: + if (len != 66) { + printf("ParsePublicKeyHex: Error invalid public key specified (66 character length)\n"); + return false; + } + ret.x.SetBase16(str+2); + ret.y = GetY(ret.x, true); + isCompressed = true; + break; + + case 0x03: + if (len != 66) { + printf("ParsePublicKeyHex: Error invalid public key specified (66 character length)\n"); + return false; + } + ret.x.SetBase16(str+2); + ret.y = GetY(ret.x, false); + isCompressed = true; + break; + case 0x04: + if (len != 130) { + printf("ParsePublicKeyHex: Error invalid public key specified (130 character length)\n"); + return false; + } + strncpy(tempbuffer,str+2,64); + tempbuffer[64] = 0x00; + ret.x.SetBase16(tempbuffer); + ret.x.SetBase16(str+66); + isCompressed = false; + break; + default: + printf("ParsePublicKeyHex: Error invalid public key specified (Unexpected prefix (only 02,03 or 04 allowed)\n"); + return false; + } + + ret.z.SetInt32(1); + + if (!EC(ret)) { + printf("ParsePublicKeyHex: Error invalid public key specified (Not lie on elliptic curve)\n"); + return false; + } + return true; +} + +char* Secp256K1::GetPublicKeyHex(bool compressed, Point &pubKey) { + unsigned char publicKeyBytes[65]; + char *ret = NULL; + if (!compressed) { + //Uncompressed public key + publicKeyBytes[0] = 0x4; + pubKey.x.Get32Bytes(publicKeyBytes + 1); + pubKey.y.Get32Bytes(publicKeyBytes + 33); + ret = (char*) tohex((char*)publicKeyBytes,65); + } + else { + // Compressed public key + publicKeyBytes[0] = pubKey.y.IsEven() ? 0x02 : 0x03; + pubKey.x.Get32Bytes(publicKeyBytes + 1); + ret = (char*) tohex((char*)publicKeyBytes,33); + } + return ret; +} + + +/* + The caller of this function must asuste that there are enough space in dst pointer +*/ +void Secp256K1::GetPublicKeyHex(bool compressed, Point &pubKey,char *dst){ + unsigned char publicKeyBytes[65]; + if (!compressed) { + //Uncompressed public key + publicKeyBytes[0] = 0x4; + pubKey.x.Get32Bytes(publicKeyBytes + 1); + pubKey.y.Get32Bytes(publicKeyBytes + 33); + tohex_dst((char*)publicKeyBytes,65,dst); + } + else { + // Compressed public key + publicKeyBytes[0] = pubKey.y.IsEven() ? 0x2 : 0x3; + pubKey.x.Get32Bytes(publicKeyBytes + 1); + tohex_dst((char*)publicKeyBytes,33,dst); + } +} + + +char* Secp256K1::GetPublicKeyRaw(bool compressed, Point &pubKey) { + char *ret = (char*) malloc(65); + if(ret == NULL) { + ::fprintf(stderr,"Can't alloc memory\n"); + exit(0); + } + if (!compressed) { + //Uncompressed public key + ret[0] = 0x04; + pubKey.x.Get32Bytes((unsigned char*) (ret + 1)); + pubKey.y.Get32Bytes((unsigned char*) (ret + 33)); + } + else { + // Compressed public key + ret[0] = pubKey.y.IsEven() ? 0x02 : 0x03; + pubKey.x.Get32Bytes((unsigned char*) (ret + 1)); + } + return ret; +} + +/* + The caller of this function must asuste that there are enough space in dst pointer +*/ +void Secp256K1::GetPublicKeyRaw(bool compressed, Point &pubKey,char *dst) { + if (!compressed) { + //Uncompressed public key + dst[0] = 0x4; + pubKey.x.Get32Bytes((unsigned char*) (dst + 1)); + pubKey.y.Get32Bytes((unsigned char*) (dst + 33)); + } + else { + // Compressed public key + dst[0] = pubKey.y.IsEven() ? 0x2 : 0x3; + pubKey.x.Get32Bytes((unsigned char*) (dst + 1)); + } +} + +uint8_t Secp256K1::GetByte(char *str, int idx) { + char tmp[3]; + int val; + tmp[0] = str[2 * idx]; + tmp[1] = str[2 * idx + 1]; + tmp[2] = 0; + if (sscanf(tmp, "%X", &val) != 1) { + printf("ParsePublicKeyHex: Error invalid public key specified (unexpected hexadecimal digit)\n"); + exit(-1); + } + return (uint8_t)val; +} + + + + + + + +/* + +*/ + + +Point Secp256K1::AddDirect(Point &p1,Point &p2) { + Int _s; + Int _p; + Int dy; + Int dx; + Point r; + r.z.SetInt32(1); + + dy.ModSub(&p2.y,&p1.y); + dx.ModSub(&p2.x,&p1.x); + dx.ModInv(); + _s.ModMulK1(&dy,&dx); // s = (p2.y-p1.y)*inverse(p2.x-p1.x); + + _p.ModSquareK1(&_s); // _p = pow2(s) + + r.x.ModSub(&_p,&p1.x); + r.x.ModSub(&p2.x); // rx = pow2(s) - p1.x - p2.x; + + r.y.ModSub(&p2.x,&r.x); + r.y.ModMulK1(&_s); + r.y.ModSub(&p2.y); // ry = - p2.y - s*(ret.x-p2.x); + + return r; +} + +Point Secp256K1::Add2(Point &p1, Point &p2) { + // P2.z = 1 + Int u; + Int v; + Int u1; + Int v1; + Int vs2; + Int vs3; + Int us2; + Int a; + Int us2w; + Int vs2v2; + Int vs3u2; + Int _2vs2v2; + Point r; + u1.ModMulK1(&p2.y, &p1.z); + v1.ModMulK1(&p2.x, &p1.z); + u.ModSub(&u1, &p1.y); + v.ModSub(&v1, &p1.x); + us2.ModSquareK1(&u); + vs2.ModSquareK1(&v); + vs3.ModMulK1(&vs2, &v); + us2w.ModMulK1(&us2, &p1.z); + vs2v2.ModMulK1(&vs2, &p1.x); + _2vs2v2.ModAdd(&vs2v2, &vs2v2); + a.ModSub(&us2w, &vs3); + a.ModSub(&_2vs2v2); + + r.x.ModMulK1(&v, &a); + + vs3u2.ModMulK1(&vs3, &p1.y); + r.y.ModSub(&vs2v2, &a); + r.y.ModMulK1(&r.y, &u); + r.y.ModSub(&vs3u2); + + r.z.ModMulK1(&vs3, &p1.z); + return r; +} + + + +Point Secp256K1::Add(Point &p1,Point &p2) { + Int u; + Int v; + Int u1; + Int u2; + Int v1; + Int v2; + Int vs2; + Int vs3; + Int us2; + Int w; + Int a; + Int us2w; + Int vs2v2; + Int vs3u2; + Int _2vs2v2; + Int x3; + Int vs3y1; + Point r; + + + /* + U1 = Y2 * Z1 + U2 = Y1 * Z2 + V1 = X2 * Z1 + V2 = X1 * Z2 + if (V1 == V2) + if (U1 != U2) + return POINT_AT_INFINITY + else + return POINT_DOUBLE(X1, Y1, Z1) + U = U1 - U2 + V = V1 - V2 + W = Z1 * Z2 + A = U ^ 2 * W - V ^ 3 - 2 * V ^ 2 * V2 + X3 = V * A + Y3 = U * (V ^ 2 * V2 - A) - V ^ 3 * U2 + Z3 = V ^ 3 * W + return (X3, Y3, Z3) + */ + + u1.ModMulK1(&p2.y,&p1.z); + u2.ModMulK1(&p1.y,&p2.z); + v1.ModMulK1(&p2.x,&p1.z); + v2.ModMulK1(&p1.x,&p2.z); + u.ModSub(&u1,&u2); + v.ModSub(&v1,&v2); + w.ModMulK1(&p1.z,&p2.z); + us2.ModSquareK1(&u); + vs2.ModSquareK1(&v); + vs3.ModMulK1(&vs2,&v); + us2w.ModMulK1(&us2,&w); + vs2v2.ModMulK1(&vs2,&v2); + _2vs2v2.ModAdd(&vs2v2,&vs2v2); + a.ModSub(&us2w,&vs3); + a.ModSub(&_2vs2v2); + + r.x.ModMulK1(&v,&a); + + vs3u2.ModMulK1(&vs3,&u2); + r.y.ModSub(&vs2v2,&a); + r.y.ModMulK1(&r.y,&u); + r.y.ModSub(&vs3u2); + + r.z.ModMulK1(&vs3,&w); + + return r; + +} + +Point Secp256K1::Double(Point &p) { + + /* + if (Y == 0) + return POINT_AT_INFINITY + W = a * Z ^ 2 + 3 * X ^ 2 + S = Y * Z + B = X * Y*S + H = W ^ 2 - 8 * B + X' = 2*H*S + Y' = W*(4*B - H) - 8*Y^2*S^2 + Z' = 8*S^3 + return (X', Y', Z') + */ + + Int z2; + Int x2; + Int _3x2; + Int w; + Int s; + Int s2; + Int b; + Int _8b; + Int _8y2s2; + Int y2; + Int h; + Point r; + z2.ModSquareK1(&p.z); + z2.SetInt32(0); // a=0 + x2.ModSquareK1(&p.x); + _3x2.ModAdd(&x2,&x2); + _3x2.ModAdd(&x2); + w.ModAdd(&z2,&_3x2); + s.ModMulK1(&p.y,&p.z); + b.ModMulK1(&p.y,&s); + b.ModMulK1(&p.x); + h.ModSquareK1(&w); + _8b.ModAdd(&b,&b); + _8b.ModDouble(); + _8b.ModDouble(); + h.ModSub(&_8b); + r.x.ModMulK1(&h,&s); + r.x.ModAdd(&r.x); + s2.ModSquareK1(&s); + y2.ModSquareK1(&p.y); + _8y2s2.ModMulK1(&y2,&s2); + _8y2s2.ModDouble(); + _8y2s2.ModDouble(); + _8y2s2.ModDouble(); + r.y.ModAdd(&b,&b); + r.y.ModAdd(&r.y,&r.y); + r.y.ModSub(&h); + r.y.ModMulK1(&w); + r.y.ModSub(&_8y2s2); + r.z.ModMulK1(&s2,&s); + r.z.ModDouble(); + r.z.ModDouble(); + r.z.ModDouble(); + return r; +} + + +Point Secp256K1::ScalarMultiplication(Point &P,Int *scalar) { + Point R,Q,T,Dummy; + int no_of_bits, loop; + no_of_bits = scalar->GetBitLength(); + R.Clear(); + R.z.SetInt32(1); + if(!scalar->IsZero()) { + Q.Set(P); + if(scalar->GetBit(0) == 1) { + R.Set(P); + } + for(loop = 1; loop < no_of_bits; loop++) { + T = Double(Q); + Q.Set(T); + T.Set(R); + if(scalar->GetBit(loop)){ + R = Add(T,Q); + } + else { + Dummy = Add(T,Q); + } + } + } + R.Reduce(); + return R; +} + +void Secp256K1::GetHash160(int type, bool compressed, Point &pubKey, unsigned char *hash) { + unsigned char shapk[64]; + switch (type) { + case P2PKH: + case BECH32: + unsigned char publicKeyBytes[128]; + + if (!compressed) { + // Full public key + publicKeyBytes[0] = 0x4; + pubKey.x.Get32Bytes(publicKeyBytes + 1); + pubKey.y.Get32Bytes(publicKeyBytes + 33); + sha256(publicKeyBytes,65,shapk); + } else { + // Compressed public key + publicKeyBytes[0] = pubKey.y.IsEven() ? 0x2 : 0x3; + pubKey.x.Get32Bytes(publicKeyBytes + 1); + sha256(publicKeyBytes,33,shapk); + } + rmd160(shapk,32,hash); + + break; + case P2SH: + // Redeem Script (1 to 1 P2SH) + unsigned char script[64]; + script[0] = 0x00; // OP_0 + script[1] = 0x14; // PUSH 20 bytes + GetHash160(P2PKH, compressed, pubKey, script + 2); + sha256(script, 22, shapk); + rmd160(shapk,32,hash); + break; + } +} + +void Secp256K1::GetHash160(int type,bool compressed, + Point &k0,Point &k1,Point &k2,Point &k3, + uint8_t *h0,uint8_t *h1,uint8_t *h2,uint8_t *h3) { + GetHash160(type,compressed,k0,h0); + GetHash160(type,compressed,k1,h1); + GetHash160(type,compressed,k2,h2); + GetHash160(type,compressed,k3,h3); +} + + +void Secp256K1::GetHash160_fromX(int type,unsigned char prefix, + Int *k0,Int *k1,Int *k2,Int *k3, + uint8_t *h0,uint8_t *h1,uint8_t *h2,uint8_t *h3) { + unsigned char digests[4][33]; + int i; + switch (type) { + case P2PKH: + + k0->Get32Bytes((unsigned char*)(digests[0] + 1)); + k1->Get32Bytes((unsigned char*)(digests[1] + 1)); + k2->Get32Bytes((unsigned char*)(digests[2] + 1)); + k3->Get32Bytes((unsigned char*)(digests[3] + 1)); + for(i = 0; i < 4; i++) { + digests[i][0] = prefix; + sha256(digests[i],33,digests[i]); + } + rmd160(digests[0],32,h0); + rmd160(digests[1],32,h1); + rmd160(digests[2],32,h2); + rmd160(digests[3],32,h3); + break; + + case P2SH: + fprintf(stderr,"[E] Fixme unsopported case"); + exit(0); + break; + } +} \ No newline at end of file diff --git a/gmp256k1/GMP256K1.h b/gmp256k1/GMP256K1.h new file mode 100644 index 0000000..cd19a5f --- /dev/null +++ b/gmp256k1/GMP256K1.h @@ -0,0 +1,80 @@ +/* + This file is part of the Keyhunt distribution (https://github.com/albertobsd/keyhunt). + Copyright (c) 2020 Luis Alberto + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#ifndef SECP256K1H +#define SECP256K1H + +#include "Point.h" +#include + +// Address type +#define P2PKH 0 +#define P2SH 1 +#define BECH32 2 + + +class Secp256K1 { + +public: + + Secp256K1(); + ~Secp256K1(); + void Init(); + Point ComputePublicKey(Int *privKey); + Point Add(Point &p1, Point &p2); + Point Add2(Point &p1, Point &p2); + Point NextKey(Point &key); + bool EC(Point &p); + + void GetHash160_fromX(int type,unsigned char prefix, + Int *k0,Int *k1,Int *k2,Int *k3, + uint8_t *h0,uint8_t *h1,uint8_t *h2,uint8_t *h3); + bool ParsePublicKeyHex(char *str,Point &p,bool &isCompressed); + Point ScalarMultiplication(Point &P,Int *scalar); + char* GetPublicKeyHex(bool compressed, Point &p); + void GetPublicKeyHex(bool compressed, Point &pubKey,char *dst); + + char* GetPublicKeyRaw(bool compressed, Point &p); + void GetPublicKeyRaw(bool compressed, Point &pubKey,char *dst); + void GetHash160(int type,bool compressed, Point &pubKey, unsigned char *hash); + void GetHash160(int type,bool compressed, + Point &k0, Point &k1, Point &k2, Point &k3, + uint8_t *h0, uint8_t *h1, uint8_t *h2, uint8_t *h3); + + Point Negation(Point &p); + Point Double(Point &p); + Point DoubleDirect(Point &p); + Point AddDirect(Point &p1, Point &p2); + Point G; // Generator + Int P; // Prime for the finite field + Int order; // Curve order + +private: + + uint8_t GetByte(char *str,int idx); + Int GetY(Int x, bool isEven); + Point GTable[256*32]; // Generator table + +}; + +#endif // SECP256K1H diff --git a/gmp256k1/Int.cpp b/gmp256k1/Int.cpp new file mode 100644 index 0000000..735cc59 --- /dev/null +++ b/gmp256k1/Int.cpp @@ -0,0 +1,370 @@ +/* + * This file is part of the Keyhunt distribution (https://github.com/albertobsd/keyhunt). + * Copyright (c) 2023 albertobsd. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +// Big integer class (libgmp) + +#include "Int.h" +#include +#include +#include +#include + +#define U64STRINGSIZE 30 + +Int::Int() { + mpz_init_set_ui(num,0); +} + +Int::Int(const int32_t i32) { + mpz_init_set_si(num,i32); +} + +Int::Int(const uint32_t u32) { + mpz_init_set_ui(num,u32); +} + +Int::Int(const Int *other) { + mpz_init_set(num,other->num); +} + +Int::Int(const char *str) { + mpz_init_set_str(num,str,0); +} + +Int::Int(const uint64_t u64) { + char my_str_value[U64STRINGSIZE]; // 30 digits + null terminator + snprintf(my_str_value,U64STRINGSIZE, "%lu", u64); + mpz_init_set_str(num,my_str_value,0); +} + +Int::Int(const int64_t i64) { + char my_str_value[U64STRINGSIZE]; // 30 digits + null terminator + snprintf(my_str_value,U64STRINGSIZE,"%li", i64); + mpz_init_set_str(num,my_str_value,0); +} + +Int::Int(const Int &value) { + mpz_init_set(num,value.num); +} + + + +void Int::Add(const uint64_t u64) { + mpz_t value; + char my_str_value[U64STRINGSIZE]; // 30 digits + null terminator + snprintf(my_str_value,U64STRINGSIZE,"%lu", u64); + mpz_init_set_str(value,my_str_value,0); + mpz_add(num,num,value); + mpz_clear(value); +} + +void Int::Add(const uint32_t u32) { + mpz_add_ui(num,num,u32); +} + +void Int::Add(const Int *a) { + mpz_add(num,num,a->num); +} + +void Int::Add(const Int *a,const Int *b) { + mpz_add(num,num,a->num); + mpz_add(num,num,b->num); +} + +void Int::Sub(const uint32_t u32) { + mpz_sub_ui(num,num,u32); +} + +void Int::Sub(const uint64_t u64) { + mpz_t value; + char my_str_value[U64STRINGSIZE]; // 30 digits + null terminator + snprintf(my_str_value,U64STRINGSIZE,"%lu", u64); + mpz_init_set_str(value,my_str_value,0); + mpz_sub(num,num,value); + mpz_clear(value); +} + +void Int::Sub(Int *a) { + mpz_sub(num,num,a->num); +} + +void Int::Sub(Int *a, Int *b) { + mpz_sub(num,num,a->num); + mpz_sub(num,num,b->num); +} + +void Int::Mult(Int *a) { + mpz_mul(num,num,a->num); +} + +void Int::Mult(uint64_t u64) { + mpz_t value; + char my_str_value[U64STRINGSIZE]; // 30 digits + null terminator + snprintf(my_str_value,U64STRINGSIZE,"%lu", u64); + mpz_init_set_str(value,my_str_value,0); + mpz_mul(num,num,value); + mpz_clear(value); +} + +void Int::IMult(int64_t i64) { + mpz_t value; + char my_str_value[U64STRINGSIZE]; // 30 digits + null terminator + snprintf(my_str_value,U64STRINGSIZE,"%li", i64); + mpz_init_set_str(value,my_str_value,0); + mpz_mul(num,num,value); + mpz_clear(value); +} + +void Int::Neg() { + mpz_neg(num,num); +} + +void Int::Abs() { + mpz_abs(num,num); +} + +bool Int::IsGreater(Int *a) { + if(mpz_cmp(num,a->num) > 0) + return true; + return false; +} + +bool Int::IsGreaterOrEqual(Int *a) { + if(mpz_cmp(num,a->num) >= 0) + return true; + return false; +} + +bool Int::IsLowerOrEqual(Int *a) { + if(mpz_cmp(num,a->num) <= 0) + return true; + return false; +} + +bool Int::IsLower(Int *a) { + if(mpz_cmp(num,a->num) < 0) + return true; + return false; +} + +bool Int::IsEqual(Int *a) { + if(mpz_cmp(num,a->num) == 0) + return true; + return false; +} + +bool Int::IsZero() { + if(mpz_cmp_ui(num,0) == 0) + return true; + return false; +} + +bool Int::IsOne() { + if(mpz_cmp_ui(num,1) == 0) + return true; + return false; +} + +bool Int::IsPositive() { + if(mpz_cmp_ui(num,0) >= 0) + return true; + return false; +} + +bool Int::IsNegative() { + if(mpz_cmp_ui(num,0) < 0) + return true; + return false; +} + +bool Int::IsEven() { + if(mpz_tstbit(num,0) == 0) + return true; + return false; +} + +bool Int::IsOdd() { + if(mpz_tstbit(num,0) == 1) + return true; + return false; +} + +int Int::GetSize() { + int r = mpz_sizeinbase(num,2); + if(r % 8 == 0) + return (int)(r/8); + else + return (int)(r/8) + 1; +} + +int Int::GetBitLength() { + return mpz_sizeinbase(num,2); +} + +uint64_t Int::GetInt64() { + char *temp =NULL; + uint64_t r; + temp = mpz_get_str(NULL,10,num); + r = strtoull(temp,NULL,10); + free(temp); + return r; +} + +uint32_t Int::GetInt32() { + return mpz_get_ui(num); +} + +int Int::GetBit(uint32_t n) { + return mpz_tstbit(num,n); +} + + +void Int::Get32Bytes(unsigned char *buff) { + size_t count, size = this->GetSize(); + memset(buff, 0, 32); + mpz_export(buff + 32 - size, &count, 0, 1, 0, 0, num); +} + +void Int::Set32Bytes(unsigned char *buff) { + mpz_import(num,32,0,1,0,0,buff); +} + +unsigned char Int::GetByte(int n) { + unsigned char buffer[32]; + size_t count, size = this->GetSize(); + memset(buffer, 0, 32); + mpz_export(buffer + 32 - size, &count, 0, 1, 0, 0, num); + return buffer[n]; +} + +/* +void mpz_get_byte(mpz_t num, unsigned char* bytes, size_t index) { + size_t num_bytes = (mpz_sizeinbase(num, 2) + 7) / 8; // Calculate the total number of bytes + if (index < num_bytes) { + mpz_export(bytes, NULL, 1, sizeof(unsigned char), 0, 0, num); // Export the mpz_t variable to bytes + } else { + // Handle invalid index + printf("Error: Index out of range.\n"); + } +} +*/ + +/* +unsigned char Int::GetByte(unsigned char *buff) { + +} +*/ + +char* Int::GetBase2() { + return mpz_get_str(NULL,2,num); +} + +char* Int::GetBase10() { + return mpz_get_str(NULL,10,num); +} + +char* Int::GetBase16() { + return mpz_get_str(NULL,16,num); +} + +/* +char* Int::GetBaseN(int n,const char *charset); +char* Int::GetBlockStr(); +char* Int::GetC64Str(int nbDigit); +*/ + + +void Int::SetInt64(uint64_t value) { + char my_str_value[U64STRINGSIZE]; // 30 digits + null terminator + snprintf(my_str_value, U64STRINGSIZE, "%lu", value); + mpz_set_str(num,my_str_value,0); +} + +void Int::SetInt32(const uint32_t value) { + mpz_set_ui(num,value); +} + +void Int::Set(const Int* other) { + mpz_set(num,other->num); +} + +void Int::Set(const char *str) { + mpz_set_str(num,str,0); +} + +void Int::SetBase10(const char *str) { + mpz_set_str(num,str,10); +} + +void Int::SetBase16(const char *str) { + mpz_set_str(num,str,16); +} + +Int::~Int() { + mpz_clear(num); +} + +// Copy assignment operator +Int& Int::operator=(const Int& other) { + // Check for self-assignment + if (this == &other) { + return *this; + } + + // Assign the values from 'other' to the current object + mpz_set(num,other.num); + + // Return the current object + return *this; +} + +void Int::AddOne() { + mpz_add_ui(num,num,1); +} + +void Int::ShiftL(uint32_t n) { + mpz_mul_2exp(num,num,n); + +} + +void Int::Div(Int *a,Int *mod) { + if(mpz_cmp(num,a->num) < 0) { + if(mod) mpz_set(mod->num,num); + CLEAR(); + return; + } + if(mpz_cmp_ui(a->num,0) == 0) { + printf("Divide by 0!\n"); + return; + } + + if(mpz_cmp(num,a->num) == 0) { + if(mod) mod->CLEAR(); + mpz_set_ui(num,1); + return; + } + if(mod) { + mpz_fdiv_qr (num, mod->num, num, a->num); + } + else { + mpz_fdiv_q(num,num,a->num); + } +} + +void Int::CLEAR() { + mpz_set_ui(num,0); +} \ No newline at end of file diff --git a/gmp256k1/Int.h b/gmp256k1/Int.h new file mode 100644 index 0000000..4f60b44 --- /dev/null +++ b/gmp256k1/Int.h @@ -0,0 +1,153 @@ +/* + This file is part of the Keyhunt distribution (https://github.com/albertobsd/keyhunt). + Copyright (c) 2020 Luis Alberto + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +// Big integer class (GMP) + +#ifndef BIGINTH +#define BIGINTH + +#include "Random.h" +#include +#include +#include + +class Int { +public: + mpz_t num; + + Int(); + Int(const char*); + Int(const int32_t); + Int(const uint32_t); + Int(const int64_t); + Int(const uint64_t); + Int(const Int*); + Int(const Int&); + + /* Aritmetic*/ + void Add(const uint64_t); + void Add(const uint32_t); + void Add(const Int*); + void Add(const Int*,const Int*); + void AddOne(); + void Sub(const uint64_t); + void Sub(const uint32_t); + void Sub(Int *); + void Sub(Int *a, Int *b); + void Mult(Int *); + void Mult(uint64_t ); + void IMult(int64_t ); + + void Div(Int *a,Int *mod = NULL); + /* + void Mult(Int *a,uint64_t b); + void IMult(Int *a, int64_t b); + void Mult(Int *a,Int *b)M + */ + void Neg(); + void Abs(); + + bool IsGreater(Int *a); + bool IsGreaterOrEqual(Int *a); + bool IsLowerOrEqual(Int *a); + bool IsLower(Int *a); + bool IsEqual(Int *a); + bool IsZero(); + bool IsOne(); + //bool IsStrictPositive(); + bool IsPositive(); + bool IsNegative(); + bool IsEven(); + bool IsOdd(); + + /*Setters*/ + void SetInt64(const uint64_t value); + void SetInt32(const uint32_t value); + void Set(const Int* other); + void Set(const char *str); + void SetBase10(const char *str); + void SetBase16(const char *str); + + // Size + int GetSize(); + int GetBitLength(); + // + uint64_t GetInt64(); + uint32_t GetInt32(); + int GetBit(uint32_t n); + unsigned char GetByte(int n); + void Get32Bytes(unsigned char *buff); + void Set32Bytes(unsigned char *buff); + + char* GetBase2(); + char* GetBase10(); + char* GetBase16(); + /* + char* GetBaseN(int n,const char *charset); + char* GetBlockStr(); + char* GetC64Str(int nbDigit); + */ + // Left shift + void ShiftL(uint32_t n); + void Mod(Int *a); // this <- this (mod a) + + /* + All next mod n are setup as mod P, where P = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F + */ + void ModInv(); // this <- this^-1 (mod n) + void ModAdd(Int *a); // this <- this+a (mod n) [0. +*/ + +#include "IntGroup.h" + +using namespace std; + +IntGroup::IntGroup(int size) { + this->size = size; + subp = (Int *)calloc(size,sizeof(Int)); +} + +IntGroup::~IntGroup() { + free(subp); +} + +void IntGroup::Set(Int *pts) { + ints = pts; +} + +// Compute modular inversion of the whole group +void IntGroup::ModInv() { + + Int newValue; + Int inverse; + + subp[0].Set(&ints[0]); + for (int i = 1; i < size; i++) { + subp[i].ModMulK1(&subp[i - 1], &ints[i]); + } + + // Do the inversion + inverse.Set(&subp[size - 1]); + inverse.ModInv(); + + for (int i = size - 1; i > 0; i--) { + newValue.ModMulK1(&subp[i - 1], &inverse); + inverse.ModMulK1(&ints[i]); + ints[i].Set(&newValue); + } + + ints[0].Set(&inverse); + +} \ No newline at end of file diff --git a/gmp256k1/IntGroup.h b/gmp256k1/IntGroup.h new file mode 100644 index 0000000..1fb0104 --- /dev/null +++ b/gmp256k1/IntGroup.h @@ -0,0 +1,42 @@ +/* + This file is part of the Keyhunt distribution (https://github.com/albertobsd/keyhunt). + Copyright (c) 2020 Luis Alberto + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#ifndef INTGROUPH +#define INTGROUPH + +#include "Int.h" +#include + +class IntGroup { +public: + IntGroup(int size); + ~IntGroup(); + void Set(Int *pts); + void ModInv(); +private: + Int *ints; + Int *subp; + int size; +}; + +#endif // INTGROUPCPUH diff --git a/gmp256k1/IntMod.cpp b/gmp256k1/IntMod.cpp new file mode 100644 index 0000000..3bb581f --- /dev/null +++ b/gmp256k1/IntMod.cpp @@ -0,0 +1,144 @@ +#include "Int.h" + +static Int _P; // Field characteristic +static Int _R2o; // R^2 for SecpK1 order modular mult +static Int *_O; // Field Order + +void Int::Mod(Int *A) { + mpz_mod(num,num,A->num); +} + +void Int::ModInv() { + mpz_invert(num,num,_P.num); +} + +void Int::ModNeg() { + mpz_neg(num,num); + mpz_add(num,num,_P.num); +} + +void Int::ModAdd(Int *a) { + mpz_t p; + mpz_add(num,num,a->num); + mpz_init_set(p,num); + mpz_sub(p,p,_P.num); + if(mpz_cmp_ui(p,0) >= 0) + mpz_set(num,p); + mpz_clear(p); +} + + +void Int::ModAdd(uint32_t a) { + mpz_t p; + mpz_add_ui(num,num,a); + mpz_init_set(p,num); + mpz_sub(p,p,_P.num); + if(mpz_cmp_ui(p,0) >= 0) + mpz_set(num,p); + mpz_clear(p); +} + +void Int::ModAdd(Int *a, Int *b) { + mpz_t p; + mpz_add(num,a->num,b->num); + mpz_init_set(p,num); + mpz_sub(p,p,_P.num); + if(mpz_cmp_ui(p,0) >= 0) + mpz_set(num,p); + mpz_clear(p); +} + +void Int::ModMul(Int *a) { // this <- this*b (mod n) + mpz_mul(num,num,a->num); + mpz_mod(num,num,_P.num); +} + +void Int::ModMul(Int *a,Int *b) { // this <- a*b (mod n) + mpz_mul(num,a->num,b->num); + mpz_mod(num,num,_P.num); +} + +void Int::ModSub(Int *a) { + mpz_sub(num,num,a->num); + if (mpz_cmp_ui(num,0) < 0 ) + mpz_add(num,num,_P.num); +} + +void Int::ModSub(Int *a,Int *b) { + mpz_sub(num,a->num,b->num); + if (mpz_cmp_ui(num,0) < 0 ) + mpz_add(num,num,_P.num); +} + +void Int::ModSub(uint64_t a) { + Int A(a); + mpz_add(num,num,A.num); + if (mpz_cmp_ui(num,0) < 0) + mpz_add(num,num,_P.num); +} + + +void Int::ModMulK1(Int *a, Int *b) { + mpz_mul(num,a->num,b->num); + mpz_mod(num,num,_P.num); +} + +void Int::ModMulK1(Int *a) { + mpz_mul(num,num,a->num); + mpz_mod(num,num,_P.num); +} + + + +void Int::ModSquareK1(Int *a) { + mpz_powm_ui(num,a->num,2,_P.num); +} + +void Int::ModDouble() { + mpz_t p; + mpz_add(num,num,num); + mpz_init_set(p,num); + mpz_sub(p,p,_P.num); + if(mpz_cmp(p,0) > 0) { + mpz_set(num,p); + } + mpz_clear(p); +} + +void Int::ModSqrt() { + mpz_sqrt(num,num); + mpz_mod(num,num,_P.num); +} + +bool Int::HasSqrt() { + if(mpz_perfect_square_p(num) != 0) + return true; + return false; +} + + +/* Initializator of some Values P and N (Order) */ + +void Int::SetupField(Int *n) { + _P.Set(n); +} + +void Int::InitK1(Int *order) { + _O = order; + _R2o.SetBase16("9D671CD581C69BC5E697F5E45BCD07C6741496C20E7CF878896CF21467D7D140"); +} + +/* This next Opeations that have endin in order are modulo N */ + +void Int::ModMulK1order(Int *a) { + mpz_mul(num,num,a->num); + mpz_mod(num,num,_O->num); +} + +void Int::ModAddK1order(Int *a, Int *b) { + mpz_add(num,num,a->num); + mpz_add(num,num,b->num); + mpz_sub(num,num,_O->num); + if (mpz_cmp_ui(num,0) < 0 ) + mpz_add(num,num,_O->num); +} diff --git a/gmp256k1/Point.cpp b/gmp256k1/Point.cpp new file mode 100644 index 0000000..eabaf07 --- /dev/null +++ b/gmp256k1/Point.cpp @@ -0,0 +1,153 @@ +/* + * This file is part of the BSGS distribution (https://github.com/JeanLucPons/BSGS). + * Copyright (c) 2020 Jean Luc PONS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +#include "Point.h" +#include + +Point::Point() { + +} + +Point::Point(const Point &p) { + + //char *ptrs[3]; + mpz_set(x.num,p.x.num); + mpz_set(y.num,p.y.num); + mpz_set(z.num,p.z.num); + /* + ptrs[0] = x.GetBase16(); + ptrs[1] = y.GetBase16(); + ptrs[2] = z.GetBase16(); + printf("Point\n"); + printf("X: %s\n",ptrs[0]); + printf("Y: %s\n",ptrs[1]); + printf("Z: %s\n",ptrs[2]); + printf("End Point\n"); + for(int i = 0; i<3; i++) { + free(ptrs[i]); + } + */ +} + +Point::Point(Int *cx,Int *cy,Int *cz) { + mpz_set(x.num,cx->num); + mpz_set(y.num,cy->num); + mpz_set(z.num,cz->num); +} + +/* +Point::Point(Int *cx, Int *cz) { + x.Set(cx); + z.Set(cz); +} +*/ + +void Point::Clear() { + mpz_set_ui(x.num,0); + mpz_set_ui(y.num,0); + mpz_set_ui(z.num,0); +} + +void Point::Set(Int *cx, Int *cy,Int *cz) { + mpz_set(x.num,cx->num); + mpz_set(y.num,cy->num); + mpz_set(z.num,cz->num); +} + +Point::~Point() { + +} + +void Point::Set(Point &p) { + mpz_set(x.num,p.x.num); + mpz_set(y.num,p.y.num); + mpz_set(z.num,p.z.num); +} + +bool Point::isZero() { + return x.IsZero() && y.IsZero(); +} + +void Point::Reduce() { + Int i(&z); + i.ModInv(); + x.ModMul(&x,&i); + y.ModMul(&y,&i); + z.SetInt32(1); +/* +Yes, exactly. The Reduce function you mentioned converts the point from projective coordinates back to affine coordinates. + +In elliptic curve computations, it's often more efficient to work with projective coordinates because they allow addition and doubling operations to be performed without needing to do division operations, which are computationally expensive. + +However, at the end of your computation, or at certain intermediate stages, you might need to convert the point back to affine coordinates. That's what this Reduce function is doing. + +Here's what each line in Reduce is doing: + +Int i(&z); creates an integer i from the z coordinate of the point. +i.ModInv(); computes the modular inverse of i, effectively performing a division operation. Note that this operation is only valid if i is not zero. +x.ModMul(&x,&i); and y.ModMul(&y,&i); multiply the x and y coordinates by the modular inverse of z, effectively dividing them by z. This converts the x and y coordinates from projective back to affine coordinates. +z.SetInt32(1); sets the z coordinate to 1, completing the conversion to affine coordinates. +In the end, Reduce leaves the point in the form (X/Z, Y/Z, 1), which is equivalent to (X, Y) in affine coordinates. +*/ +} + +bool Point::equals(Point &p) { + return x.IsEqual(&p.x) && y.IsEqual(&p.y) && z.IsEqual(&p.z); +} + +// Copy assignment operator +Point& Point::operator=(const Point& other) { + // Check for self-assignment + if (this == &other) { + return *this; + } + //char *ptrs[3]; + // Assign the values from 'other' to the current object + mpz_set(x.num,other.x.num); + mpz_set(y.num,other.y.num); + mpz_set(z.num,other.z.num); + /* + ptrs[0] = x.GetBase16(); + ptrs[1] = y.GetBase16(); + ptrs[2] = z.GetBase16(); + printf("Point\n"); + printf("X: %s\n",ptrs[0]); + printf("Y: %s\n",ptrs[1]); + printf("Z: %s\n",ptrs[2]); + printf("End Point\n"); + for(int i = 0; i<3; i++) { + free(ptrs[i]); + } + */ + // Return the current object + return *this; +} + +void Point::print(const char *str) { + char *ptrs[3]; + ptrs[0] = x.GetBase16(); + ptrs[1] = y.GetBase16(); + ptrs[2] = z.GetBase16(); + printf("Point %s\n",str); + printf("X: %s\n",ptrs[0]); + printf("Y: %s\n",ptrs[1]); + printf("Z: %s\n",ptrs[2]); + printf("End Point\n"); + for(int i = 0; i<3; i++) { + free(ptrs[i]); + } +} \ No newline at end of file diff --git a/gmp256k1/Point.h b/gmp256k1/Point.h new file mode 100644 index 0000000..5c37321 --- /dev/null +++ b/gmp256k1/Point.h @@ -0,0 +1,48 @@ +/* + This file is part of the Keyhunt distribution (https://github.com/albertobsd/keyhunt). + Copyright (c) 2020 Luis Alberto + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#ifndef POINTH +#define POINTH + +#include "Int.h" + +class Point { +public: + Point(); + Point(Int *cx, Int *cy,Int *cz); + Point& operator=(const Point& other); + Point(const Point &p); + ~Point(); + bool isZero(); + bool equals(Point &p); + void Set(Point &p); + void Set(Int *cx, Int *cy,Int *cz); + void Clear(); + void Reduce(); + void print(const char *str); + Int x; + Int y; + Int z; +}; + +#endif // POINTH \ No newline at end of file diff --git a/gmp256k1/Random.cpp b/gmp256k1/Random.cpp new file mode 100644 index 0000000..9160714 --- /dev/null +++ b/gmp256k1/Random.cpp @@ -0,0 +1,94 @@ +#include +#include +#include +#include + + +#if defined(_WIN32) || defined(_WIN64) + #include + #include + #pragma comment(lib, "bcrypt.lib") +#elif __unix__ || __unix || __APPLE__ || __MACH__ || __CYGWIN__ + #include + #include + #include + #include + #if defined(GRND_NONBLOCK) + #define USE_GETRANDOM + #endif +#endif + +#include "Int.h" + +static int r_state_mt_ready = 0; +static gmp_randstate_t r_state_mt; + + +void int_randominit() { + if(r_state_mt_ready) { + fprintf(stderr,"r_state_mt already initialized, file %s, line %i\n",__FILE__,__LINE__ - 1); + exit(0); + } + mpz_t mpz_seed; + int bytes_readed,bytes = 64; + unsigned char seed[64]; + bytes_readed = random_bytes(seed, bytes); + if(bytes_readed != bytes) { + fprintf(stderr,"Error random_bytes(), file %s, line %i\n",__FILE__,__LINE__ - 2); + exit(0); + } + mpz_init(mpz_seed); + mpz_import(mpz_seed,bytes,1,sizeof(unsigned char),0,0,seed); + gmp_randinit_mt(r_state_mt); + gmp_randseed(r_state_mt,mpz_seed); + r_state_mt_ready = 1; + mpz_clear(mpz_seed); + memset(seed,0,bytes); +} + +void Int::Rand(int nbit) { + if(!r_state_mt_ready) { + fprintf(stderr,"Error Rand(), file %s, line %i\n",__FILE__,__LINE__ - 1); + exit(0); + } + mpz_urandomb(num,r_state_mt,nbit); + mpz_setbit(num,nbit-1); +} + +void Int::Rand(Int *min,Int *max) { + if(!r_state_mt_ready) { + fprintf(stderr,"Error Rand(), file %s, line %i\n",__FILE__,__LINE__ - 1); + exit(0); + } + Int diff(max); + diff.Sub(min); + this->Rand(256); + this->Mod(&diff); + this->Add(min); +} + +int random_bytes(unsigned char *buffer,int bytes) { + #if defined(_WIN32) || defined(_WIN64) + if (!BCryptGenRandom(NULL, buffer, length, BCRYPT_USE_SYSTEM_PREFERRED_RNG)) { + fprintf(stderr,"Not BCryptGenRandom available\n"); + exit(EXIT_FAILURE); + } + else + return bytes; + #elif __unix__ || __unix || __APPLE__ || __MACH__ || __CYGWIN__ + #ifdef USE_GETRANDOM + return syscall(SYS_getrandom, buffer, bytes, GRND_NONBLOCK); + #else + int fd = open("/dev/urandom", O_RDONLY); + if (fd == -1) { + fprintf(stderr,"Not /dev/urandom available\n"); + exit(EXIT_FAILURE); + } + ssize_t result = read(fd, buffer, bytes); + close(fd); + return result; + #endif + #else + #error "Unsupported platform" + #endif +} diff --git a/gmp256k1/Random.h b/gmp256k1/Random.h new file mode 100644 index 0000000..3c271dc --- /dev/null +++ b/gmp256k1/Random.h @@ -0,0 +1,30 @@ +/* + This file is part of the Keyhunt distribution (https://github.com/albertobsd/keyhunt). + Copyright (c) 2020 Luis Alberto + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#ifndef RANDOM_H +#define RANDOM_H + +void int_randominit(); +int random_bytes(unsigned char *buffer,int bytes); + +#endif \ No newline at end of file diff --git a/hashing.c b/hashing.c new file mode 100644 index 0000000..d95fb2f --- /dev/null +++ b/hashing.c @@ -0,0 +1,148 @@ +#include +#include +#include +#include "hashing.h" + +int sha256(const unsigned char *data, size_t length, unsigned char *digest) { + EVP_MD_CTX *mdctx; + const EVP_MD *md; + md = EVP_sha256(); + if(!md) { + printf("Unknown message digest sha256\n"); + return 1; + } + mdctx = EVP_MD_CTX_new(); + if(!mdctx) { + printf("Failed to create new EVP_MD_CTX\n"); + return 1; + } + if(EVP_DigestInit_ex(mdctx, md, NULL) != 1) { + printf("Failed to initialize EVP_Digest with sha256\n"); + EVP_MD_CTX_free(mdctx); + return 1; + } + if(EVP_DigestUpdate(mdctx, data, length) != 1) { + printf("Failed to update digest\n"); + EVP_MD_CTX_free(mdctx); + return 1; + } + unsigned int digest_len; + if(EVP_DigestFinal_ex(mdctx, digest, &digest_len) != 1) { + printf("Failed to finalize digest\n"); + EVP_MD_CTX_free(mdctx); + return 1; + } + EVP_MD_CTX_free(mdctx); + return 0; // Success +} + +// Function for hashing +int keccak(const unsigned char *data, size_t length, unsigned char *digest) { + EVP_MD_CTX *mdctx; + const EVP_MD *md; + md = EVP_get_digestbyname("keccak256"); + if(!md) { + printf("Unknown message digest keccak256\n"); + return 1; + } + mdctx = EVP_MD_CTX_new(); + if(!mdctx) { + printf("Failed to create new EVP_MD_CTX\n"); + return 1; + } + if(EVP_DigestInit_ex(mdctx, md, NULL) != 1) { + printf("Failed to initialize EVP_Digest with keccak256\n"); + EVP_MD_CTX_free(mdctx); + return 1; + } + if(EVP_DigestUpdate(mdctx, data, length) != 1) { + printf("Failed to update digest\n"); + EVP_MD_CTX_free(mdctx); + return 1; + } + unsigned int digest_len; + if(EVP_DigestFinal_ex(mdctx, digest, &digest_len) != 1) { + printf("Failed to finalize digest\n"); + EVP_MD_CTX_free(mdctx); + return 1; + } + EVP_MD_CTX_free(mdctx); + return 0; // Success +} + +int rmd160(const unsigned char *data, size_t length, unsigned char *digest) { + EVP_MD_CTX *mdctx; + const EVP_MD *md; + md = EVP_get_digestbyname("rmd160"); + if(!md) { + printf("Unknown message digest rmd160\n"); + return 1; + } + mdctx = EVP_MD_CTX_new(); + if(!mdctx) { + printf("Failed to create new EVP_MD_CTX\n"); + return 1; + } + if(EVP_DigestInit_ex(mdctx, md, NULL) != 1) { + printf("Failed to initialize EVP_Digest with rmd160\n"); + EVP_MD_CTX_free(mdctx); + return 1; + } + if(EVP_DigestUpdate(mdctx, data, length) != 1) { + printf("Failed to update digest\n"); + EVP_MD_CTX_free(mdctx); + return 1; + } + unsigned int digest_len; + if(EVP_DigestFinal_ex(mdctx, digest, &digest_len) != 1) { + printf("Failed to finalize digest\n"); + EVP_MD_CTX_free(mdctx); + return 1; + } + EVP_MD_CTX_free(mdctx); + return 0; // Success +} + +bool sha256_file(const char* file_name, uint8_t* digest) { + FILE* file = fopen(file_name, "rb"); + if (file == NULL) { + printf("Failed to open file: %s\n", file_name); + return false; + } + uint8_t buffer[8192]; // Buffer to read file contents + size_t bytes_read; + EVP_MD_CTX *mdctx; + const EVP_MD *md; + md = EVP_sha256(); + if(!md) { + printf("Unknown message digest sha256\n"); + return false; + } + mdctx = EVP_MD_CTX_new(); + if(!mdctx) { + printf("Failed to create new EVP_MD_CTX\n"); + return false; + } + if(EVP_DigestInit_ex(mdctx, md, NULL) != 1) { + printf("Failed to initialize EVP_Digest with sha256\n"); + EVP_MD_CTX_free(mdctx); + return false; + } + // Read file contents and update SHA256 context + while ((bytes_read = fread(buffer, 1, sizeof(buffer), file)) > 0) { + if(EVP_DigestUpdate(mdctx, buffer, bytes_read) != 1) { + printf("Failed to update digest\n"); + EVP_MD_CTX_free(mdctx); + return false; + } + } + unsigned int digest_len; + if(EVP_DigestFinal_ex(mdctx, digest, &digest_len) != 1) { + printf("Failed to finalize digest\n"); + EVP_MD_CTX_free(mdctx); + return 1; + } + EVP_MD_CTX_free(mdctx); + fclose(file); + return true; +} \ No newline at end of file diff --git a/hashing.h b/hashing.h new file mode 100644 index 0000000..2bd5a30 --- /dev/null +++ b/hashing.h @@ -0,0 +1,12 @@ +#ifndef HASHSING +#define HASHSING + +#include +#include + +int sha256(const unsigned char *data, size_t length, unsigned char *digest); +int rmd160(const unsigned char *data, size_t length, unsigned char *digest); +int keccak(const unsigned char *data, size_t length, unsigned char *digest); +bool sha256_file(const char* file_name, unsigned char * checksum); + +#endif // HASHSING \ No newline at end of file diff --git a/keyhunt_legacy.cpp b/keyhunt_legacy.cpp new file mode 100644 index 0000000..3ab09c8 --- /dev/null +++ b/keyhunt_legacy.cpp @@ -0,0 +1,7142 @@ +/* +Develop by Alberto +email: albertobsd@gmail.com +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "base58/libbase58.h" +#include "oldbloom/oldbloom.h" +#include "bloom/bloom.h" +#include "util.h" +#include "hashing.h" + +#include "gmp256k1/GMP256K1.h" +#include "gmp256k1/Point.h" +#include "gmp256k1/Int.h" +#include "gmp256k1/IntGroup.h" +#include "gmp256k1/Random.h" + + +#if defined(_WIN64) && !defined(__CYGWIN__) +#include "getopt.h" +#include +#else +#include +#include +#include +#endif + +#ifdef __unix__ +#ifdef __CYGWIN__ +#else +#include +#endif +#endif + +#define CRYPTO_NONE 0 +#define CRYPTO_BTC 1 +#define CRYPTO_ETH 2 +#define CRYPTO_ALL 3 + +#define MODE_XPOINT 0 +#define MODE_ADDRESS 1 +#define MODE_BSGS 2 +#define MODE_RMD160 3 +#define MODE_PUB2RMD 4 +#define MODE_MINIKEYS 5 +#define MODE_VANITY 6 + +#define SEARCH_UNCOMPRESS 0 +#define SEARCH_COMPRESS 1 +#define SEARCH_BOTH 2 + +uint32_t THREADBPWORKLOAD = 1048576; + +struct checksumsha256 { + char data[32]; + char backup[32]; +}; + +struct bsgs_xvalue { + uint8_t value[6]; + uint64_t index; +}; + +struct address_value { + uint8_t value[20]; +}; + +struct tothread { + int nt; //Number thread + char *rs; //range start + char *rpt; //rng per thread +}; + +struct bPload { + uint32_t threadid; + uint64_t from; + uint64_t to; + uint64_t counter; + uint64_t workload; + uint32_t aux; + uint32_t finished; +}; + +#if defined(_WIN64) && !defined(__CYGWIN__) +#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop)) +PACK(struct publickey +{ + uint8_t parity; + union { + uint8_t data8[32]; + uint32_t data32[8]; + uint64_t data64[4]; + } X; +}); +#else +struct __attribute__((__packed__)) publickey { + uint8_t parity; + union { + uint8_t data8[32]; + uint32_t data32[8]; + uint64_t data64[4]; + } X; +}; +#endif + +const char *Ccoinbuffer_default = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + +char *Ccoinbuffer = (char*) Ccoinbuffer_default; +char *str_baseminikey = NULL; +char *raw_baseminikey = NULL; +char *minikeyN = NULL; +int minikey_n_limit; + +const char *version = "0.2.230507 Satoshi Quest (legacy)"; + +#define CPU_GRP_SIZE 1024 +//reserve +std::vector Gn; +Point _2Gn; + +std::vector GSn; +Point _2GSn; + +/* +std::vector GSn2; +Point _2GSn2; + +std::vector GSn3; +Point _2GSn3; +*/ + +void menu(); +void init_generator(); + +int searchbinary(struct address_value *buffer,char *data,int64_t array_length); +void sleep_ms(int milliseconds); + +void _sort(struct address_value *arr,int64_t N); +void _insertionsort(struct address_value *arr, int64_t n); +void _introsort(struct address_value *arr,uint32_t depthLimit, int64_t n); +void _swap(struct address_value *a,struct address_value *b); +int64_t _partition(struct address_value *arr, int64_t n); +void _myheapsort(struct address_value *arr, int64_t n); +void _heapify(struct address_value *arr, int64_t n, int64_t i); + +void bsgs_sort(struct bsgs_xvalue *arr,int64_t n); +void bsgs_myheapsort(struct bsgs_xvalue *arr, int64_t n); +void bsgs_insertionsort(struct bsgs_xvalue *arr, int64_t n); +void bsgs_introsort(struct bsgs_xvalue *arr,uint32_t depthLimit, int64_t n); +void bsgs_swap(struct bsgs_xvalue *a,struct bsgs_xvalue *b); +void bsgs_heapify(struct bsgs_xvalue *arr, int64_t n, int64_t i); +int64_t bsgs_partition(struct bsgs_xvalue *arr, int64_t n); + +int bsgs_searchbinary(struct bsgs_xvalue *arr,char *data,int64_t array_length,uint64_t *r_value); +int bsgs_secondcheck(Int *start_range,uint32_t a,uint32_t k_index,Int *privatekey); +int bsgs_thirdcheck(Int *start_range,uint32_t a,uint32_t k_index,Int *privatekey); + +void sha256sse_22(uint8_t *src0, uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *dst0, uint8_t *dst1, uint8_t *dst2, uint8_t *dst3); +void sha256sse_23(uint8_t *src0, uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *dst0, uint8_t *dst1, uint8_t *dst2, uint8_t *dst3); + +bool vanityrmdmatch(unsigned char *rmdhash); +void writevanitykey(bool compress,Int *key); +int addvanity(char *target); +int minimum_same_bytes(unsigned char* A,unsigned char* B, int length); + +void writekey(bool compressed,Int *key); +void checkpointer(void *ptr,const char *file,const char *function,const char *name,int line); + +bool isBase58(char c); +bool isValidBase58String(char *str); + +bool readFileAddress(char *fileName); +bool readFileVanity(char *fileName); +bool forceReadFileAddress(char *fileName); +bool forceReadFileAddressEth(char *fileName); +bool forceReadFileXPoint(char *fileName); +bool processOneVanity(); + +bool initBloomFilter(struct bloom *bloom_arg,uint64_t items_bloom); + +void writeFileIfNeeded(const char *fileName); + +#if defined(_WIN64) && !defined(__CYGWIN__) +DWORD WINAPI thread_process_vanity(LPVOID vargp); +DWORD WINAPI thread_process_minikeys(LPVOID vargp); +DWORD WINAPI thread_process(LPVOID vargp); +DWORD WINAPI thread_process_bsgs(LPVOID vargp); +DWORD WINAPI thread_process_bsgs_backward(LPVOID vargp); +DWORD WINAPI thread_process_bsgs_both(LPVOID vargp); +DWORD WINAPI thread_process_bsgs_random(LPVOID vargp); +DWORD WINAPI thread_process_bsgs_dance(LPVOID vargp); +DWORD WINAPI thread_bPload(LPVOID vargp); +DWORD WINAPI thread_bPload_2blooms(LPVOID vargp); +DWORD WINAPI thread_pub2rmd(LPVOID vargp); +#else +void *thread_process_vanity(void *vargp); +void *thread_process_minikeys(void *vargp); +void *thread_process(void *vargp); +void *thread_process_bsgs(void *vargp); +void *thread_process_bsgs_backward(void *vargp); +void *thread_process_bsgs_both(void *vargp); +void *thread_process_bsgs_random(void *vargp); +void *thread_process_bsgs_dance(void *vargp); +void *thread_bPload(void *vargp); +void *thread_bPload_2blooms(void *vargp); +void *thread_pub2rmd(void *vargp); +#endif + +//char *publickeytohashrmd160(char *pkey,int length); +//void publickeytohashrmd160_dst(char *pkey,int length,char *dst); +char *pubkeytopubaddress(char *pkey,int length); +void pubkeytopubaddress_dst(char *pkey,int length,char *dst); +void rmd160toaddress_dst(char *rmd,char *dst); +void set_minikey(char *buffer,char *rawbuffer,int length); +bool increment_minikey_index(char *buffer,char *rawbuffer,int index); +void increment_minikey_N(char *rawbuffer); + + +void generate_binaddress_eth(Point &publickey,unsigned char *dst_address); + +int THREADOUTPUT = 0; +char *bit_range_str_min; +char *bit_range_str_max; + +const char *bsgs_modes[5] = {"sequential","backward","both","random","dance"}; +const char *modes[7] = {"xpoint","address","bsgs","rmd160","pub2rmd","minikeys","vanity"}; +const char *cryptos[3] = {"btc","eth","all"}; +const char *publicsearch[3] = {"uncompress","compress","both"}; +const char *default_fileName = "addresses.txt"; + +#if defined(_WIN64) && !defined(__CYGWIN__) +HANDLE* tid = NULL; +HANDLE write_keys; +HANDLE write_random; +HANDLE bsgs_thread; +HANDLE *bPload_mutex; +#else +pthread_t *tid = NULL; +pthread_mutex_t write_keys; +pthread_mutex_t write_random; +pthread_mutex_t bsgs_thread; +pthread_mutex_t *bPload_mutex; +#endif + +uint64_t FINISHED_THREADS_COUNTER = 0; +uint64_t FINISHED_THREADS_BP = 0; +uint64_t THREADCYCLES = 0; +uint64_t THREADCOUNTER = 0; +uint64_t FINISHED_ITEMS = 0; +uint64_t OLDFINISHED_ITEMS = -1; + +uint8_t byte_encode_crypto = 0x00; /* Bitcoin */ + + +int vanity_rmd_targets = 0; +int vanity_rmd_total = 0; +int *vanity_rmd_limits = NULL; +uint8_t ***vanity_rmd_limit_values_A = NULL,***vanity_rmd_limit_values_B = NULL; +int vanity_rmd_minimun_bytes_check_length = 999999; +char **vanity_address_targets = NULL; +struct bloom *vanity_bloom = NULL; + +struct bloom bloom; + +uint64_t *steps = NULL; +unsigned int *ends = NULL; +uint64_t N = 0; + +uint64_t N_SEQUENTIAL_MAX = 0x100000000; +uint64_t DEBUGCOUNT = 0x400; +uint64_t u64range; + +Int OUTPUTSECONDS; + +int FLAGSKIPCHECKSUM = 0; +int FLAGENDOMORPHISM = 0; + +int FLAGBLOOMMULTIPLIER = 1; +int FLAGVANITY = 0; +int FLAGBASEMINIKEY = 0; +int FLAGBSGSMODE = 0; +int FLAGDEBUG = 0; +int FLAGQUIET = 0; +int FLAGMATRIX = 0; +int KFACTOR = 1; +int MAXLENGTHADDRESS = -1; +int NTHREADS = 1; + +int FLAGSAVEREADFILE = 0; +int FLAGREADEDFILE1 = 0; +int FLAGREADEDFILE2 = 0; +int FLAGREADEDFILE3 = 0; +int FLAGREADEDFILE4 = 0; +int FLAGUPDATEFILE1 = 0; + + +int FLAGSTRIDE = 0; +int FLAGSEARCH = 2; +int FLAGBITRANGE = 0; +int FLAGRANGE = 0; +int FLAGFILE = 0; +int FLAGMODE = MODE_ADDRESS; +int FLAGCRYPTO = 0; +int FLAGRAWDATA = 0; +int FLAGRANDOM = 0; +int FLAG_N = 0; +int FLAGPRECALCUTED_P_FILE = 0; + +int bitrange; +char *str_N; +char *range_start; +char *range_end; +char *str_stride; +Int stride; + +uint64_t BSGS_XVALUE_RAM = 6; +uint64_t BSGS_BUFFERXPOINTLENGTH = 32; +uint64_t BSGS_BUFFERREGISTERLENGTH = 36; + +/* +BSGS Variables +*/ +int *bsgs_found; +std::vector OriginalPointsBSGS; +bool *OriginalPointsBSGScompressed; + +uint64_t bytes; +char checksum[32],checksum_backup[32]; +char buffer_bloom_file[1024]; +struct bsgs_xvalue *bPtable; +struct address_value *addressTable; + +struct oldbloom oldbloom_bP; + +struct bloom *bloom_bP; +struct bloom *bloom_bPx2nd; //2nd Bloom filter check +struct bloom *bloom_bPx3rd; //3rd Bloom filter check + +struct checksumsha256 *bloom_bP_checksums; +struct checksumsha256 *bloom_bPx2nd_checksums; +struct checksumsha256 *bloom_bPx3rd_checksums; + +#if defined(_WIN64) && !defined(__CYGWIN__) +std::vector bloom_bP_mutex; +std::vector bloom_bPx2nd_mutex; +std::vector bloom_bPx3rd_mutex; +#else +pthread_mutex_t *bloom_bP_mutex; +pthread_mutex_t *bloom_bPx2nd_mutex; +pthread_mutex_t *bloom_bPx3rd_mutex; +#endif + + + + +uint64_t bloom_bP_totalbytes = 0; +uint64_t bloom_bP2_totalbytes = 0; +uint64_t bloom_bP3_totalbytes = 0; +uint64_t bsgs_m = 4194304; +uint64_t bsgs_m2; +uint64_t bsgs_m3; +unsigned long int bsgs_aux; +uint32_t bsgs_point_number; + +const char *str_limits_prefixs[7] = {"Mkeys/s","Gkeys/s","Tkeys/s","Pkeys/s","Ekeys/s","Zkeys/s","Ykeys/s"}; +const char *str_limits[7] = {"1000000","1000000000","1000000000000","1000000000000000","1000000000000000000","1000000000000000000000","1000000000000000000000000"}; +Int int_limits[7]; + + + + +Int BSGS_GROUP_SIZE; +Int BSGS_CURRENT; +Int BSGS_R; +Int BSGS_AUX; +Int BSGS_N; +Int BSGS_M; //M is squareroot(N) +Int BSGS_M2; +Int BSGS_M3; +Int ONE; +Int ZERO; +Int MPZAUX; + +Point BSGS_P; //Original P is actually G, but this P value change over time for calculations +Point BSGS_MP; //MP values this is m * P +Point BSGS_MP2; //MP2 values this is m2 * P +Point BSGS_MP3; //MP3 values this is m3 * P + +std::vector BSGS_AMP2; +std::vector BSGS_AMP3; + +Point point_temp,point_temp2; //Temp value for some process + +Int n_range_start; +Int n_range_end; +Int n_range_diff; +Int n_range_aux; + +Int lambda,lambda2,beta,beta2; + +Secp256K1 *secp; + +int main(int argc, char **argv) { + char buffer[2048]; + char rawvalue[32]; + struct tothread *tt; //tothread + Tokenizer t,tokenizerbsgs; //tokenizer + char *fileName = NULL; + char *hextemp = NULL; + char *aux = NULL; + char *aux2 = NULL; + char *pointx_str = NULL; + char *pointy_str = NULL; + char *str_seconds = NULL; + char *str_total = NULL; + char *str_pretotal = NULL; + char *str_divpretotal = NULL; + char *bf_ptr = NULL; + char *bPload_threads_available; + FILE *fd,*fd_aux1,*fd_aux2,*fd_aux3; + uint64_t BASE,PERTHREAD_R,itemsbloom,itemsbloom2,itemsbloom3; + uint32_t finished; + int i,readed,continue_flag,check_flag,c,salir,index_value; + Int total,pretotal,debugcount_mpz,seconds,div_pretotal,int_aux,int_r,int_q,int58; + struct bPload *bPload_temp_ptr; + size_t rsize; + //if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); } + +#if defined(_WIN64) && !defined(__CYGWIN__) + DWORD s; + write_keys = CreateMutex(NULL, FALSE, NULL); + write_random = CreateMutex(NULL, FALSE, NULL); + bsgs_thread = CreateMutex(NULL, FALSE, NULL); +#else + pthread_mutex_init(&write_keys,NULL); + pthread_mutex_init(&write_random,NULL); + pthread_mutex_init(&bsgs_thread,NULL); + int s; +#endif + //if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); } + srand(time(NULL)); + + secp = new Secp256K1(); + secp->Init(); + OUTPUTSECONDS.SetInt32(30); + ZERO.SetInt32(0); + ONE.SetInt32(1); + BSGS_GROUP_SIZE.SetInt32(CPU_GRP_SIZE); + + int_randominit(); + + + + + + + + + + + //if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); } + + + + + + + + + + + + + + + + printf("[+] Version %s, developed by AlbertoBSD\n",version); + + while ((c = getopt(argc, argv, "deh6MqRSB:b:c:C:E:f:I:k:l:m:N:n:p:r:s:t:v:G:8:z:")) != -1) { + switch(c) { + case 'h': + menu(); + break; + case '6': + FLAGSKIPCHECKSUM = 1; + fprintf(stderr,"[W] Skipping checksums on files\n"); + break; + case 'B': + index_value = indexOf(optarg,bsgs_modes,5); + if(index_value >= 0 && index_value <= 4) { + FLAGBSGSMODE = index_value; + //printf("[+] BSGS mode %s\n",optarg); + } + else { + fprintf(stderr,"[W] Ignoring unknow bsgs mode %s\n",optarg); + } + break; + case 'b': + bitrange = strtol(optarg,NULL,10); + if(bitrange > 0 && bitrange <=256 ) { + MPZAUX.Set(&ONE); + MPZAUX.ShiftL(bitrange-1); + bit_range_str_min = MPZAUX.GetBase16(); + checkpointer((void *)bit_range_str_min,__FILE__,"malloc","bit_range_str_min" ,__LINE__ -1); + MPZAUX.Set(&ONE); + MPZAUX.ShiftL(bitrange); + if(MPZAUX.IsGreater(&secp->order)) { + MPZAUX.Set(&secp->order); + } + bit_range_str_max = MPZAUX.GetBase16(); + checkpointer((void *)bit_range_str_max,__FILE__,"malloc","bit_range_str_min" ,__LINE__ -1); + FLAGBITRANGE = 1; + } + else { + fprintf(stderr,"[E] invalid bits param: %s.\n",optarg); + } + break; + case 'c': + index_value = indexOf(optarg,cryptos,3); + switch(index_value) { + case 0: //btc + FLAGCRYPTO = CRYPTO_BTC; + break; + case 1: //eth + FLAGCRYPTO = CRYPTO_ETH; + printf("[+] Setting search for ETH adddress.\n"); + break; + /* + case 2: //all + FLAGCRYPTO = CRYPTO_ALL; + break; + */ + default: + FLAGCRYPTO = CRYPTO_NONE; + fprintf(stderr,"[E] Unknow crypto value %s\n",optarg); + exit(EXIT_FAILURE); + break; + } + break; + case 'C': + if(strlen(optarg) == 22) { + FLAGBASEMINIKEY = 1; + str_baseminikey = (char*) malloc(23); + checkpointer((void *)str_baseminikey,__FILE__,"malloc","str_baseminikey" ,__LINE__ - 1); + raw_baseminikey = (char*) malloc(23); + checkpointer((void *)raw_baseminikey,__FILE__,"malloc","raw_baseminikey" ,__LINE__ - 1); + strncpy(str_baseminikey,optarg,22); + for(i = 0; i< 21; i++) { + if(strchr(Ccoinbuffer,str_baseminikey[i+1]) != NULL) { + raw_baseminikey[i] = (int)(strchr(Ccoinbuffer,str_baseminikey[i+1]) - Ccoinbuffer) % 58; + } + else { + fprintf(stderr,"[E] invalid character in minikey\n"); + exit(EXIT_FAILURE); + } + + } + } + else { + fprintf(stderr,"[E] Invalid Minikey length %li : %s\n",strlen(optarg),optarg); + exit(EXIT_FAILURE); + } + + break; + case 'd': + FLAGDEBUG = 1; + printf("[+] Flag DEBUG enabled\n"); + break; + case 'e': + FLAGENDOMORPHISM = 1; + printf("[+] Endomorphism enabled\n"); + lambda.SetBase16("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72"); + lambda2.SetBase16("ac9c52b33fa3cf1f5ad9e3fd77ed9ba4a880b9fc8ec739c2e0cfc810b51283ce"); + beta.SetBase16("7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee"); + beta2.SetBase16("851695d49a83f8ef919bb86153cbcb16630fb68aed0a766a3ec693d68e6afa40"); + break; + case 'f': + FLAGFILE = 1; + fileName = optarg; + break; + case 'I': + FLAGSTRIDE = 1; + str_stride = optarg; + break; + case 'k': + KFACTOR = (int)strtol(optarg,NULL,10); + if(KFACTOR <= 0) { + KFACTOR = 1; + } + printf("[+] K factor %i\n",KFACTOR); + break; + + case 'l': + switch(indexOf(optarg,publicsearch,3)) { + case SEARCH_UNCOMPRESS: + FLAGSEARCH = SEARCH_UNCOMPRESS; + printf("[+] Search uncompress only\n"); + break; + case SEARCH_COMPRESS: + FLAGSEARCH = SEARCH_COMPRESS; + printf("[+] Search compress only\n"); + break; + case SEARCH_BOTH: + FLAGSEARCH = SEARCH_BOTH; + printf("[+] Search both compress and uncompress\n"); + break; + } + break; + case 'M': + FLAGMATRIX = 1; + printf("[+] Matrix screen\n"); + break; + case 'm': + switch(indexOf(optarg,modes,7)) { + case MODE_XPOINT: //xpoint + FLAGMODE = MODE_XPOINT; + printf("[+] Mode xpoint\n"); + break; + case MODE_ADDRESS: //address + FLAGMODE = MODE_ADDRESS; + printf("[+] Mode address\n"); + break; + case MODE_BSGS: + FLAGMODE = MODE_BSGS; + //printf("[+] Mode BSGS\n"); + break; + case MODE_RMD160: + FLAGMODE = MODE_RMD160; + FLAGCRYPTO = CRYPTO_BTC; + printf("[+] Mode rmd160\n"); + break; + case MODE_PUB2RMD: + FLAGMODE = MODE_PUB2RMD; + printf("[+] Mode pub2rmd\n"); + break; + case MODE_MINIKEYS: + FLAGMODE = MODE_MINIKEYS; + printf("[+] Mode minikeys\n"); + break; + case MODE_VANITY: + FLAGMODE = MODE_VANITY; + printf("[+] Mode vanity\n"); + if(vanity_bloom == NULL){ + vanity_bloom = (struct bloom*) calloc(1,sizeof(struct bloom)); + checkpointer((void *)vanity_bloom,__FILE__,"calloc","vanity_bloom" ,__LINE__ -1); + } + break; + default: + fprintf(stderr,"[E] Unknow mode value %s\n",optarg); + exit(EXIT_FAILURE); + break; + } + break; + case 'n': + FLAG_N = 1; + str_N = optarg; + break; + case 'q': + FLAGQUIET = 1; + printf("[+] Quiet thread output\n"); + break; + case 'R': + printf("[+] Random mode\n"); + FLAGRANDOM = 1; + FLAGBSGSMODE = 3; + break; + case 'r': + if(optarg != NULL) { + stringtokenizer(optarg,&t); + switch(t.n) { + case 1: + range_start = nextToken(&t); + if(isValidHex(range_start)) { + FLAGRANGE = 1; + range_end = secp->order.GetBase16(); + } + else { + fprintf(stderr,"[E] Invalid hexstring : %s.\n",range_start); + } + break; + case 2: + range_start = nextToken(&t); + range_end = nextToken(&t); + if(isValidHex(range_start) && isValidHex(range_end)) { + FLAGRANGE = 1; + } + else { + if(isValidHex(range_start)) { + fprintf(stderr,"[E] Invalid hexstring : %s\n",range_start); + } + else { + fprintf(stderr,"[E] Invalid hexstring : %s\n",range_end); + } + } + break; + default: + printf("[E] Unknow number of Range Params: %i\n",t.n); + break; + } + } + break; + case 's': + OUTPUTSECONDS.SetBase10(optarg); + if(OUTPUTSECONDS.IsLower(&ZERO)) { + OUTPUTSECONDS.SetInt32(30); + } + if(OUTPUTSECONDS.IsZero()) { + printf("[+] Turn off stats output\n"); + } + else { + hextemp = OUTPUTSECONDS.GetBase10(); + printf("[+] Stats output every %s seconds\n",hextemp); + free(hextemp); + } + break; + case 'S': + FLAGSAVEREADFILE = 1; + break; + case 't': + NTHREADS = strtol(optarg,NULL,10); + if(NTHREADS <= 0) { + NTHREADS = 1; + } + printf((NTHREADS > 1) ? "[+] Threads : %u\n": "[+] Thread : %u\n",NTHREADS); + break; + case 'v': + FLAGVANITY = 1; + if(vanity_bloom == NULL){ + vanity_bloom = (struct bloom*) calloc(1,sizeof(struct bloom)); + checkpointer((void *)vanity_bloom,__FILE__,"calloc","vanity_bloom" ,__LINE__ -1); + } + if(isValidBase58String(optarg)) { + if(addvanity(optarg) > 0) { + printf("[+] Added Vanity search : %s\n",optarg); + } + else { + printf("[+] Vanity search \"%s\" was NOT Added\n",optarg); + } + } + else { + fprintf(stderr,"[+] The string \"%s\" is not Valid Base58\n",optarg); + } + + break; + case '8': + if(strlen(optarg) == 58) { + Ccoinbuffer = optarg; + printf("[+] Base58 for Minikeys %s\n",Ccoinbuffer); + } + else { + fprintf(stderr,"[E] The base58 alphabet must be 58 characters long.\n"); + exit(EXIT_FAILURE); + } + break; + case 'z': + FLAGBLOOMMULTIPLIER= strtol(optarg,NULL,10); + if(FLAGBLOOMMULTIPLIER <= 0) { + FLAGBLOOMMULTIPLIER = 1; + } + printf("[+] Bloom Size Multiplier %i\n",FLAGBLOOMMULTIPLIER); + break; + default: + fprintf(stderr,"[E] Unknow opcion -%c\n",c); + exit(EXIT_FAILURE); + break; + } + } + //if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); } + if( FLAGBSGSMODE == MODE_BSGS && FLAGENDOMORPHISM) { + fprintf(stderr,"[E] Endomorphism doesn't work with BSGS\n"); + exit(EXIT_FAILURE); + } + + //if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); } + if( ( FLAGBSGSMODE == MODE_BSGS || FLAGBSGSMODE == MODE_PUB2RMD ) && FLAGSTRIDE) { + fprintf(stderr,"[E] Stride doesn't work with BSGS, pub2rmd\n"); + exit(EXIT_FAILURE); + } + if(FLAGSTRIDE) { + if(str_stride[0] == '0' && str_stride[1] == 'x') { + stride.SetBase16(str_stride+2); + } + else{ + stride.SetBase10(str_stride); + } + printf("[+] Stride : %s\n",stride.GetBase10()); + } + else { + FLAGSTRIDE = 1; + stride.Set(&ONE); + } + //if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); } + init_generator(); + //if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); } + if(FLAGMODE == MODE_BSGS ) { + printf("[+] Mode BSGS %s\n",bsgs_modes[FLAGBSGSMODE]); + } + + if(FLAGFILE == 0) { + fileName =(char*) default_fileName; + } + //if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); } + if(FLAGMODE == MODE_ADDRESS && FLAGCRYPTO == CRYPTO_NONE) { //When none crypto is defined the default search is for Bitcoin + FLAGCRYPTO = CRYPTO_BTC; + printf("[+] Setting search for btc adddress\n"); + } + if(FLAGRANGE) { + n_range_start.SetBase16(range_start); + if(n_range_start.IsZero()) { + n_range_start.AddOne(); + } + n_range_end.SetBase16(range_end); + if(n_range_start.IsEqual(&n_range_end) == false ) { + if( n_range_start.IsLower(&secp->order) && n_range_end.IsLowerOrEqual(&secp->order) ) { + if( n_range_start.IsGreater(&n_range_end)) { + fprintf(stderr,"[W] Opps, start range can't be great than end range. Swapping them\n"); + n_range_aux.Set(&n_range_start); + n_range_start.Set(&n_range_end); + n_range_end.Set(&n_range_aux); + } + n_range_diff.Set(&n_range_end); + n_range_diff.Sub(&n_range_start); + } + else { + fprintf(stderr,"[E] Start and End range can't be great than N\nFallback to random mode!\n"); + FLAGRANGE = 0; + } + } + else { + fprintf(stderr,"[E] Start and End range can't be the same\nFallback to random mode!\n"); + FLAGRANGE = 0; + } + } + if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); } + if(FLAGMODE != MODE_BSGS && FLAGMODE != MODE_MINIKEYS) { + BSGS_N.SetInt32(DEBUGCOUNT); + if(FLAGRANGE == 0 && FLAGBITRANGE == 0) { + n_range_start.SetInt32(1); + n_range_end.Set(&secp->order); + n_range_diff.Set(&n_range_end); + n_range_diff.Sub(&n_range_start); + } + else { + if(FLAGBITRANGE) { + n_range_start.SetBase16(bit_range_str_min); + n_range_end.SetBase16(bit_range_str_max); + n_range_diff.Set(&n_range_end); + n_range_diff.Sub(&n_range_start); + } + else { + if(FLAGRANGE == 0) { + fprintf(stderr,"[W] WTF!\n"); + } + } + } + } + N = 0; + if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); } + if(FLAGMODE != MODE_BSGS ) { + if(FLAG_N){ + if(str_N[0] == '0' && str_N[1] == 'x') { + N_SEQUENTIAL_MAX =strtol(str_N,NULL,16); + } + else { + N_SEQUENTIAL_MAX =strtol(str_N,NULL,10); + } + + if(N_SEQUENTIAL_MAX < 1024) { + fprintf(stderr,"[I] n value need to be equal or great than 1024, back to defaults\n"); + FLAG_N = 0; + N_SEQUENTIAL_MAX = 0x100000000; + } + if(N_SEQUENTIAL_MAX % 1024 != 0) { + fprintf(stderr,"[I] n value need to be multiplier of 1024\n"); + FLAG_N = 0; + N_SEQUENTIAL_MAX = 0x100000000; + } + } + printf("[+] N = %p\n",(void*)N_SEQUENTIAL_MAX); + if(FLAGMODE == MODE_MINIKEYS) { + BSGS_N.SetInt32(DEBUGCOUNT); + if(FLAGBASEMINIKEY) { + printf("[+] Base Minikey : %s\n",str_baseminikey); + } + minikeyN = (char*) malloc(22); + checkpointer((void *)minikeyN,__FILE__,"malloc","minikeyN" ,__LINE__ -1); + i =0; + int58.SetInt32(58); + int_aux.SetInt64(N_SEQUENTIAL_MAX); + int_aux.Mult(253); + /* We get approximately one valid mini key for each 256 candidates mini keys since this is only statistics we multiply N_SEQUENTIAL_MAX by 253 to ensure not missed one one candidate minikey between threads... in this approach we repeat from 1 to 3 candidates in each N_SEQUENTIAL_MAX cycle IF YOU FOUND some other workaround please let me know */ + i = 20; + salir = 0; + do { + if(!int_aux.IsZero()) { + int_r.Set(&int_aux); + int_r.Mod(&int58); + int_q.Set(&int_aux); + minikeyN[i] = (uint8_t)int_r.GetInt64(); + int_q.Sub(&int_r); + int_q.Div(&int58); + int_aux.Set(&int_q); + i--; + } + else { + salir =1; + } + }while(!salir && i > 0); + minikey_n_limit = 21 -i; + } + else { + if(FLAGBITRANGE) { // Bit Range + printf("[+] Bit Range %i\n",bitrange); + } + else { + printf("[+] Range \n"); + } + } + if(FLAGMODE != MODE_MINIKEYS) { + hextemp = n_range_start.GetBase16(); + printf("[+] -- from : 0x%s\n",hextemp); + free(hextemp); + hextemp = n_range_end.GetBase16(); + printf("[+] -- to : 0x%s\n",hextemp); + free(hextemp); + } + + switch(FLAGMODE) { + case MODE_MINIKEYS: + case MODE_PUB2RMD: + case MODE_RMD160: + case MODE_ADDRESS: + case MODE_XPOINT: + if(!readFileAddress(fileName)) { + fprintf(stderr,"[E] Unenexpected error\n"); + exit(EXIT_FAILURE); + } + break; + case MODE_VANITY: + if(!readFileVanity(fileName)) { + fprintf(stderr,"[E] Unenexpected error\n"); + exit(EXIT_FAILURE); + } + break; + } + if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); } + if(FLAGMODE != MODE_VANITY && !FLAGREADEDFILE1) { + printf("[+] Sorting data ..."); + _sort(addressTable,N); + printf(" done! %" PRIu64 " values were loaded and sorted\n",N); + writeFileIfNeeded(fileName); + } + } + if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); } + if(FLAGMODE == MODE_BSGS ) { + printf("[+] Opening file %s\n",fileName); + fd = fopen(fileName,"rb"); + if(fd == NULL) { + fprintf(stderr,"[E] Can't open file %s\n",fileName); + exit(EXIT_FAILURE); + } + aux = (char*) malloc(1024); + checkpointer((void *)aux,__FILE__,"malloc","aux" ,__LINE__ - 1); + while(!feof(fd)) { + if(fgets(aux,1022,fd) == aux) { + trim(aux," \t\n\r"); + if(strlen(aux) >= 128) { //Length of a full address in hexadecimal without 04 + N++; + }else { + if(strlen(aux) >= 66) { + N++; + } + } + } + } + if(N == 0) { + fprintf(stderr,"[E] There is no valid data in the file\n"); + exit(EXIT_FAILURE); + } + bsgs_found = (int*) calloc(N,sizeof(int)); + checkpointer((void *)bsgs_found,__FILE__,"calloc","bsgs_found" ,__LINE__ -1 ); + OriginalPointsBSGS.resize(N,secp->G); + OriginalPointsBSGScompressed = (bool*) malloc(N*sizeof(bool)); + checkpointer((void *)OriginalPointsBSGScompressed,__FILE__,"malloc","OriginalPointsBSGScompressed" ,__LINE__ -1 ); + pointx_str = (char*) malloc(65); + checkpointer((void *)pointx_str,__FILE__,"malloc","pointx_str" ,__LINE__ -1 ); + pointy_str = (char*) malloc(65); + checkpointer((void *)pointy_str,__FILE__,"malloc","pointy_str" ,__LINE__ -1 ); + fseek(fd,0,SEEK_SET); + i = 0; + while(!feof(fd)) { + if(fgets(aux,1022,fd) == aux) { + trim(aux," \t\n\r"); + if(strlen(aux) >= 66) { + stringtokenizer(aux,&tokenizerbsgs); + aux2 = nextToken(&tokenizerbsgs); + memset(pointx_str,0,65); + memset(pointy_str,0,65); + switch(strlen(aux2)) { + case 66: //Compress + if(secp->ParsePublicKeyHex(aux2,OriginalPointsBSGS[i],OriginalPointsBSGScompressed[i])) { + i++; + } + else { + N--; + } + + break; + case 130: //With the 04 + + if(secp->ParsePublicKeyHex(aux2,OriginalPointsBSGS[i],OriginalPointsBSGScompressed[i])) { + i++; + } + else { + N--; + } + + break; + default: + printf("Invalid length: %s\n",aux2); + N--; + break; + } + freetokenizer(&tokenizerbsgs); + } + } + } + fclose(fd); + bsgs_point_number = N; + if(bsgs_point_number > 0) { + printf("[+] Added %u points from file\n",bsgs_point_number); + } + else { + fprintf(stderr,"[E] The file don't have any valid publickeys\n"); + exit(EXIT_FAILURE); + } + BSGS_N.SetInt32(0); + BSGS_M.SetInt32(0); + + + BSGS_M.SetInt64(bsgs_m); + + + if(FLAG_N) { //Custom N by the -n param + + /* Here we need to validate if the given string is a valid hexadecimal number or a base 10 number*/ + + /* Now the conversion*/ + if(str_N[0] == '0' && str_N[1] == 'x' ) { /*We expected a hexadecimal value after 0x -> str_N +2 */ + BSGS_N.SetBase16((char*)(str_N+2)); + } + else { + BSGS_N.SetBase10(str_N); + } + + } + else { //Default N + BSGS_N.SetInt64((uint64_t)0x100000000000); + } + + if(BSGS_N.HasSqrt()) { //If the root is exact + BSGS_M.Set(&BSGS_N); + BSGS_M.ModSqrt(); + } + else { + fprintf(stderr,"[E] -n param doesn't have exact square root\n"); + exit(EXIT_FAILURE); + } + + BSGS_AUX.Set(&BSGS_M); + BSGS_AUX.Mod(&BSGS_GROUP_SIZE); + + if(!BSGS_AUX.IsZero()){ //If M is not divisible by BSGS_GROUP_SIZE (1024) + hextemp = BSGS_GROUP_SIZE.GetBase10(); + fprintf(stderr,"[E] M value is not divisible by %s\n",hextemp); + exit(EXIT_FAILURE); + } + + bsgs_m = BSGS_M.GetInt64(); + + if(FLAGRANGE || FLAGBITRANGE) { + if(FLAGBITRANGE) { // Bit Range + n_range_start.SetBase16(bit_range_str_min); + n_range_end.SetBase16(bit_range_str_max); + + n_range_diff.Set(&n_range_end); + n_range_diff.Sub(&n_range_start); + printf("[+] Bit Range %i\n",bitrange); + printf("[+] -- from : 0x%s\n",bit_range_str_min); + printf("[+] -- to : 0x%s\n",bit_range_str_max); + } + else { + printf("[+] Range \n"); + printf("[+] -- from : 0x%s\n",range_start); + printf("[+] -- to : 0x%s\n",range_end); + } + } + else { //Random start + + n_range_start.SetInt32(1); + n_range_end.Set(&secp->order); + n_range_diff.Rand(&n_range_start,&n_range_end); + n_range_start.Set(&n_range_diff); + } + BSGS_CURRENT.Set(&n_range_start); + + + if(n_range_diff.IsLower(&BSGS_N) ) { + fprintf(stderr,"[E] the given range is small\n"); + exit(EXIT_FAILURE); + } + + /* + M 2199023255552 + 109951162777.6 + M2 109951162778 + 5497558138.9 + M3 5497558139 + */ + + BSGS_M.Mult((uint64_t)KFACTOR); + BSGS_AUX.SetInt32(32); + BSGS_R.Set(&BSGS_M); + BSGS_R.Mod(&BSGS_AUX); + BSGS_M2.Set(&BSGS_M); + BSGS_M2.Div(&BSGS_AUX); + + if(!BSGS_R.IsZero()) { /* If BSGS_M modulo 32 is not 0*/ + BSGS_M2.AddOne(); + } + + BSGS_R.Set(&BSGS_M2); + BSGS_R.Mod(&BSGS_AUX); + + BSGS_M3.Set(&BSGS_M2); + BSGS_M3.Div(&BSGS_AUX); + + if(!BSGS_R.IsZero()) { /* If BSGS_M2 modulo 32 is not 0*/ + BSGS_M3.AddOne(); + } + + bsgs_m2 = BSGS_M2.GetInt64(); + bsgs_m3 = BSGS_M3.GetInt64(); + + BSGS_AUX.Set(&BSGS_N); + BSGS_AUX.Div(&BSGS_M); + + BSGS_R.Set(&BSGS_N); + BSGS_R.Mod(&BSGS_M); + + if(!BSGS_R.IsZero()) { /* if BSGS_N modulo BSGS_M is not 0*/ + BSGS_N.Set(&BSGS_M); + BSGS_N.Mult(&BSGS_AUX); + } + + bsgs_m = BSGS_M.GetInt64(); + bsgs_aux = BSGS_AUX.GetInt64(); + + + hextemp = BSGS_N.GetBase16(); + printf("[+] N = 0x%s\n",hextemp); + free(hextemp); + if(((uint64_t)(bsgs_m/256)) > 10000) { + itemsbloom = (uint64_t)(bsgs_m / 256); + if(bsgs_m % 256 != 0 ) { + itemsbloom++; + } + } + else{ + itemsbloom = 1000; + } + + if(((uint64_t)(bsgs_m2/256)) > 1000) { + itemsbloom2 = (uint64_t)(bsgs_m2 / 256); + if(bsgs_m2 % 256 != 0) { + itemsbloom2++; + } + } + else { + itemsbloom2 = 1000; + } + + if(((uint64_t)(bsgs_m3/256)) > 1000) { + itemsbloom3 = (uint64_t)(bsgs_m3/256); + if(bsgs_m3 % 256 != 0 ) { + itemsbloom3++; + } + } + else { + itemsbloom3 = 1000; + } + + printf("[+] Bloom filter for %" PRIu64 " elements ",bsgs_m); + bloom_bP = (struct bloom*)calloc(256,sizeof(struct bloom)); + checkpointer((void *)bloom_bP,__FILE__,"calloc","bloom_bP" ,__LINE__ -1 ); + bloom_bP_checksums = (struct checksumsha256*)calloc(256,sizeof(struct checksumsha256)); + checkpointer((void *)bloom_bP_checksums,__FILE__,"calloc","bloom_bP_checksums" ,__LINE__ -1 ); + +#if defined(_WIN64) && !defined(__CYGWIN__) + bloom_bP_mutex = (HANDLE*) calloc(256,sizeof(HANDLE)); + +#else + bloom_bP_mutex = (pthread_mutex_t*) calloc(256,sizeof(pthread_mutex_t)); +#endif + checkpointer((void *)bloom_bP_mutex,__FILE__,"calloc","bloom_bP_mutex" ,__LINE__ -1 ); + + + fflush(stdout); + bloom_bP_totalbytes = 0; + for(i=0; i< 256; i++) { +#if defined(_WIN64) && !defined(__CYGWIN__) + bloom_bP_mutex[i] = CreateMutex(NULL, FALSE, NULL); +#else + pthread_mutex_init(&bloom_bP_mutex[i],NULL); +#endif + if(bloom_init2(&bloom_bP[i],itemsbloom,0.000001) == 1){ + fprintf(stderr,"[E] error bloom_init _ [%i]\n",i); + exit(EXIT_FAILURE); + } + bloom_bP_totalbytes += bloom_bP[i].bytes; + //if(FLAGDEBUG) bloom_print(&bloom_bP[i]); + } + printf(": %.2f MB\n",(float)((float)(uint64_t)bloom_bP_totalbytes/(float)(uint64_t)1048576)); + + + printf("[+] Bloom filter for %" PRIu64 " elements ",bsgs_m2); + +#if defined(_WIN64) && !defined(__CYGWIN__) + bloom_bPx2nd_mutex = (HANDLE*) calloc(256,sizeof(HANDLE)); +#else + bloom_bPx2nd_mutex = (pthread_mutex_t*) calloc(256,sizeof(pthread_mutex_t)); +#endif + checkpointer((void *)bloom_bPx2nd_mutex,__FILE__,"calloc","bloom_bPx2nd_mutex" ,__LINE__ -1 ); + bloom_bPx2nd = (struct bloom*)calloc(256,sizeof(struct bloom)); + checkpointer((void *)bloom_bPx2nd,__FILE__,"calloc","bloom_bPx2nd" ,__LINE__ -1 ); + bloom_bPx2nd_checksums = (struct checksumsha256*) calloc(256,sizeof(struct checksumsha256)); + checkpointer((void *)bloom_bPx2nd_checksums,__FILE__,"calloc","bloom_bPx2nd_checksums" ,__LINE__ -1 ); + bloom_bP2_totalbytes = 0; + for(i=0; i< 256; i++) { +#if defined(_WIN64) && !defined(__CYGWIN__) + bloom_bPx2nd_mutex[i] = CreateMutex(NULL, FALSE, NULL); +#else + pthread_mutex_init(&bloom_bPx2nd_mutex[i],NULL); +#endif + if(bloom_init2(&bloom_bPx2nd[i],itemsbloom2,0.000001) == 1){ + fprintf(stderr,"[E] error bloom_init _ [%i]\n",i); + exit(EXIT_FAILURE); + } + bloom_bP2_totalbytes += bloom_bPx2nd[i].bytes; + //if(FLAGDEBUG) bloom_print(&bloom_bPx2nd[i]); + } + printf(": %.2f MB\n",(float)((float)(uint64_t)bloom_bP2_totalbytes/(float)(uint64_t)1048576)); + + +#if defined(_WIN64) && !defined(__CYGWIN__) + bloom_bPx3rd_mutex = (HANDLE*) calloc(256,sizeof(HANDLE)); +#else + bloom_bPx3rd_mutex = (pthread_mutex_t*) calloc(256,sizeof(pthread_mutex_t)); +#endif + checkpointer((void *)bloom_bPx3rd_mutex,__FILE__,"calloc","bloom_bPx3rd_mutex" ,__LINE__ -1 ); + bloom_bPx3rd = (struct bloom*)calloc(256,sizeof(struct bloom)); + checkpointer((void *)bloom_bPx3rd,__FILE__,"calloc","bloom_bPx3rd" ,__LINE__ -1 ); + bloom_bPx3rd_checksums = (struct checksumsha256*) calloc(256,sizeof(struct checksumsha256)); + checkpointer((void *)bloom_bPx3rd_checksums,__FILE__,"calloc","bloom_bPx3rd_checksums" ,__LINE__ -1 ); + + printf("[+] Bloom filter for %" PRIu64 " elements ",bsgs_m3); + bloom_bP3_totalbytes = 0; + for(i=0; i< 256; i++) { +#if defined(_WIN64) && !defined(__CYGWIN__) + bloom_bPx3rd_mutex[i] = CreateMutex(NULL, FALSE, NULL); +#else + pthread_mutex_init(&bloom_bPx3rd_mutex[i],NULL); +#endif + if(bloom_init2(&bloom_bPx3rd[i],itemsbloom3,0.000001) == 1){ + fprintf(stderr,"[E] error bloom_init [%i]\n",i); + exit(EXIT_FAILURE); + } + bloom_bP3_totalbytes += bloom_bPx3rd[i].bytes; + //if(FLAGDEBUG) bloom_print(&bloom_bPx3rd[i]); + } + printf(": %.2f MB\n",(float)((float)(uint64_t)bloom_bP3_totalbytes/(float)(uint64_t)1048576)); + //if(FLAGDEBUG) printf("[D] bloom_bP3_totalbytes : %" PRIu64 "\n",bloom_bP3_totalbytes); + + + + + BSGS_MP = secp->ComputePublicKey(&BSGS_M); + BSGS_MP2 = secp->ComputePublicKey(&BSGS_M2); + BSGS_MP3 = secp->ComputePublicKey(&BSGS_M3); + + i= 0; + + /* New aMP table just to keep the same code of JLP */ + /* Auxiliar Points to speed up calculations for the main bloom filter check */ + Point bsP = secp->Negation(BSGS_MP); + Point g = bsP; + GSn.resize(CPU_GRP_SIZE/2,g); + BSGS_AMP2.resize(32,g); + BSGS_AMP3.resize(32,g); + + /* + GSn2.resize(16,g); + GSn3.resize(16,g); + */ + + GSn[0] = g; + + + g = secp->DoubleDirect(g); + GSn[1] = g; + for(i = 2; i < CPU_GRP_SIZE / 2; i++) { + g = secp->AddDirect(g,bsP); + GSn[i] = g; + + } + _2GSn = secp->DoubleDirect(GSn[CPU_GRP_SIZE / 2 - 1]); + + + /*Auxiliar Points to speed up calculations for the second bloom filter check */ + /* + bsP = secp->Negation(BSGS_MP2); + g = bsP; + GSn2[0] = g; + g = secp->DoubleDirect(g); + GSn2[1] = g; + for(int i = 2; i < 16; i++) { + g = secp->AddDirect(g,bsP); + GSn2[i] = g; + + } + _2GSn2 = secp->DoubleDirect(GSn2[16 - 1]); + */ + + /*Auxiliar Points to speed up calculations for the third bloom filter check */ + /* + bsP = secp->Negation(BSGS_MP3); + g = bsP; + GSn3[0] = g; + g = secp->DoubleDirect(g); + GSn3[1] = g; + for(int i = 2; i < 16; i++) { + g = secp->AddDirect(g,bsP); + GSn3[i] = g; + + } + _2GSn3 = secp->DoubleDirect(GSn3[16 - 1]); + */ + + + + + point_temp.Set(BSGS_MP2); + BSGS_AMP2[0] = secp->Negation(point_temp); + point_temp = secp->DoubleDirect(BSGS_MP2); + + for(i = 1; i < 32; i++) { + BSGS_AMP2[i] = secp->Negation(point_temp); + point_temp2 = secp->AddDirect(point_temp,BSGS_MP2); + point_temp.Set(point_temp2); + } + + point_temp.Set(BSGS_MP3); + BSGS_AMP3[0] = secp->Negation(point_temp); + point_temp = secp->DoubleDirect(BSGS_MP3); + + for(i = 1; i < 32; i++) { + BSGS_AMP3[i] = secp->Negation(point_temp); + point_temp2 = secp->AddDirect(point_temp,BSGS_MP3); + point_temp.Set(point_temp2); + } + + bytes = (uint64_t)bsgs_m3 * (uint64_t) sizeof(struct bsgs_xvalue); + printf("[+] Allocating %.2f MB for %" PRIu64 " bP Points\n",(double)(bytes/1048576),bsgs_m3); + + bPtable = (struct bsgs_xvalue*) malloc(bytes); + checkpointer((void *)bPtable,__FILE__,"malloc","bPtable" ,__LINE__ -1 ); + memset(bPtable,0,bytes); + + if(FLAGSAVEREADFILE) { + /*Reading file for 1st bloom filter */ + + snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_4_%" PRIu64 ".blm",bsgs_m); + fd_aux1 = fopen(buffer_bloom_file,"rb"); + if(fd_aux1 != NULL) { + printf("[+] Reading bloom filter from file %s ",buffer_bloom_file); + fflush(stdout); + for(i = 0; i < 256;i++) { + bf_ptr = (char*) bloom_bP[i].bf; /*We need to save the current bf pointer*/ + readed = fread(&bloom_bP[i],sizeof(struct bloom),1,fd_aux1); + if(readed != 1) { + fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + bloom_bP[i].bf = (uint8_t*)bf_ptr; /* Restoring the bf pointer*/ + readed = fread(bloom_bP[i].bf,bloom_bP[i].bytes,1,fd_aux1); + if(readed != 1) { + fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + readed = fread(&bloom_bP_checksums[i],sizeof(struct checksumsha256),1,fd_aux1); + if(readed != 1) { + fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + if(FLAGSKIPCHECKSUM == 0) { + sha256((uint8_t*)bloom_bP[i].bf,bloom_bP[i].bytes,(uint8_t*)rawvalue); + if(memcmp(bloom_bP_checksums[i].data,rawvalue,32) != 0 || memcmp(bloom_bP_checksums[i].backup,rawvalue,32) != 0 ) { /* Verification */ + fprintf(stderr,"[E] Error checksum file mismatch! %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + } + if(i % 64 == 0 ) { + printf("."); + fflush(stdout); + } + } + printf(" Done!\n"); + fclose(fd_aux1); + memset(buffer_bloom_file,0,1024); + snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_3_%" PRIu64 ".blm",bsgs_m); + fd_aux1 = fopen(buffer_bloom_file,"rb"); + if(fd_aux1 != NULL) { + printf("[W] Unused file detected %s you can delete it without worry\n",buffer_bloom_file); + fclose(fd_aux1); + } + FLAGREADEDFILE1 = 1; + } + else { /*Checking for old file keyhunt_bsgs_3_ */ + snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_3_%" PRIu64 ".blm",bsgs_m); + fd_aux1 = fopen(buffer_bloom_file,"rb"); + if(fd_aux1 != NULL) { + printf("[+] Reading bloom filter from file %s ",buffer_bloom_file); + fflush(stdout); + for(i = 0; i < 256;i++) { + bf_ptr = (char*) bloom_bP[i].bf; /*We need to save the current bf pointer*/ + readed = fread(&oldbloom_bP,sizeof(struct oldbloom),1,fd_aux1); + + /* + if(FLAGDEBUG) { + printf("old Bloom filter %i\n",i); + oldbloom_print(&oldbloom_bP); + } + */ + + if(readed != 1) { + fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + memcpy(&bloom_bP[i],&oldbloom_bP,sizeof(struct bloom));//We only need to copy the part data to the new bloom size, not from the old size + bloom_bP[i].bf = (uint8_t*)bf_ptr; /* Restoring the bf pointer*/ + + readed = fread(bloom_bP[i].bf,bloom_bP[i].bytes,1,fd_aux1); + if(readed != 1) { + fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + memcpy(bloom_bP_checksums[i].data,oldbloom_bP.checksum,32); + memcpy(bloom_bP_checksums[i].backup,oldbloom_bP.checksum_backup,32); + memset(rawvalue,0,32); + if(FLAGSKIPCHECKSUM == 0) { + sha256((uint8_t*)bloom_bP[i].bf,bloom_bP[i].bytes,(uint8_t*)rawvalue); + if(memcmp(bloom_bP_checksums[i].data,rawvalue,32) != 0 || memcmp(bloom_bP_checksums[i].backup,rawvalue,32) != 0 ) { /* Verification */ + fprintf(stderr,"[E] Error checksum file mismatch! %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + } + if(i % 32 == 0 ) { + printf("."); + fflush(stdout); + } + } + printf(" Done!\n"); + fclose(fd_aux1); + FLAGUPDATEFILE1 = 1; /* Flag to migrate the data to the new File keyhunt_bsgs_4_ */ + FLAGREADEDFILE1 = 1; + + } + else { + FLAGREADEDFILE1 = 0; + //Flag to make the new file + } + } + + /*Reading file for 2nd bloom filter */ + snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_6_%" PRIu64 ".blm",bsgs_m2); + fd_aux2 = fopen(buffer_bloom_file,"rb"); + if(fd_aux2 != NULL) { + printf("[+] Reading bloom filter from file %s ",buffer_bloom_file); + fflush(stdout); + for(i = 0; i < 256;i++) { + bf_ptr = (char*) bloom_bPx2nd[i].bf; /*We need to save the current bf pointer*/ + readed = fread(&bloom_bPx2nd[i],sizeof(struct bloom),1,fd_aux2); + if(readed != 1) { + fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + bloom_bPx2nd[i].bf = (uint8_t*)bf_ptr; /* Restoring the bf pointer*/ + readed = fread(bloom_bPx2nd[i].bf,bloom_bPx2nd[i].bytes,1,fd_aux2); + if(readed != 1) { + fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + readed = fread(&bloom_bPx2nd_checksums[i],sizeof(struct checksumsha256),1,fd_aux2); + if(readed != 1) { + fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + memset(rawvalue,0,32); + if(FLAGSKIPCHECKSUM == 0) { + sha256((uint8_t*)bloom_bPx2nd[i].bf,bloom_bPx2nd[i].bytes,(uint8_t*)rawvalue); + if(memcmp(bloom_bPx2nd_checksums[i].data,rawvalue,32) != 0 || memcmp(bloom_bPx2nd_checksums[i].backup,rawvalue,32) != 0 ) { /* Verification */ + fprintf(stderr,"[E] Error checksum file mismatch! %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + } + if(i % 64 == 0) { + printf("."); + fflush(stdout); + } + } + fclose(fd_aux2); + printf(" Done!\n"); + memset(buffer_bloom_file,0,1024); + snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_5_%" PRIu64 ".blm",bsgs_m2); + fd_aux2 = fopen(buffer_bloom_file,"rb"); + if(fd_aux2 != NULL) { + printf("[W] Unused file detected %s you can delete it without worry\n",buffer_bloom_file); + fclose(fd_aux2); + } + memset(buffer_bloom_file,0,1024); + snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_1_%" PRIu64 ".blm",bsgs_m2); + fd_aux2 = fopen(buffer_bloom_file,"rb"); + if(fd_aux2 != NULL) { + printf("[W] Unused file detected %s you can delete it without worry\n",buffer_bloom_file); + fclose(fd_aux2); + } + FLAGREADEDFILE2 = 1; + } + else { + FLAGREADEDFILE2 = 0; + } + + /*Reading file for bPtable */ + snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_2_%" PRIu64 ".tbl",bsgs_m3); + fd_aux3 = fopen(buffer_bloom_file,"rb"); + if(fd_aux3 != NULL) { + printf("[+] Reading bP Table from file %s .",buffer_bloom_file); + fflush(stdout); + rsize = fread(bPtable,bytes,1,fd_aux3); + if(rsize != 1) { + fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + rsize = fread(checksum,32,1,fd_aux3); + if(rsize != 1) { + fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + if(FLAGSKIPCHECKSUM == 0) { + sha256((uint8_t*)bPtable,bytes,(uint8_t*)checksum_backup); + if(memcmp(checksum,checksum_backup,32) != 0) { + fprintf(stderr,"[E] Error checksum file mismatch! %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + } + printf("... Done!\n"); + fclose(fd_aux3); + FLAGREADEDFILE3 = 1; + } + else { + FLAGREADEDFILE3 = 0; + } + + /*Reading file for 3rd bloom filter */ + snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_7_%" PRIu64 ".blm",bsgs_m3); + fd_aux2 = fopen(buffer_bloom_file,"rb"); + if(fd_aux2 != NULL) { + printf("[+] Reading bloom filter from file %s ",buffer_bloom_file); + fflush(stdout); + for(i = 0; i < 256;i++) { + bf_ptr = (char*) bloom_bPx3rd[i].bf; /*We need to save the current bf pointer*/ + readed = fread(&bloom_bPx3rd[i],sizeof(struct bloom),1,fd_aux2); + if(readed != 1) { + fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + bloom_bPx3rd[i].bf = (uint8_t*)bf_ptr; /* Restoring the bf pointer*/ + readed = fread(bloom_bPx3rd[i].bf,bloom_bPx3rd[i].bytes,1,fd_aux2); + if(readed != 1) { + fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + readed = fread(&bloom_bPx3rd_checksums[i],sizeof(struct checksumsha256),1,fd_aux2); + if(readed != 1) { + fprintf(stderr,"[E] Error reading the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + memset(rawvalue,0,32); + if(FLAGSKIPCHECKSUM == 0) { + sha256((uint8_t*)bloom_bPx3rd[i].bf,bloom_bPx3rd[i].bytes,(uint8_t*)rawvalue); + if(memcmp(bloom_bPx3rd_checksums[i].data,rawvalue,32) != 0 || memcmp(bloom_bPx3rd_checksums[i].backup,rawvalue,32) != 0 ) { /* Verification */ + fprintf(stderr,"[E] Error checksum file mismatch! %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + } + if(i % 64 == 0) { + printf("."); + fflush(stdout); + } + } + fclose(fd_aux2); + printf(" Done!\n"); + FLAGREADEDFILE4 = 1; + } + else { + FLAGREADEDFILE4 = 0; + } + + } + + if(!FLAGREADEDFILE1 || !FLAGREADEDFILE2 || !FLAGREADEDFILE3 || !FLAGREADEDFILE4) { + if(FLAGREADEDFILE1 == 1) { + /* + We need just to make File 2 to File 4 this is + - Second bloom filter 5% + - third bloom fitler 0.25 % + - bp Table 0.25 % + */ + printf("[I] We need to recalculate some files, don't worry this is only 3%% of the previous work\n"); + FINISHED_THREADS_COUNTER = 0; + FINISHED_THREADS_BP = 0; + FINISHED_ITEMS = 0; + salir = 0; + BASE = 0; + THREADCOUNTER = 0; + if(THREADBPWORKLOAD >= bsgs_m2) { + THREADBPWORKLOAD = bsgs_m2; + } + THREADCYCLES = bsgs_m2 / THREADBPWORKLOAD; + PERTHREAD_R = bsgs_m2 % THREADBPWORKLOAD; + if(PERTHREAD_R != 0) { + THREADCYCLES++; + } + + printf("\r[+] processing %lu/%lu bP points : %i%%\r",FINISHED_ITEMS,bsgs_m,(int) (((double)FINISHED_ITEMS/(double)bsgs_m)*100)); + fflush(stdout); + +#if defined(_WIN64) && !defined(__CYGWIN__) + tid = (HANDLE*)calloc(NTHREADS, sizeof(HANDLE)); + checkpointer((void *)tid,__FILE__,"calloc","tid" ,__LINE__ -1 ); + bPload_mutex = (HANDLE*) calloc(NTHREADS,sizeof(HANDLE)); +#else + tid = (pthread_t *) calloc(NTHREADS,sizeof(pthread_t)); + bPload_mutex = (pthread_mutex_t*) calloc(NTHREADS,sizeof(pthread_mutex_t)); +#endif + checkpointer((void *)bPload_mutex,__FILE__,"calloc","bPload_mutex" ,__LINE__ -1 ); + bPload_temp_ptr = (struct bPload*) calloc(NTHREADS,sizeof(struct bPload)); + checkpointer((void *)bPload_temp_ptr,__FILE__,"calloc","bPload_temp_ptr" ,__LINE__ -1 ); + bPload_threads_available = (char*) calloc(NTHREADS,sizeof(char)); + checkpointer((void *)bPload_threads_available,__FILE__,"calloc","bPload_threads_available" ,__LINE__ -1 ); + + memset(bPload_threads_available,1,NTHREADS); + + for(i = 0; i < NTHREADS; i++) { +#if defined(_WIN64) && !defined(__CYGWIN__) + bPload_mutex[i] = CreateMutex(NULL, FALSE, NULL); +#else + pthread_mutex_init(&bPload_mutex[i],NULL); +#endif + } + + do { + for(i = 0; i < NTHREADS && !salir; i++) { + + if(bPload_threads_available[i] && !salir) { + bPload_threads_available[i] = 0; + bPload_temp_ptr[i].from = BASE; + bPload_temp_ptr[i].threadid = i; + bPload_temp_ptr[i].finished = 0; + if( THREADCOUNTER < THREADCYCLES-1) { + bPload_temp_ptr[i].to = BASE + THREADBPWORKLOAD; + bPload_temp_ptr[i].workload = THREADBPWORKLOAD; + } + else { + bPload_temp_ptr[i].to = BASE + THREADBPWORKLOAD + PERTHREAD_R; + bPload_temp_ptr[i].workload = THREADBPWORKLOAD + PERTHREAD_R; + salir = 1; + //if(FLAGDEBUG) printf("[D] Salir OK\n"); + } + //if(FLAGDEBUG) printf("[I] %lu to %lu\n",bPload_temp_ptr[i].from,bPload_temp_ptr[i].to); +#if defined(_WIN64) && !defined(__CYGWIN__) + tid[i] = CreateThread(NULL, 0, thread_bPload_2blooms, (void*) &bPload_temp_ptr[i], 0, &s); +#else + s = pthread_create(&tid[i],NULL,thread_bPload_2blooms,(void*) &bPload_temp_ptr[i]); + pthread_detach(tid[i]); +#endif + BASE+=THREADBPWORKLOAD; + THREADCOUNTER++; + } + } + + if(OLDFINISHED_ITEMS != FINISHED_ITEMS) { + printf("\r[+] processing %lu/%lu bP points : %i%%\r",FINISHED_ITEMS,bsgs_m2,(int) (((double)FINISHED_ITEMS/(double)bsgs_m2)*100)); + fflush(stdout); + OLDFINISHED_ITEMS = FINISHED_ITEMS; + } + + for(i = 0 ; i < NTHREADS ; i++) { + +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(bPload_mutex[i], INFINITE); + finished = bPload_temp_ptr[i].finished; + ReleaseMutex(bPload_mutex[i]); +#else + pthread_mutex_lock(&bPload_mutex[i]); + finished = bPload_temp_ptr[i].finished; + pthread_mutex_unlock(&bPload_mutex[i]); +#endif + if(finished) { + bPload_temp_ptr[i].finished = 0; + bPload_threads_available[i] = 1; + FINISHED_ITEMS += bPload_temp_ptr[i].workload; + FINISHED_THREADS_COUNTER++; + } + } + + }while(FINISHED_THREADS_COUNTER < THREADCYCLES); + printf("\r[+] processing %lu/%lu bP points : 100%% \n",bsgs_m2,bsgs_m2); + + free(tid); + free(bPload_mutex); + free(bPload_temp_ptr); + free(bPload_threads_available); + } + else{ + /* We need just to do all the files + - first bllom filter 100% + - Second bloom filter 5% + - third bloom fitler 0.25 % + - bp Table 0.25 % + */ + FINISHED_THREADS_COUNTER = 0; + FINISHED_THREADS_BP = 0; + FINISHED_ITEMS = 0; + salir = 0; + BASE = 0; + THREADCOUNTER = 0; + if(THREADBPWORKLOAD >= bsgs_m) { + THREADBPWORKLOAD = bsgs_m; + } + THREADCYCLES = bsgs_m / THREADBPWORKLOAD; + PERTHREAD_R = bsgs_m % THREADBPWORKLOAD; + //if(FLAGDEBUG) printf("[D] THREADCYCLES: %lu\n",THREADCYCLES); + if(PERTHREAD_R != 0) { + THREADCYCLES++; + //if(FLAGDEBUG) printf("[D] PERTHREAD_R: %lu\n",PERTHREAD_R); + } + + printf("\r[+] processing %lu/%lu bP points : %i%%\r",FINISHED_ITEMS,bsgs_m,(int) (((double)FINISHED_ITEMS/(double)bsgs_m)*100)); + fflush(stdout); + +#if defined(_WIN64) && !defined(__CYGWIN__) + tid = (HANDLE*)calloc(NTHREADS, sizeof(HANDLE)); + bPload_mutex = (HANDLE*) calloc(NTHREADS,sizeof(HANDLE)); +#else + tid = (pthread_t *) calloc(NTHREADS,sizeof(pthread_t)); + bPload_mutex = (pthread_mutex_t*) calloc(NTHREADS,sizeof(pthread_mutex_t)); +#endif + checkpointer((void *)tid,__FILE__,"calloc","tid" ,__LINE__ -1 ); + checkpointer((void *)bPload_mutex,__FILE__,"calloc","bPload_mutex" ,__LINE__ -1 ); + + bPload_temp_ptr = (struct bPload*) calloc(NTHREADS,sizeof(struct bPload)); + checkpointer((void *)bPload_temp_ptr,__FILE__,"calloc","bPload_temp_ptr" ,__LINE__ -1 ); + bPload_threads_available = (char*) calloc(NTHREADS,sizeof(char)); + checkpointer((void *)bPload_threads_available,__FILE__,"calloc","bPload_threads_available" ,__LINE__ -1 ); + + + memset(bPload_threads_available,1,NTHREADS); + + for(i = 0; i < NTHREADS; i++) { +#if defined(_WIN64) && !defined(__CYGWIN__) + bPload_mutex = CreateMutex(NULL, FALSE, NULL); +#else + pthread_mutex_init(&bPload_mutex[i],NULL); +#endif + } + + do { + for(i = 0; i < NTHREADS && !salir; i++) { + + if(bPload_threads_available[i] && !salir) { + bPload_threads_available[i] = 0; + bPload_temp_ptr[i].from = BASE; + bPload_temp_ptr[i].threadid = i; + bPload_temp_ptr[i].finished = 0; + if( THREADCOUNTER < THREADCYCLES-1) { + bPload_temp_ptr[i].to = BASE + THREADBPWORKLOAD; + bPload_temp_ptr[i].workload = THREADBPWORKLOAD; + } + else { + bPload_temp_ptr[i].to = BASE + THREADBPWORKLOAD + PERTHREAD_R; + bPload_temp_ptr[i].workload = THREADBPWORKLOAD + PERTHREAD_R; + salir = 1; + //if(FLAGDEBUG) printf("[D] Salir OK\n"); + } + //if(FLAGDEBUG) printf("[I] %lu to %lu\n",bPload_temp_ptr[i].from,bPload_temp_ptr[i].to); +#if defined(_WIN64) && !defined(__CYGWIN__) + tid[i] = CreateThread(NULL, 0, thread_bPload, (void*) &bPload_temp_ptr[i], 0, &s); +#else + s = pthread_create(&tid[i],NULL,thread_bPload,(void*) &bPload_temp_ptr[i]); + pthread_detach(tid[i]); +#endif + BASE+=THREADBPWORKLOAD; + THREADCOUNTER++; + } + } + if(OLDFINISHED_ITEMS != FINISHED_ITEMS) { + printf("\r[+] processing %lu/%lu bP points : %i%%\r",FINISHED_ITEMS,bsgs_m,(int) (((double)FINISHED_ITEMS/(double)bsgs_m)*100)); + fflush(stdout); + OLDFINISHED_ITEMS = FINISHED_ITEMS; + } + + for(i = 0 ; i < NTHREADS ; i++) { + +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(bPload_mutex[i], INFINITE); + finished = bPload_temp_ptr[i].finished; + ReleaseMutex(bPload_mutex[i]); +#else + pthread_mutex_lock(&bPload_mutex[i]); + finished = bPload_temp_ptr[i].finished; + pthread_mutex_unlock(&bPload_mutex[i]); +#endif + if(finished) { + bPload_temp_ptr[i].finished = 0; + bPload_threads_available[i] = 1; + FINISHED_ITEMS += bPload_temp_ptr[i].workload; + FINISHED_THREADS_COUNTER++; + } + } + + }while(FINISHED_THREADS_COUNTER < THREADCYCLES); + printf("\r[+] processing %lu/%lu bP points : 100%% \n",bsgs_m,bsgs_m); + + free(tid); + free(bPload_mutex); + free(bPload_temp_ptr); + free(bPload_threads_available); + } + } + + if(!FLAGREADEDFILE1 || !FLAGREADEDFILE2 || !FLAGREADEDFILE4) { + printf("[+] Making checkums .. "); + fflush(stdout); + } + if(!FLAGREADEDFILE1) { + for(i = 0; i < 256 ; i++) { + sha256((uint8_t*)bloom_bP[i].bf, bloom_bP[i].bytes,(uint8_t*) bloom_bP_checksums[i].data); + memcpy(bloom_bP_checksums[i].backup,bloom_bP_checksums[i].data,32); + } + printf("."); + } + if(!FLAGREADEDFILE2) { + for(i = 0; i < 256 ; i++) { + sha256((uint8_t*)bloom_bPx2nd[i].bf, bloom_bPx2nd[i].bytes,(uint8_t*) bloom_bPx2nd_checksums[i].data); + memcpy(bloom_bPx2nd_checksums[i].backup,bloom_bPx2nd_checksums[i].data,32); + } + printf("."); + } + if(!FLAGREADEDFILE4) { + for(i = 0; i < 256 ; i++) { + sha256((uint8_t*)bloom_bPx3rd[i].bf, bloom_bPx3rd[i].bytes,(uint8_t*) bloom_bPx3rd_checksums[i].data); + memcpy(bloom_bPx3rd_checksums[i].backup,bloom_bPx3rd_checksums[i].data,32); + } + printf("."); + } + if(!FLAGREADEDFILE1 || !FLAGREADEDFILE2 || !FLAGREADEDFILE4) { + printf(" done\n"); + fflush(stdout); + } + if(!FLAGREADEDFILE3) { + printf("[+] Sorting %lu elements... ",bsgs_m3); + fflush(stdout); + bsgs_sort(bPtable,bsgs_m3); + sha256((uint8_t*)bPtable, bytes,(uint8_t*) checksum); + memcpy(checksum_backup,checksum,32); + printf("Done!\n"); + fflush(stdout); + } + if(FLAGSAVEREADFILE || FLAGUPDATEFILE1 ) { + if(!FLAGREADEDFILE1 || FLAGUPDATEFILE1) { + snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_4_%" PRIu64 ".blm",bsgs_m); + + if(FLAGUPDATEFILE1) { + printf("[W] Updating old file into a new one\n"); + } + + /* Writing file for 1st bloom filter */ + + fd_aux1 = fopen(buffer_bloom_file,"wb"); + if(fd_aux1 != NULL) { + printf("[+] Writing bloom filter to file %s ",buffer_bloom_file); + fflush(stdout); + for(i = 0; i < 256;i++) { + readed = fwrite(&bloom_bP[i],sizeof(struct bloom),1,fd_aux1); + if(readed != 1) { + fprintf(stderr,"[E] Error writing the file %s please delete it\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + readed = fwrite(bloom_bP[i].bf,bloom_bP[i].bytes,1,fd_aux1); + if(readed != 1) { + fprintf(stderr,"[E] Error writing the file %s please delete it\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + readed = fwrite(&bloom_bP_checksums[i],sizeof(struct checksumsha256),1,fd_aux1); + if(readed != 1) { + fprintf(stderr,"[E] Error writing the file %s please delete it\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + if(i % 64 == 0) { + printf("."); + fflush(stdout); + } + } + printf(" Done!\n"); + fclose(fd_aux1); + } + else { + fprintf(stderr,"[E] Error can't create the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + } + if(!FLAGREADEDFILE2 ) { + + snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_6_%" PRIu64 ".blm",bsgs_m2); + + /* Writing file for 2nd bloom filter */ + fd_aux2 = fopen(buffer_bloom_file,"wb"); + if(fd_aux2 != NULL) { + printf("[+] Writing bloom filter to file %s ",buffer_bloom_file); + fflush(stdout); + for(i = 0; i < 256;i++) { + readed = fwrite(&bloom_bPx2nd[i],sizeof(struct bloom),1,fd_aux2); + if(readed != 1) { + fprintf(stderr,"[E] Error writing the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + readed = fwrite(bloom_bPx2nd[i].bf,bloom_bPx2nd[i].bytes,1,fd_aux2); + if(readed != 1) { + fprintf(stderr,"[E] Error writing the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + readed = fwrite(&bloom_bPx2nd_checksums[i],sizeof(struct checksumsha256),1,fd_aux2); + if(readed != 1) { + fprintf(stderr,"[E] Error writing the file %s please delete it\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + if(i % 64 == 0) { + printf("."); + fflush(stdout); + } + } + printf(" Done!\n"); + fclose(fd_aux2); + } + else { + fprintf(stderr,"[E] Error can't create the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + } + + if(!FLAGREADEDFILE3) { + /* Writing file for bPtable */ + snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_2_%" PRIu64 ".tbl",bsgs_m3); + fd_aux3 = fopen(buffer_bloom_file,"wb"); + if(fd_aux3 != NULL) { + printf("[+] Writing bP Table to file %s .. ",buffer_bloom_file); + fflush(stdout); + readed = fwrite(bPtable,bytes,1,fd_aux3); + if(readed != 1) { + fprintf(stderr,"[E] Error writing the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + readed = fwrite(checksum,32,1,fd_aux3); + if(readed != 1) { + fprintf(stderr,"[E] Error writing the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + printf("Done!\n"); + fclose(fd_aux3); + } + else { + fprintf(stderr,"[E] Error can't create the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + } + if(!FLAGREADEDFILE4) { + snprintf(buffer_bloom_file,1024,"keyhunt_bsgs_7_%" PRIu64 ".blm",bsgs_m3); + + /* Writing file for 3rd bloom filter */ + fd_aux2 = fopen(buffer_bloom_file,"wb"); + if(fd_aux2 != NULL) { + printf("[+] Writing bloom filter to file %s ",buffer_bloom_file); + fflush(stdout); + for(i = 0; i < 256;i++) { + readed = fwrite(&bloom_bPx3rd[i],sizeof(struct bloom),1,fd_aux2); + if(readed != 1) { + fprintf(stderr,"[E] Error writing the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + readed = fwrite(bloom_bPx3rd[i].bf,bloom_bPx3rd[i].bytes,1,fd_aux2); + if(readed != 1) { + fprintf(stderr,"[E] Error writing the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + readed = fwrite(&bloom_bPx3rd_checksums[i],sizeof(struct checksumsha256),1,fd_aux2); + if(readed != 1) { + fprintf(stderr,"[E] Error writing the file %s please delete it\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + if(i % 64 == 0) { + printf("."); + fflush(stdout); + } + } + printf(" Done!\n"); + fclose(fd_aux2); + } + else { + fprintf(stderr,"[E] Error can't create the file %s\n",buffer_bloom_file); + exit(EXIT_FAILURE); + } + } + } + + + i = 0; + + steps = (uint64_t *) calloc(NTHREADS,sizeof(uint64_t)); + checkpointer((void *)steps,__FILE__,"calloc","steps" ,__LINE__ -1 ); + ends = (unsigned int *) calloc(NTHREADS,sizeof(int)); + checkpointer((void *)ends,__FILE__,"calloc","ends" ,__LINE__ -1 ); +#if defined(_WIN64) && !defined(__CYGWIN__) + tid = (HANDLE*)calloc(NTHREADS, sizeof(HANDLE)); +#else + tid = (pthread_t *) calloc(NTHREADS,sizeof(pthread_t)); +#endif + checkpointer((void *)tid,__FILE__,"calloc","tid" ,__LINE__ -1 ); + + for(i= 0;i < NTHREADS; i++) { + tt = (tothread*) malloc(sizeof(struct tothread)); + checkpointer((void *)tt,__FILE__,"malloc","tt" ,__LINE__ -1 ); + tt->nt = i; + s = 0; + switch(FLAGBSGSMODE) { +#if defined(_WIN64) && !defined(__CYGWIN__) + case 0: + tid[i] = CreateThread(NULL, 0, thread_process_bsgs, (void*)tt, 0, &s); + break; + case 1: + tid[i] = CreateThread(NULL, 0, thread_process_bsgs_backward, (void*)tt, 0, &s); + break; + case 2: + tid[i] = CreateThread(NULL, 0, thread_process_bsgs_both, (void*)tt, 0, &s); + break; + case 3: + tid[i] = CreateThread(NULL, 0, thread_process_bsgs_random, (void*)tt, 0, &s); + break; + case 4: + tid[i] = CreateThread(NULL, 0, thread_process_bsgs_dance, (void*)tt, 0, &s); + break; + } +#else + + case 0: + s = pthread_create(&tid[i],NULL,thread_process_bsgs,(void *)tt); + break; + case 1: + s = pthread_create(&tid[i],NULL,thread_process_bsgs_backward,(void *)tt); + break; + case 2: + s = pthread_create(&tid[i],NULL,thread_process_bsgs_both,(void *)tt); + break; + case 3: + s = pthread_create(&tid[i],NULL,thread_process_bsgs_random,(void *)tt); + break; + case 4: + s = pthread_create(&tid[i],NULL,thread_process_bsgs_dance,(void *)tt); + break; +#endif + } +#if defined(_WIN64) && !defined(__CYGWIN__) + if (tid[i] == NULL) { +#else + if(s != 0) { +#endif + fprintf(stderr,"[E] thread thread_process\n"); + exit(EXIT_FAILURE); + } + } + + + free(aux); + } + if(FLAGMODE != MODE_BSGS) { + if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); } + steps = (uint64_t *) calloc(NTHREADS,sizeof(uint64_t)); + checkpointer((void *)steps,__FILE__,"calloc","steps" ,__LINE__ -1 ); + ends = (unsigned int *) calloc(NTHREADS,sizeof(int)); + checkpointer((void *)ends,__FILE__,"calloc","ends" ,__LINE__ -1 ); +#if defined(_WIN64) && !defined(__CYGWIN__) + tid = (HANDLE*)calloc(NTHREADS, sizeof(HANDLE)); +#else + tid = (pthread_t *) calloc(NTHREADS,sizeof(pthread_t)); +#endif + checkpointer((void *)tid,__FILE__,"calloc","tid" ,__LINE__ -1 ); + if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); } + for(i= 0;i < NTHREADS; i++) { + tt = (tothread*) malloc(sizeof(struct tothread)); + checkpointer((void *)tt,__FILE__,"malloc","tt" ,__LINE__ -1 ); + tt->nt = i; + steps[i] = 0; + s = 0; + switch(FLAGMODE) { +#if defined(_WIN64) && !defined(__CYGWIN__) + case MODE_ADDRESS: + case MODE_XPOINT: + case MODE_RMD160: + if(FLAGDEBUG) { printf("[D] File: %s Line %i\n",__FILE__,__LINE__); fflush(stdout); } + tid[i] = CreateThread(NULL, 0, thread_process, (void*)tt, 0, &s); + break; + case MODE_PUB2RMD: + tid[i] = CreateThread(NULL, 0, thread_pub2rmd, (void*)tt, 0, &s); + break; + case MODE_MINIKEYS: + tid[i] = CreateThread(NULL, 0, thread_process_minikeys, (void*)tt, 0, &s); + break; +#else + case MODE_ADDRESS: + case MODE_XPOINT: + case MODE_RMD160: + s = pthread_create(&tid[i],NULL,thread_process,(void *)tt); + break; + case MODE_PUB2RMD: + s = pthread_create(&tid[i],NULL,thread_pub2rmd,(void *)tt); + break; + case MODE_MINIKEYS: + s = pthread_create(&tid[i],NULL,thread_process_minikeys,(void *)tt); + break; + case MODE_VANITY: + s = pthread_create(&tid[i],NULL,thread_process_vanity,(void *)tt); + break; +#endif + } +#if defined(_WIN64) && !defined(__CYGWIN__) + if (tid[i] == NULL) { +#else + if(s != 0) { +#endif + fprintf(stderr,"[E] pthread_create thread_process\n"); + exit(EXIT_FAILURE); + } + } + } + i = 0; + + while(i < 7) { + int_limits[i].SetBase10((char*)str_limits[i]); + i++; + } + + continue_flag = 1; + total.SetInt32(0); + pretotal.SetInt32(0); + debugcount_mpz.Set(&BSGS_N); + seconds.SetInt32(0); + do { + sleep_ms(1000); + seconds.AddOne(); + check_flag = 1; + for(i = 0; i = 1) { + half = (max - min)/2; + rcmp = memcmp(data,buffer[current+half].value,20); + if(rcmp == 0) { + r = 1; //Found!! + } + else { + if(rcmp < 0) { //data < temp_read + max = (max-half); + } + else { // data > temp_read + min = (min+half); + } + current = min; + } + } + return r; +} + +#if defined(_WIN64) && !defined(__CYGWIN__) +DWORD WINAPI thread_process_minikeys(LPVOID vargp) { +#else +void *thread_process_minikeys(void *vargp) { +#endif + FILE *keys; + Point publickey[4]; + Int key_mpz[4]; + struct tothread *tt; + uint64_t count; + char publickeyhashrmd160_uncompress[4][20]; + char public_key_uncompressed_hex[131]; + char rawvalue[4][32]; + char address[4][40],minikey[4][24],minikeys[8][24],buffer_b58[21],minikey2check[24]; + char *hextemp,rawbuffer[32]; + int r,thread_number,continue_flag = 1,k,j,count_valid; + //Int counter; + tt = (struct tothread *)vargp; + thread_number = tt->nt; + free(tt); + //rawbuffer = (char*) &counter.bits64; + count_valid = 0; + for(k = 0; k < 4; k++) { + minikey[k][0] = 'S'; + minikey[k][22] = '?'; + minikey[k][23] = 0x00; + } + minikey2check[0] = 'S'; + minikey2check[22] = '?'; + minikey2check[23] = 0x00; + + do { + if(FLAGRANDOM) { + random_bytes((unsigned char*)rawbuffer,32); + for(k = 0; k < 21; k++) { + buffer_b58[k] =(uint8_t)((uint8_t) rawbuffer[k] % 58); + } + } + else { + if(FLAGBASEMINIKEY) { +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_random, INFINITE); + memcpy(buffer_b58,raw_baseminikey,21); + increment_minikey_N(raw_baseminikey); + ReleaseMutex(write_random); +#else + pthread_mutex_lock(&write_random); + memcpy(buffer_b58,raw_baseminikey,21); + increment_minikey_N(raw_baseminikey); + pthread_mutex_unlock(&write_random); +#endif + } + else { +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_random, INFINITE); +#else + pthread_mutex_lock(&write_random); +#endif + if(raw_baseminikey == NULL){ + raw_baseminikey = (char *) malloc(22); + checkpointer((void *)raw_baseminikey,__FILE__,"malloc","raw_baseminikey" ,__LINE__ -1 ); + random_bytes((unsigned char*)rawbuffer,32); + for(k = 0; k < 21; k++) { + raw_baseminikey[k] =(uint8_t)((uint8_t) rawbuffer[k] % 58); + } + memcpy(buffer_b58,raw_baseminikey,21); + increment_minikey_N(raw_baseminikey); + + } + else { + memcpy(buffer_b58,raw_baseminikey,21); + increment_minikey_N(raw_baseminikey); + } +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(write_random); +#else + pthread_mutex_unlock(&write_random); +#endif + + } + } + set_minikey(minikey2check+1,buffer_b58,21); + if(continue_flag) { + count = 0; + if(FLAGMATRIX) { + printf("[+] Base minikey: %s \n",minikey2check); + fflush(stdout); + } + else { + if(!FLAGQUIET) { + printf("\r[+] Base minikey: %s \r",minikey2check); + fflush(stdout); + } + } + do { + for(j = 0;j<256; j++) { + + if(count_valid > 0) { + for(k = 0; k < count_valid ; k++) { + memcpy(minikeys[k],minikeys[4+k],22); + } + } + do { + increment_minikey_index(minikey2check+1,buffer_b58,20); + memcpy(minikey[0]+1,minikey2check+1,21); + increment_minikey_index(minikey2check+1,buffer_b58,20); + memcpy(minikey[1]+1,minikey2check+1,21); + increment_minikey_index(minikey2check+1,buffer_b58,20); + memcpy(minikey[2]+1,minikey2check+1,21); + increment_minikey_index(minikey2check+1,buffer_b58,20); + memcpy(minikey[3]+1,minikey2check+1,21); + + sha256sse_23((uint8_t*)minikey[0],(uint8_t*)minikey[1],(uint8_t*)minikey[2],(uint8_t*)minikey[3],(uint8_t*)rawvalue[0],(uint8_t*)rawvalue[1],(uint8_t*)rawvalue[2],(uint8_t*)rawvalue[3]); + for(k = 0; k < 4; k++){ + if(rawvalue[k][0] == 0x00) { + memcpy(minikeys[count_valid],minikey[k],22); + count_valid++; + } + } + }while(count_valid < 4); + count_valid-=4; + sha256sse_22((uint8_t*)minikeys[0],(uint8_t*)minikeys[1],(uint8_t*)minikeys[2],(uint8_t*)minikeys[3],(uint8_t*)rawvalue[0],(uint8_t*)rawvalue[1],(uint8_t*)rawvalue[2],(uint8_t*)rawvalue[3]); + + for(k = 0; k < 4; k++) { + key_mpz[k].Set32Bytes((uint8_t*)rawvalue[k]); + publickey[k] = secp->ComputePublicKey(&key_mpz[k]); + } + + secp->GetHash160(P2PKH,false,publickey[0],publickey[1],publickey[2],publickey[3],(uint8_t*)publickeyhashrmd160_uncompress[0],(uint8_t*)publickeyhashrmd160_uncompress[1],(uint8_t*)publickeyhashrmd160_uncompress[2],(uint8_t*)publickeyhashrmd160_uncompress[3]); + + for(k = 0; k < 4; k++) { + r = bloom_check(&bloom,publickeyhashrmd160_uncompress[k],20); + if(r) { + r = searchbinary(addressTable,publickeyhashrmd160_uncompress[k],N); + if(r) { + /* hit */ + hextemp = key_mpz[k].GetBase16(); + secp->GetPublicKeyHex(false,publickey[k],public_key_uncompressed_hex); +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_keys, INFINITE); +#else + pthread_mutex_lock(&write_keys); +#endif + + keys = fopen("KEYFOUNDKEYFOUND.txt","a+"); + rmd160toaddress_dst(publickeyhashrmd160_uncompress[k],address[k]); + minikeys[k][22] = '\0'; + if(keys != NULL) { + fprintf(keys,"Private Key: %s\npubkey: %s\nminikey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,minikeys[k],address[k]); + fclose(keys); + } + printf("\nHIT!! Private Key: %s\npubkey: %s\nminikey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,minikeys[k],address[k]); +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(write_keys); +#else + pthread_mutex_unlock(&write_keys); +#endif + + free(hextemp); + } + } + } + } + steps[thread_number]++; + count+=1024; + }while(count < N_SEQUENTIAL_MAX && continue_flag); + } + }while(continue_flag); + return NULL; +} + + +#if defined(_WIN64) && !defined(__CYGWIN__) +DWORD WINAPI thread_process(LPVOID vargp) { +#else +void *thread_process(void *vargp) { +#endif + struct tothread *tt; + Point pts[CPU_GRP_SIZE]; + Point endomorphism_beta[CPU_GRP_SIZE]; + Point endomorphism_beta2[CPU_GRP_SIZE]; + Point endomorphism_negeted_point[4]; + + Int dx[CPU_GRP_SIZE / 2 + 1]; + IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1); + Point startP; + Int dy; + Int dyn; + Int _s; + Int _p; + Point pp; + Point pn; + int l,pp_offset,pn_offset; + int i,hLength = (CPU_GRP_SIZE / 2 - 1); + uint64_t j,count; + Point R,temporal,publickey; + int r,thread_number,continue_flag = 1,k; + char *hextemp = NULL; + + char publickeyhashrmd160[20]; + char publickeyhashrmd160_uncompress[4][20]; + char hexstrpoint[65],rawvalue[32]; + + char publickeyhashrmd160_endomorphism[12][4][20]; + + bool calculate_y = FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH; + FILE *keys; + Int key_mpz,keyfound,temp_stride; + tt = (struct tothread *)vargp; + thread_number = tt->nt; + free(tt); + grp->Set(dx); + + do { + if(FLAGRANDOM){ + key_mpz.Rand(&n_range_start,&n_range_end); + } + else { + if(n_range_start.IsLower(&n_range_end)) { +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_random, INFINITE); + key_mpz.Set(&n_range_start); + n_range_start.Add(N_SEQUENTIAL_MAX); + ReleaseMutex(write_random); +#else + pthread_mutex_lock(&write_random); + key_mpz.Set(&n_range_start); + n_range_start.Add(N_SEQUENTIAL_MAX); + pthread_mutex_unlock(&write_random); +#endif + } + else { + continue_flag = 0; + } + } + if(continue_flag) { + count = 0; + if(FLAGMATRIX) { + hextemp = key_mpz.GetBase16(); + printf("Base key: %s thread %i\n",hextemp,thread_number); + fflush(stdout); + free(hextemp); + } + else { + if(FLAGQUIET == 0){ + hextemp = key_mpz.GetBase16(); + printf("\rBase key: %s \r",hextemp); + fflush(stdout); + free(hextemp); + THREADOUTPUT = 1; + } + } + do { + temp_stride.SetInt32(CPU_GRP_SIZE / 2); + temp_stride.Mult(&stride); + key_mpz.Add(&temp_stride); + startP = secp->ComputePublicKey(&key_mpz); + key_mpz.Sub(&temp_stride); + + for(i = 0; i < hLength; i++) { + dx[i].ModSub(&Gn[i].x,&startP.x); + } + + dx[i].ModSub(&Gn[i].x,&startP.x); // For the first point + dx[i + 1].ModSub(&_2Gn.x,&startP.x); // For the next center point + grp->ModInv(); + + pts[CPU_GRP_SIZE / 2] = startP; + + for(i = 0; iGetHash160_fromX(P2PKH,0x02,&pts[(j*4)].x,&pts[(j*4)+1].x,&pts[(j*4)+2].x,&pts[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[0][0],(uint8_t*)publickeyhashrmd160_endomorphism[0][1],(uint8_t*)publickeyhashrmd160_endomorphism[0][2],(uint8_t*)publickeyhashrmd160_endomorphism[0][3]); + secp->GetHash160_fromX(P2PKH,0x03,&pts[(j*4)].x,&pts[(j*4)+1].x,&pts[(j*4)+2].x,&pts[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[1][0],(uint8_t*)publickeyhashrmd160_endomorphism[1][1],(uint8_t*)publickeyhashrmd160_endomorphism[1][2],(uint8_t*)publickeyhashrmd160_endomorphism[1][3]); + + secp->GetHash160_fromX(P2PKH,0x02,&endomorphism_beta[(j*4)].x,&endomorphism_beta[(j*4)+1].x,&endomorphism_beta[(j*4)+2].x,&endomorphism_beta[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[2][0],(uint8_t*)publickeyhashrmd160_endomorphism[2][1],(uint8_t*)publickeyhashrmd160_endomorphism[2][2],(uint8_t*)publickeyhashrmd160_endomorphism[2][3]); + secp->GetHash160_fromX(P2PKH,0x03,&endomorphism_beta[(j*4)].x,&endomorphism_beta[(j*4)+1].x,&endomorphism_beta[(j*4)+2].x,&endomorphism_beta[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[3][0],(uint8_t*)publickeyhashrmd160_endomorphism[3][1],(uint8_t*)publickeyhashrmd160_endomorphism[3][2],(uint8_t*)publickeyhashrmd160_endomorphism[3][3]); + + secp->GetHash160_fromX(P2PKH,0x02,&endomorphism_beta2[(j*4)].x,&endomorphism_beta2[(j*4)+1].x,&endomorphism_beta2[(j*4)+2].x,&endomorphism_beta2[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[4][0],(uint8_t*)publickeyhashrmd160_endomorphism[4][1],(uint8_t*)publickeyhashrmd160_endomorphism[4][2],(uint8_t*)publickeyhashrmd160_endomorphism[4][3]); + secp->GetHash160_fromX(P2PKH,0x03,&endomorphism_beta2[(j*4)].x,&endomorphism_beta2[(j*4)+1].x,&endomorphism_beta2[(j*4)+2].x,&endomorphism_beta2[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[5][0],(uint8_t*)publickeyhashrmd160_endomorphism[5][1],(uint8_t*)publickeyhashrmd160_endomorphism[5][2],(uint8_t*)publickeyhashrmd160_endomorphism[5][3]); + } + else { + secp->GetHash160_fromX(P2PKH,0x02,&pts[(j*4)].x,&pts[(j*4)+1].x,&pts[(j*4)+2].x,&pts[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[0][0],(uint8_t*)publickeyhashrmd160_endomorphism[0][1],(uint8_t*)publickeyhashrmd160_endomorphism[0][2],(uint8_t*)publickeyhashrmd160_endomorphism[0][3]); + secp->GetHash160_fromX(P2PKH,0x03,&pts[(j*4)].x,&pts[(j*4)+1].x,&pts[(j*4)+2].x,&pts[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[1][0],(uint8_t*)publickeyhashrmd160_endomorphism[1][1],(uint8_t*)publickeyhashrmd160_endomorphism[1][2],(uint8_t*)publickeyhashrmd160_endomorphism[1][3]); + } + + } + if(FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH){ + if(FLAGENDOMORPHISM) { + for(l = 0; l < 4; l++) { + endomorphism_negeted_point[l] = secp->Negation(pts[(j*4)+l]); + } + secp->GetHash160(P2PKH,false, pts[(j*4)], pts[(j*4)+1], pts[(j*4)+2], pts[(j*4)+3],(uint8_t*)publickeyhashrmd160_endomorphism[6][0],(uint8_t*)publickeyhashrmd160_endomorphism[6][1],(uint8_t*)publickeyhashrmd160_endomorphism[6][2],(uint8_t*)publickeyhashrmd160_endomorphism[6][3]); + secp->GetHash160(P2PKH,false,endomorphism_negeted_point[(j*4)] ,endomorphism_negeted_point[(j*4)+1],endomorphism_negeted_point[(j*4)+2],endomorphism_negeted_point[(j*4)+3],(uint8_t*)publickeyhashrmd160_endomorphism[7][0],(uint8_t*)publickeyhashrmd160_endomorphism[7][1],(uint8_t*)publickeyhashrmd160_endomorphism[7][2],(uint8_t*)publickeyhashrmd160_endomorphism[7][3]); + for(l = 0; l < 4; l++) { + endomorphism_negeted_point[l] = secp->Negation(endomorphism_beta[(j*4)+l]); + } + secp->GetHash160(P2PKH,false,endomorphism_beta[(j*4)], endomorphism_beta[(j*4)+1], endomorphism_beta[(j*4)+2], endomorphism_beta[(j*4)+3] ,(uint8_t*)publickeyhashrmd160_endomorphism[8][0],(uint8_t*)publickeyhashrmd160_endomorphism[8][1],(uint8_t*)publickeyhashrmd160_endomorphism[8][2],(uint8_t*)publickeyhashrmd160_endomorphism[8][3]); + secp->GetHash160(P2PKH,false,endomorphism_negeted_point[(j*4)],endomorphism_negeted_point[(j*4)+1],endomorphism_negeted_point[(j*4)+2],endomorphism_negeted_point[(j*4)+3],(uint8_t*)publickeyhashrmd160_endomorphism[9][0],(uint8_t*)publickeyhashrmd160_endomorphism[9][1],(uint8_t*)publickeyhashrmd160_endomorphism[9][2],(uint8_t*)publickeyhashrmd160_endomorphism[9][3]); + + for(l = 0; l < 4; l++) { + endomorphism_negeted_point[l] = secp->Negation(endomorphism_beta2[(j*4)+l]); + } + secp->GetHash160(P2PKH,false, endomorphism_beta2[(j*4)], endomorphism_beta2[(j*4)+1] , endomorphism_beta2[(j*4)+2] , endomorphism_beta2[(j*4)+3] ,(uint8_t*)publickeyhashrmd160_endomorphism[10][0],(uint8_t*)publickeyhashrmd160_endomorphism[10][1],(uint8_t*)publickeyhashrmd160_endomorphism[10][2],(uint8_t*)publickeyhashrmd160_endomorphism[10][3]); + secp->GetHash160(P2PKH,false, endomorphism_negeted_point[(j*4)], endomorphism_negeted_point[(j*4)+1], endomorphism_negeted_point[(j*4)+2],endomorphism_negeted_point[(j*4)+3],(uint8_t*)publickeyhashrmd160_endomorphism[11][0],(uint8_t*)publickeyhashrmd160_endomorphism[11][1],(uint8_t*)publickeyhashrmd160_endomorphism[11][2],(uint8_t*)publickeyhashrmd160_endomorphism[11][3]); + + } + else { + secp->GetHash160(P2PKH,false,pts[(j*4)],pts[(j*4)+1],pts[(j*4)+2],pts[(j*4)+3],(uint8_t*)publickeyhashrmd160_uncompress[0],(uint8_t*)publickeyhashrmd160_uncompress[1],(uint8_t*)publickeyhashrmd160_uncompress[2],(uint8_t*)publickeyhashrmd160_uncompress[3]); + + } + } + } + break; + } + + + switch(FLAGMODE) { + case MODE_RMD160: + case MODE_ADDRESS: + if( FLAGCRYPTO == CRYPTO_BTC) { + + for(k = 0; k < 4;k++) { + if(FLAGSEARCH == SEARCH_COMPRESS || FLAGSEARCH == SEARCH_BOTH){ + if(FLAGENDOMORPHISM) { + for(l = 0;l < 6; l++) { + r = bloom_check(&bloom,publickeyhashrmd160_endomorphism[l][k],MAXLENGTHADDRESS); + if(r) { + r = searchbinary(addressTable,publickeyhashrmd160_endomorphism[l][k],N); + if(r) { + keyfound.SetInt32(k); + keyfound.Mult(&stride); + keyfound.Add(&key_mpz); + publickey = secp->ComputePublicKey(&keyfound); + switch(l) { + case 0: //Original point, prefix 02 + if(publickey.y.IsOdd()) { //if the current publickey is odd that means, we need to negate the keyfound to get the correct key + keyfound.Neg(); + keyfound.Add(&secp->order); + } + // else we dont need to chage the current keyfound because it already have prefix 02 + break; + case 1: //Original point, prefix 03 + if(publickey.y.IsEven()) { //if the current publickey is even that means, we need to negate the keyfound to get the correct key + keyfound.Neg(); + keyfound.Add(&secp->order); + } + // else we dont need to chage the current keyfound because it already have prefix 03 + break; + case 2: //Beta point, prefix 02 + keyfound.ModMulK1order(&lambda); + if(publickey.y.IsOdd()) { //if the current publickey is odd that means, we need to negate the keyfound to get the correct key + keyfound.Neg(); + keyfound.Add(&secp->order); + } + // else we dont need to chage the current keyfound because it already have prefix 02 + break; + case 3: //Beta point, prefix 03 + keyfound.ModMulK1order(&lambda); + if(publickey.y.IsEven()) { //if the current publickey is even that means, we need to negate the keyfound to get the correct key + keyfound.Neg(); + keyfound.Add(&secp->order); + } + // else we dont need to chage the current keyfound because it already have prefix 02 + break; + case 4: //Beta^2 point, prefix 02 + keyfound.ModMulK1order(&lambda2); + if(publickey.y.IsOdd()) { //if the current publickey is odd that means, we need to negate the keyfound to get the correct key + keyfound.Neg(); + keyfound.Add(&secp->order); + } + // else we dont need to chage the current keyfound because it already have prefix 02 + break; + case 5: //Beta^2 point, prefix 03 + keyfound.ModMulK1order(&lambda2); + if(publickey.y.IsEven()) { //if the current publickey is even that means, we need to negate the keyfound to get the correct key + keyfound.Neg(); + keyfound.Add(&secp->order); + } + // else we dont need to chage the current keyfound because it already have prefix 02 + break; + } + writekey(true,&keyfound); + } + } + } + } + else { + for(l = 0;l < 2; l++) { + r = bloom_check(&bloom,publickeyhashrmd160_endomorphism[l][k],MAXLENGTHADDRESS); + if(r) { + r = searchbinary(addressTable,publickeyhashrmd160_endomorphism[l][k],N); + if(r) { + keyfound.SetInt32(k); + keyfound.Mult(&stride); + keyfound.Add(&key_mpz); + + publickey = secp->ComputePublicKey(&keyfound); + secp->GetHash160(P2PKH,true,publickey,(uint8_t*)publickeyhashrmd160); + if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160,20) != 0) { + keyfound.Neg(); + keyfound.Add(&secp->order); + } + writekey(true,&keyfound); + } + } + } + } + } + + if(FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH) { + if(FLAGENDOMORPHISM) { + for(l = 6;l < 12; l++) { //We check the array from 6 to 12(excluded) because we save the uncompressed information there + r = bloom_check(&bloom,publickeyhashrmd160_endomorphism[l][k],MAXLENGTHADDRESS); //Check in Bloom filter + if(r) { + r = searchbinary(addressTable,publickeyhashrmd160_endomorphism[l][k],N); //Check in Array using Binary search + if(r) { + keyfound.SetInt32(k); + keyfound.Mult(&stride); + keyfound.Add(&key_mpz); + switch(l) { + case 6: + case 7: + publickey = secp->ComputePublicKey(&keyfound); + secp->GetHash160(P2PKH,false,publickey,(uint8_t*)publickeyhashrmd160_uncompress[0]); + if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160_uncompress[0],20) != 0){ + keyfound.Neg(); + keyfound.Add(&secp->order); + } + break; + case 8: + case 9: + keyfound.ModMulK1order(&lambda); + publickey = secp->ComputePublicKey(&keyfound); + secp->GetHash160(P2PKH,false,publickey,(uint8_t*)publickeyhashrmd160_uncompress[0]); + if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160_uncompress[0],20) != 0){ + keyfound.Neg(); + keyfound.Add(&secp->order); + } + break; + case 10: + case 11: + keyfound.ModMulK1order(&lambda2); + publickey = secp->ComputePublicKey(&keyfound); + secp->GetHash160(P2PKH,false,publickey,(uint8_t*)publickeyhashrmd160_uncompress[0]); + if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160_uncompress[0],20) != 0){ + keyfound.Neg(); + keyfound.Add(&secp->order); + } + break; + } + writekey(false,&keyfound); + } + } + } + } + else { + r = bloom_check(&bloom,publickeyhashrmd160_uncompress[k],MAXLENGTHADDRESS); + if(r) { + r = searchbinary(addressTable,publickeyhashrmd160_uncompress[k],N); + if(r) { + keyfound.SetInt32(k); + keyfound.Mult(&stride); + keyfound.Add(&key_mpz); + + writekey(false,&keyfound); + + } + } + } + } + } + } + + if( FLAGCRYPTO == CRYPTO_ETH) { + for(k = 0; k < 4;k++) { + generate_binaddress_eth(pts[(4*j)+k],(unsigned char*)rawvalue); + + r = bloom_check(&bloom,rawvalue+12,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(addressTable,rawvalue+12,N); + if(r) { + keyfound.SetInt32(k); + keyfound.Mult(&stride); + keyfound.Add(&key_mpz); + hextemp = keyfound.GetBase16(); + hexstrpoint[0] = '0'; + hexstrpoint[1] = 'x'; + tohex_dst(rawvalue+12,20,hexstrpoint+2); + +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_keys, INFINITE); +#else + pthread_mutex_lock(&write_keys); +#endif + + keys = fopen("KEYFOUNDKEYFOUND.txt","a+"); + if(keys != NULL) { + fprintf(keys,"Private Key: %s\naddress: %s\n",hextemp,hexstrpoint); + fclose(keys); + } + printf("\n Hit!!!! Private Key: %s\naddress: %s\n",hextemp,hexstrpoint); +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(write_keys); +#else + pthread_mutex_unlock(&write_keys); +#endif + + free(hextemp); + } + } + } + + } + break; + case MODE_XPOINT: + for(k = 0; k < 4;k++) { + if(FLAGENDOMORPHISM) { + pts[(4*j)+k].x.Get32Bytes((unsigned char *)rawvalue); + r = bloom_check(&bloom,rawvalue,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(addressTable,rawvalue,N); + if(r) { + keyfound.SetInt32(k); + keyfound.Mult(&stride); + keyfound.Add(&key_mpz); + + writekey(false,&keyfound); + } + } + endomorphism_beta[(j*4)+k].x.Get32Bytes((unsigned char *)rawvalue); + r = bloom_check(&bloom,rawvalue,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(addressTable,rawvalue,N); + if(r) { + keyfound.SetInt32(k); + keyfound.Mult(&stride); + keyfound.Add(&key_mpz); + keyfound.ModMulK1order(&lambda); + + writekey(false,&keyfound); + } + } + + endomorphism_beta2[(j*4)+k].x.Get32Bytes((unsigned char *)rawvalue); + r = bloom_check(&bloom,rawvalue,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(addressTable,rawvalue,N); + if(r) { + keyfound.SetInt32(k); + keyfound.Mult(&stride); + keyfound.Add(&key_mpz); + keyfound.ModMulK1order(&lambda2); + writekey(false,&keyfound); + } + } + } + else { + pts[(4*j)+k].x.Get32Bytes((unsigned char *)rawvalue); + r = bloom_check(&bloom,rawvalue,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(addressTable,rawvalue,N); + if(r) { + keyfound.SetInt32(k); + keyfound.Mult(&stride); + keyfound.Add(&key_mpz); + + writekey(false,&keyfound); + } + } + } + } + break; + } + count+=4; + temp_stride.SetInt32(4); + temp_stride.Mult(&stride); + key_mpz.Add(&temp_stride); + } + + steps[thread_number]++; + + // Next start point (startP + GRP_SIZE*G) + pp = startP; + dy.ModSub(&_2Gn.y,&pp.y); + + _s.ModMulK1(&dy,&dx[i + 1]); + _p.ModSquareK1(&_s); + + pp.x.ModNeg(); + pp.x.ModAdd(&_p); + pp.x.ModSub(&_2Gn.x); + + //The Y value for the next start point always need to be calculated + pp.y.ModSub(&_2Gn.x,&pp.x); + pp.y.ModMulK1(&_s); + pp.y.ModSub(&_2Gn.y); + startP = pp; + }while(count < N_SEQUENTIAL_MAX && continue_flag); + } + } while(continue_flag); + ends[thread_number] = 1; + return NULL; +} + + +#if defined(_WIN64) && !defined(__CYGWIN__) +DWORD WINAPI thread_process_vanity(LPVOID vargp) { +#else +void *thread_process_vanity(void *vargp) { +#endif + struct tothread *tt; + Point pts[CPU_GRP_SIZE]; + Point endomorphism_beta[CPU_GRP_SIZE]; + Point endomorphism_beta2[CPU_GRP_SIZE]; + Point endomorphism_negeted_point[4]; + + Int dx[CPU_GRP_SIZE / 2 + 1]; + + IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1); + Point startP; + Int dy; + Int dyn; + Int _s; + Int _p; + Point pp; //point positive + Point pn; //point negative + int i,hLength = (CPU_GRP_SIZE / 2 - 1); + int l,pp_offset,pn_offset; + uint64_t j,count; + Point R,temporal,publickey; + int thread_number,continue_flag = 1,k; + char *hextemp = NULL; + char publickeyhashrmd160[20]; + char publickeyhashrmd160_uncompress[4][20]; + char publickeyhashrmd160_endomorphism[12][4][20]; + + Int key_mpz,temp_stride,keyfound; + tt = (struct tothread *)vargp; + thread_number = tt->nt; + free(tt); + grp->Set(dx); + + + //if FLAGENDOMORPHISM == 1 and only compress search is enabled then there is no need to calculate the Y value value + + bool calculate_y = FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH; + + /* + if(FLAGDEBUG && thread_number == 0) { + printf("[D] vanity_rmd_targets = %i fillllll\n",vanity_rmd_targets); + printf("[D] vanity_rmd_total = %i\n",vanity_rmd_total); + for(i =0; i < vanity_rmd_targets;i++) { + printf("[D] vanity_rmd_limits[%li] = %i\n",i,vanity_rmd_limits[i]); + + } + printf("[D] vanity_rmd_minimun_bytes_check_length = %i\n",vanity_rmd_minimun_bytes_check_length); + } + */ + + + do { + if(FLAGRANDOM){ + key_mpz.Rand(&n_range_start,&n_range_end); + } + else { + if(n_range_start.IsLower(&n_range_end)) { +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_random, INFINITE); + key_mpz.Set(&n_range_start); + n_range_start.Add(N_SEQUENTIAL_MAX); + ReleaseMutex(write_random); +#else + pthread_mutex_lock(&write_random); + key_mpz.Set(&n_range_start); + n_range_start.Add(N_SEQUENTIAL_MAX); + pthread_mutex_unlock(&write_random); +#endif + } + else { + continue_flag = 0; + } + } + if(continue_flag) { + count = 0; + if(FLAGMATRIX) { + hextemp = key_mpz.GetBase16(); + printf("Base key: %s thread %i\n",hextemp,thread_number); + fflush(stdout); + free(hextemp); + } + else { + if(FLAGQUIET == 0) { + hextemp = key_mpz.GetBase16(); + printf("\rBase key: %s \r",hextemp); + fflush(stdout); + free(hextemp); + THREADOUTPUT = 1; + } + } + do { + temp_stride.SetInt32(CPU_GRP_SIZE / 2); + temp_stride.Mult(&stride); + key_mpz.Add(&temp_stride); + startP = secp->ComputePublicKey(&key_mpz); + key_mpz.Sub(&temp_stride); + + for(i = 0; i < hLength; i++) { + dx[i].ModSub(&Gn[i].x,&startP.x); + } + + dx[i].ModSub(&Gn[i].x,&startP.x); // For the first point + dx[i + 1].ModSub(&_2Gn.x,&startP.x); // For the next center point + grp->ModInv(); + + pts[CPU_GRP_SIZE / 2] = startP; + + for(i = 0; iGetPublicKeyHex(false,pp); + secp->GetHash160(P2PKH,false, pp,(uint8_t*)publickeyhashrmd160_uncompress[0]); + rmd160toaddress_dst(publickeyhashrmd160_uncompress[0],address); + printf("[D] pp[%i] = %s , %s y = %s\n",pp_offset,hextemp,address,pp.y.IsEven() ? "Even" : "Odd"); + free(hextemp); + + hextemp = secp->GetPublicKeyHex(false,pn); + secp->GetHash160(P2PKH,false, pn,(uint8_t*)publickeyhashrmd160_uncompress[0]); + rmd160toaddress_dst(publickeyhashrmd160_uncompress[0],address); + printf("[D] pn[%i] = %s , %s y = %s\n",pn_offset,hextemp,address,pn.y.IsEven() ? "Even" : "Odd"); + free(hextemp); + + + hextemp = secp->GetPublicKeyHex(false,endomorphism_beta[pp_offset]); + secp->GetHash160(P2PKH,false, endomorphism_beta[pp_offset],(uint8_t*)publickeyhashrmd160_uncompress[0]); + rmd160toaddress_dst(publickeyhashrmd160_uncompress[0],address); + printf("[D] endomorphism_beta[%i] = %s , %s y = %s\n",pp_offset,hextemp,address,endomorphism_beta[pp_offset].y.IsEven() ? "Even" : "Odd"); + free(hextemp); + hextemp = secp->GetPublicKeyHex(false,endomorphism_beta[pn_offset]); + secp->GetHash160(P2PKH,false, endomorphism_beta[pn_offset],(uint8_t*)publickeyhashrmd160_uncompress[0]); + rmd160toaddress_dst(publickeyhashrmd160_uncompress[0],address); + + printf("[D] endomorphism_beta[%i] = %s , %s y = %s\n",pn_offset,hextemp,address,endomorphism_beta[pn_offset].y.IsEven() ? "Even" : "Odd"); + free(hextemp); + hextemp = secp->GetPublicKeyHex(false,endomorphism_beta2[pp_offset]); + secp->GetHash160(P2PKH,false, endomorphism_beta2[pp_offset],(uint8_t*)publickeyhashrmd160_uncompress[0]); + rmd160toaddress_dst(publickeyhashrmd160_uncompress[0],address); + printf("[D] endomorphism_beta2[%i] = %s , %s y = %s\n",pp_offset,hextemp,address,endomorphism_beta2[pp_offset].y.IsEven() ? "Even" : "Odd"); + free(hextemp); + hextemp = secp->GetPublicKeyHex(false,endomorphism_beta2[pn_offset]); + secp->GetHash160(P2PKH,false, endomorphism_beta2[pn_offset],(uint8_t*)publickeyhashrmd160_uncompress[0]); + rmd160toaddress_dst(publickeyhashrmd160_uncompress[0],address); + printf("[D] endomorphism_beta2[%i] = %s , %s y = %s\n",pn_offset,hextemp,address,endomorphism_beta2[pn_offset].y.IsEven() ? "Even" : "Odd"); + free(hextemp); + } + */ + } + } + /* + Half point for endomorphism because pts[CPU_GRP_SIZE / 2] was not calcualte in the previous cycle + */ + if(FLAGENDOMORPHISM) { + if( calculate_y ) { + + endomorphism_beta[CPU_GRP_SIZE / 2].y.Set(&pts[CPU_GRP_SIZE / 2].y); + endomorphism_beta2[CPU_GRP_SIZE / 2].y.Set(&pts[CPU_GRP_SIZE / 2].y); + } + endomorphism_beta[CPU_GRP_SIZE / 2].x.ModMulK1(&pts[CPU_GRP_SIZE / 2].x, &beta); + endomorphism_beta2[CPU_GRP_SIZE / 2].x.ModMulK1(&pts[CPU_GRP_SIZE / 2].x, &beta2); + } + + // First point (startP - (GRP_SZIE/2)*G) + pn = startP; + dyn.Set(&Gn[i].y); + dyn.ModNeg(); + dyn.ModSub(&pn.y); + + _s.ModMulK1(&dyn,&dx[i]); + _p.ModSquareK1(&_s); + + pn.x.ModNeg(); + pn.x.ModAdd(&_p); + pn.x.ModSub(&Gn[i].x); + + if(calculate_y ) { + pn.y.ModSub(&Gn[i].x,&pn.x); + pn.y.ModMulK1(&_s); + pn.y.ModAdd(&Gn[i].y); + } + pts[0] = pn; + + /* + First point for endomorphism because pts[0] was not calcualte previously + */ + if(FLAGENDOMORPHISM) { + if( calculate_y ) { + endomorphism_beta[0].y.Set(&pn.y); + endomorphism_beta2[0].y.Set(&pn.y); + } + endomorphism_beta[0].x.ModMulK1(&pn.x, &beta); + endomorphism_beta2[0].x.ModMulK1(&pn.x, &beta2); + } + + + for(j = 0; j < CPU_GRP_SIZE/4;j++) { + if(FLAGSEARCH == SEARCH_COMPRESS || FLAGSEARCH == SEARCH_BOTH ){ + if(FLAGENDOMORPHISM) { + secp->GetHash160_fromX(P2PKH,0x02,&pts[(j*4)].x,&pts[(j*4)+1].x,&pts[(j*4)+2].x,&pts[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[0][0],(uint8_t*)publickeyhashrmd160_endomorphism[0][1],(uint8_t*)publickeyhashrmd160_endomorphism[0][2],(uint8_t*)publickeyhashrmd160_endomorphism[0][3]); + secp->GetHash160_fromX(P2PKH,0x03,&pts[(j*4)].x,&pts[(j*4)+1].x,&pts[(j*4)+2].x,&pts[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[1][0],(uint8_t*)publickeyhashrmd160_endomorphism[1][1],(uint8_t*)publickeyhashrmd160_endomorphism[1][2],(uint8_t*)publickeyhashrmd160_endomorphism[1][3]); + + secp->GetHash160_fromX(P2PKH,0x02,&endomorphism_beta[(j*4)].x,&endomorphism_beta[(j*4)+1].x,&endomorphism_beta[(j*4)+2].x,&endomorphism_beta[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[2][0],(uint8_t*)publickeyhashrmd160_endomorphism[2][1],(uint8_t*)publickeyhashrmd160_endomorphism[2][2],(uint8_t*)publickeyhashrmd160_endomorphism[2][3]); + secp->GetHash160_fromX(P2PKH,0x03,&endomorphism_beta[(j*4)].x,&endomorphism_beta[(j*4)+1].x,&endomorphism_beta[(j*4)+2].x,&endomorphism_beta[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[3][0],(uint8_t*)publickeyhashrmd160_endomorphism[3][1],(uint8_t*)publickeyhashrmd160_endomorphism[3][2],(uint8_t*)publickeyhashrmd160_endomorphism[3][3]); + + secp->GetHash160_fromX(P2PKH,0x02,&endomorphism_beta2[(j*4)].x,&endomorphism_beta2[(j*4)+1].x,&endomorphism_beta2[(j*4)+2].x,&endomorphism_beta2[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[4][0],(uint8_t*)publickeyhashrmd160_endomorphism[4][1],(uint8_t*)publickeyhashrmd160_endomorphism[4][2],(uint8_t*)publickeyhashrmd160_endomorphism[4][3]); + secp->GetHash160_fromX(P2PKH,0x03,&endomorphism_beta2[(j*4)].x,&endomorphism_beta2[(j*4)+1].x,&endomorphism_beta2[(j*4)+2].x,&endomorphism_beta2[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[5][0],(uint8_t*)publickeyhashrmd160_endomorphism[5][1],(uint8_t*)publickeyhashrmd160_endomorphism[5][2],(uint8_t*)publickeyhashrmd160_endomorphism[5][3]); + + } + else { + secp->GetHash160_fromX(P2PKH,0x02,&pts[(j*4)].x,&pts[(j*4)+1].x,&pts[(j*4)+2].x,&pts[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[0][0],(uint8_t*)publickeyhashrmd160_endomorphism[0][1],(uint8_t*)publickeyhashrmd160_endomorphism[0][2],(uint8_t*)publickeyhashrmd160_endomorphism[0][3]); + secp->GetHash160_fromX(P2PKH,0x03,&pts[(j*4)].x,&pts[(j*4)+1].x,&pts[(j*4)+2].x,&pts[(j*4)+3].x,(uint8_t*)publickeyhashrmd160_endomorphism[1][0],(uint8_t*)publickeyhashrmd160_endomorphism[1][1],(uint8_t*)publickeyhashrmd160_endomorphism[1][2],(uint8_t*)publickeyhashrmd160_endomorphism[1][3]); + } + } + if(FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH) { + if(FLAGENDOMORPHISM) { + for(l = 0; l < 4; l++) { + endomorphism_negeted_point[l] = secp->Negation(pts[(j*4)+l]); + } + secp->GetHash160(P2PKH,false, pts[(j*4)], pts[(j*4)+1], pts[(j*4)+2], pts[(j*4)+3],(uint8_t*)publickeyhashrmd160_endomorphism[6][0],(uint8_t*)publickeyhashrmd160_endomorphism[6][1],(uint8_t*)publickeyhashrmd160_endomorphism[6][2],(uint8_t*)publickeyhashrmd160_endomorphism[6][3]); + secp->GetHash160(P2PKH,false,endomorphism_negeted_point[(j*4)] ,endomorphism_negeted_point[(j*4)+1],endomorphism_negeted_point[(j*4)+2],endomorphism_negeted_point[(j*4)+3],(uint8_t*)publickeyhashrmd160_endomorphism[7][0],(uint8_t*)publickeyhashrmd160_endomorphism[7][1],(uint8_t*)publickeyhashrmd160_endomorphism[7][2],(uint8_t*)publickeyhashrmd160_endomorphism[7][3]); + for(l = 0; l < 4; l++) { + endomorphism_negeted_point[l] = secp->Negation(endomorphism_beta[(j*4)+l]); + } + secp->GetHash160(P2PKH,false,endomorphism_beta[(j*4)], endomorphism_beta[(j*4)+1], endomorphism_beta[(j*4)+2], endomorphism_beta[(j*4)+3] ,(uint8_t*)publickeyhashrmd160_endomorphism[8][0],(uint8_t*)publickeyhashrmd160_endomorphism[8][1],(uint8_t*)publickeyhashrmd160_endomorphism[8][2],(uint8_t*)publickeyhashrmd160_endomorphism[8][3]); + secp->GetHash160(P2PKH,false,endomorphism_negeted_point[(j*4)],endomorphism_negeted_point[(j*4)+1],endomorphism_negeted_point[(j*4)+2],endomorphism_negeted_point[(j*4)+3],(uint8_t*)publickeyhashrmd160_endomorphism[9][0],(uint8_t*)publickeyhashrmd160_endomorphism[9][1],(uint8_t*)publickeyhashrmd160_endomorphism[9][2],(uint8_t*)publickeyhashrmd160_endomorphism[9][3]); + + for(l = 0; l < 4; l++) { + endomorphism_negeted_point[l] = secp->Negation(endomorphism_beta2[(j*4)+l]); + } + secp->GetHash160(P2PKH,false, endomorphism_beta2[(j*4)], endomorphism_beta2[(j*4)+1] , endomorphism_beta2[(j*4)+2] , endomorphism_beta2[(j*4)+3] ,(uint8_t*)publickeyhashrmd160_endomorphism[10][0],(uint8_t*)publickeyhashrmd160_endomorphism[10][1],(uint8_t*)publickeyhashrmd160_endomorphism[10][2],(uint8_t*)publickeyhashrmd160_endomorphism[10][3]); + secp->GetHash160(P2PKH,false, endomorphism_negeted_point[(j*4)], endomorphism_negeted_point[(j*4)+1], endomorphism_negeted_point[(j*4)+2],endomorphism_negeted_point[(j*4)+3],(uint8_t*)publickeyhashrmd160_endomorphism[11][0],(uint8_t*)publickeyhashrmd160_endomorphism[11][1],(uint8_t*)publickeyhashrmd160_endomorphism[11][2],(uint8_t*)publickeyhashrmd160_endomorphism[11][3]); + } + else { + secp->GetHash160(P2PKH,false,pts[(j*4)],pts[(j*4)+1],pts[(j*4)+2],pts[(j*4)+3],(uint8_t*)publickeyhashrmd160_uncompress[0],(uint8_t*)publickeyhashrmd160_uncompress[1],(uint8_t*)publickeyhashrmd160_uncompress[2],(uint8_t*)publickeyhashrmd160_uncompress[3]); + + } + } + for(k = 0; k < 4;k++) { + if(FLAGSEARCH == SEARCH_COMPRESS || FLAGSEARCH == SEARCH_BOTH ){ + if(FLAGENDOMORPHISM) { + for(l = 0;l < 6; l++) { + if(vanityrmdmatch((uint8_t*)publickeyhashrmd160_endomorphism[l][k])) { + // Here the given publickeyhashrmd160 match againts one of the vanity targets + // We need to check which of the cases is it. + + keyfound.SetInt32(k); + keyfound.Mult(&stride); + keyfound.Add(&key_mpz); + publickey = secp->ComputePublicKey(&keyfound); + + /* + if(FLAGDEBUG) { + + rmd160toaddress_dst(publickeyhashrmd160_endomorphism[l][k],address); + + hextemp = tohex(publickeyhashrmd160_endomorphism[l][k],20); + printf("[D] hash found: %s : address %s\n",hextemp,address); + free(hextemp); + hextemp = keyfound.GetBase16(); + printf("[D] key: %s\n",hextemp); + free(hextemp); + + hextemp = secp->GetPublicKeyHex(true,publickey); + printf("[D] GetPublicKeyHex: %s\n",hextemp); + free(hextemp); + + printf("[D] found something l = %i\n",l); + + } + */ + + switch(l) { + case 0: //Original point, prefix 02 + if(publickey.y.IsOdd()) { //if the current publickey is odd that means, we need to negate the keyfound to get the correct key + keyfound.Neg(); + keyfound.Add(&secp->order); + } + // else we dont need to chage the current keyfound because it already have prefix 02 + break; + case 1: //Original point, prefix 03 + if(publickey.y.IsEven()) { //if the current publickey is even that means, we need to negate the keyfound to get the correct key + keyfound.Neg(); + keyfound.Add(&secp->order); + } + // else we dont need to chage the current keyfound because it already have prefix 03 + break; + case 2: //Beta point, prefix 02 + keyfound.ModMulK1order(&lambda); + if(publickey.y.IsOdd()) { //if the current publickey is odd that means, we need to negate the keyfound to get the correct key + keyfound.Neg(); + keyfound.Add(&secp->order); + } + // else we dont need to chage the current keyfound because it already have prefix 02 + break; + case 3: //Beta point, prefix 03 + keyfound.ModMulK1order(&lambda); + if(publickey.y.IsEven()) { //if the current publickey is even that means, we need to negate the keyfound to get the correct key + keyfound.Neg(); + keyfound.Add(&secp->order); + } + // else we dont need to chage the current keyfound because it already have prefix 02 + break; + case 4: //Beta^2 point, prefix 02 + keyfound.ModMulK1order(&lambda2); + if(publickey.y.IsOdd()) { //if the current publickey is odd that means, we need to negate the keyfound to get the correct key + keyfound.Neg(); + keyfound.Add(&secp->order); + } + // else we dont need to chage the current keyfound because it already have prefix 02 + break; + case 5: //Beta^2 point, prefix 03 + keyfound.ModMulK1order(&lambda2); + if(publickey.y.IsEven()) { //if the current publickey is even that means, we need to negate the keyfound to get the correct key + keyfound.Neg(); + keyfound.Add(&secp->order); + } + // else we dont need to chage the current keyfound because it already have prefix 02 + break; + } + writevanitykey(true,&keyfound); + } + } + } + else { + for(l = 0;l < 2; l++) { + if(vanityrmdmatch((uint8_t*)publickeyhashrmd160_endomorphism[l][k])) { + keyfound.SetInt32(k); + keyfound.Mult(&stride); + keyfound.Add(&key_mpz); + + publickey = secp->ComputePublicKey(&keyfound); + secp->GetHash160(P2PKH,true,publickey,(uint8_t*)publickeyhashrmd160); + if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160,20) != 0){ + keyfound.Neg(); + keyfound.Add(&secp->order); + //if(FLAGDEBUG) printf("[D] Key need to be negated\n"); + } + writevanitykey(true,&keyfound); + } + } + } + } + if(FLAGSEARCH == SEARCH_UNCOMPRESS || FLAGSEARCH == SEARCH_BOTH) { + if(FLAGENDOMORPHISM) { + for(l = 6;l < 12; l++) { + if(vanityrmdmatch((uint8_t*)publickeyhashrmd160_endomorphism[l][k])) { + // Here the given publickeyhashrmd160 match againts one of the vanity targets + // We need to check which of the cases is it. + + //rmd160toaddress_dst(publickeyhashrmd160_endomorphism[l][k],address); + keyfound.SetInt32(k); + keyfound.Mult(&stride); + keyfound.Add(&key_mpz); + + + /* + if(FLAGDEBUG) { + + rmd160toaddress_dst(publickeyhashrmd160_endomorphism[l][k],address); + + hextemp = tohex(publickeyhashrmd160_endomorphism[l][k],20); + printf("[D] hash found: %s : address %s\n",hextemp,address); + free(hextemp); + hextemp = keyfound.GetBase16(); + printf("[D] key: %s\n",hextemp); + free(hextemp); + + hextemp = secp->GetPublicKeyHex(true,publickey); + printf("[D] GetPublicKeyHex: %s\n",hextemp); + free(hextemp); + + printf("[D] found something l = %i\n",l); + + } + */ + + switch(l) { + case 6: + case 7: + publickey = secp->ComputePublicKey(&keyfound); + secp->GetHash160(P2PKH,false,publickey,(uint8_t*)publickeyhashrmd160_uncompress[0]); + if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160_uncompress[0],20) != 0){ + keyfound.Neg(); + keyfound.Add(&secp->order); + } + break; + case 8: + case 9: + keyfound.ModMulK1order(&lambda); + publickey = secp->ComputePublicKey(&keyfound); + secp->GetHash160(P2PKH,false,publickey,(uint8_t*)publickeyhashrmd160_uncompress[0]); + if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160_uncompress[0],20) != 0){ + keyfound.Neg(); + keyfound.Add(&secp->order); + } + break; + case 10: + case 11: + keyfound.ModMulK1order(&lambda2); + publickey = secp->ComputePublicKey(&keyfound); + secp->GetHash160(P2PKH,false,publickey,(uint8_t*)publickeyhashrmd160_uncompress[0]); + if(memcmp(publickeyhashrmd160_endomorphism[l][k],publickeyhashrmd160_uncompress[0],20) != 0){ + keyfound.Neg(); + keyfound.Add(&secp->order); + } + break; + } + writevanitykey(false,&keyfound); + } + } + + } + else { + if(vanityrmdmatch((uint8_t*)publickeyhashrmd160_uncompress[k])) { + keyfound.SetInt32(k); + keyfound.Mult(&stride); + keyfound.Add(&key_mpz); + writevanitykey(false,&keyfound); + } + } + } + + } + + count+=4; + temp_stride.SetInt32(4); + temp_stride.Mult(&stride); + key_mpz.Add(&temp_stride); + } + steps[thread_number]++; + + // Next start point (startP + GRP_SIZE*G) + pp = startP; + dy.ModSub(&_2Gn.y,&pp.y); + + _s.ModMulK1(&dy,&dx[i + 1]); + _p.ModSquareK1(&_s); + + pp.x.ModNeg(); + pp.x.ModAdd(&_p); + pp.x.ModSub(&_2Gn.x); + + //The Y value for the next start point always need to be calculated + pp.y.ModSub(&_2Gn.x,&pp.x); + pp.y.ModMulK1(&_s); + pp.y.ModSub(&_2Gn.y); + startP = pp; + }while(count < N_SEQUENTIAL_MAX && continue_flag); + } + } while(continue_flag); + ends[thread_number] = 1; + return NULL; +} + +void _swap(struct address_value *a,struct address_value *b) { + struct address_value t; + t = *a; + *a = *b; + *b = t; +} + +void _sort(struct address_value *arr,int64_t n) { + uint32_t depthLimit = ((uint32_t) ceil(log(n))) * 2; + _introsort(arr,depthLimit,n); +} + +void _introsort(struct address_value *arr,uint32_t depthLimit, int64_t n) { + int64_t p; + if(n > 1) { + if(n <= 16) { + _insertionsort(arr,n); + } + else { + if(depthLimit == 0) { + _myheapsort(arr,n); + } + else { + p = _partition(arr,n); + if(p > 0) _introsort(arr , depthLimit-1 , p); + if(p < n) _introsort(&arr[p+1],depthLimit-1,n-(p+1)); + } + } + } +} + +void _insertionsort(struct address_value *arr, int64_t n) { + int64_t j; + int64_t i; + struct address_value key; + for(i = 1; i < n ; i++ ) { + key = arr[i]; + j= i-1; + while(j >= 0 && memcmp(arr[j].value,key.value,20) > 0) { + arr[j+1] = arr[j]; + j--; + } + arr[j+1] = key; + } +} + +int64_t _partition(struct address_value *arr, int64_t n) { + struct address_value pivot; + int64_t r,left,right; + r = n/2; + pivot = arr[r]; + left = 0; + right = n-1; + do { + while(left < right && memcmp(arr[left].value,pivot.value,20) <= 0 ) { + left++; + } + while(right >= left && memcmp(arr[right].value,pivot.value,20) > 0) { + right--; + } + if(left < right) { + if(left == r || right == r) { + if(left == r) { + r = right; + } + if(right == r) { + r = left; + } + } + _swap(&arr[right],&arr[left]); + } + }while(left < right); + if(right != r) { + _swap(&arr[right],&arr[r]); + } + return right; +} + +void _heapify(struct address_value *arr, int64_t n, int64_t i) { + int64_t largest = i; + int64_t l = 2 * i + 1; + int64_t r = 2 * i + 2; + if (l < n && memcmp(arr[l].value,arr[largest].value,20) > 0) + largest = l; + if (r < n && memcmp(arr[r].value,arr[largest].value,20) > 0) + largest = r; + if (largest != i) { + _swap(&arr[i],&arr[largest]); + _heapify(arr, n, largest); + } +} + +void _myheapsort(struct address_value *arr, int64_t n) { + int64_t i; + for ( i = (n / 2) - 1; i >= 0; i--) { + _heapify(arr, n, i); + } + for ( i = n - 1; i > 0; i--) { + _swap(&arr[0] , &arr[i]); + _heapify(arr, i, 0); + } +} + +/* OK */ +void bsgs_swap(struct bsgs_xvalue *a,struct bsgs_xvalue *b) { + struct bsgs_xvalue t; + t = *a; + *a = *b; + *b = t; +} + +/* OK */ +void bsgs_sort(struct bsgs_xvalue *arr,int64_t n) { + uint32_t depthLimit = ((uint32_t) ceil(log(n))) * 2; + bsgs_introsort(arr,depthLimit,n); +} + +/* OK */ +void bsgs_introsort(struct bsgs_xvalue *arr,uint32_t depthLimit, int64_t n) { + int64_t p; + if(n > 1) { + if(n <= 16) { + bsgs_insertionsort(arr,n); + } + else { + if(depthLimit == 0) { + bsgs_myheapsort(arr,n); + } + else { + p = bsgs_partition(arr,n); + if(p > 0) bsgs_introsort(arr , depthLimit-1 , p); + if(p < n) bsgs_introsort(&arr[p+1],depthLimit-1,n-(p+1)); + } + } + } +} + +/* OK */ +void bsgs_insertionsort(struct bsgs_xvalue *arr, int64_t n) { + int64_t j; + int64_t i; + struct bsgs_xvalue key; + for(i = 1; i < n ; i++ ) { + key = arr[i]; + j= i-1; + while(j >= 0 && memcmp(arr[j].value,key.value,BSGS_XVALUE_RAM) > 0) { + arr[j+1] = arr[j]; + j--; + } + arr[j+1] = key; + } +} + +int64_t bsgs_partition(struct bsgs_xvalue *arr, int64_t n) { + struct bsgs_xvalue pivot; + int64_t r,left,right; + r = n/2; + pivot = arr[r]; + left = 0; + right = n-1; + do { + while(left < right && memcmp(arr[left].value,pivot.value,BSGS_XVALUE_RAM) <= 0 ) { + left++; + } + while(right >= left && memcmp(arr[right].value,pivot.value,BSGS_XVALUE_RAM) > 0) { + right--; + } + if(left < right) { + if(left == r || right == r) { + if(left == r) { + r = right; + } + if(right == r) { + r = left; + } + } + bsgs_swap(&arr[right],&arr[left]); + } + }while(left < right); + if(right != r) { + bsgs_swap(&arr[right],&arr[r]); + } + return right; +} + +void bsgs_heapify(struct bsgs_xvalue *arr, int64_t n, int64_t i) { + int64_t largest = i; + int64_t l = 2 * i + 1; + int64_t r = 2 * i + 2; + if (l < n && memcmp(arr[l].value,arr[largest].value,BSGS_XVALUE_RAM) > 0) + largest = l; + if (r < n && memcmp(arr[r].value,arr[largest].value,BSGS_XVALUE_RAM) > 0) + largest = r; + if (largest != i) { + bsgs_swap(&arr[i],&arr[largest]); + bsgs_heapify(arr, n, largest); + } +} + +void bsgs_myheapsort(struct bsgs_xvalue *arr, int64_t n) { + int64_t i; + for ( i = (n / 2) - 1; i >= 0; i--) { + bsgs_heapify(arr, n, i); + } + for ( i = n - 1; i > 0; i--) { + bsgs_swap(&arr[0] , &arr[i]); + bsgs_heapify(arr, i, 0); + } +} + +int bsgs_searchbinary(struct bsgs_xvalue *buffer,char *data,int64_t array_length,uint64_t *r_value) { + int64_t min,max,half,current; + int r = 0,rcmp; + min = 0; + current = 0; + max = array_length; + half = array_length; + while(!r && half >= 1) { + half = (max - min)/2; + rcmp = memcmp(data+16,buffer[current+half].value,BSGS_XVALUE_RAM); + if(rcmp == 0) { + *r_value = buffer[current+half].index; + r = 1; + } + else { + if(rcmp < 0) { + max = (max-half); + } + else { + min = (min+half); + } + current = min; + } + } + return r; +} + +#if defined(_WIN64) && !defined(__CYGWIN__) +DWORD WINAPI thread_process_bsgs(LPVOID vargp) { +#else +void *thread_process_bsgs(void *vargp) { +#endif + + FILE *filekey; + struct tothread *tt; + char xpoint_raw[32],*aux_c,*hextemp; + Int base_key,keyfound; + Point base_point,point_aux,point_found; + uint32_t j,k,l,r,salir,thread_number, cycles; + IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1); + Point startP; + + int i,hLength = (CPU_GRP_SIZE / 2 - 1); + + Int dx[CPU_GRP_SIZE / 2 + 1]; + Point pts[CPU_GRP_SIZE]; + + Int dy; + Int dyn; + Int _s; + Int _p; + Int km,intaux; + Point pp; + Point pn; + grp->Set(dx); + + + tt = (struct tothread *)vargp; + thread_number = tt->nt; + free(tt); + + cycles = bsgs_aux / 1024; + if(bsgs_aux % 1024 != 0) { + cycles++; + } + + /* + We do this in an atomic pthread_mutex operation to not affect others threads + so BSGS_CURRENT is never the same between threads + */ +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(bsgs_thread, INFINITE); +#else + pthread_mutex_lock(&bsgs_thread); +#endif + + base_key.Set(&BSGS_CURRENT); /* we need to set our base_key to the current BSGS_CURRENT value*/ + BSGS_CURRENT.Add(&BSGS_N); /*Then add BSGS_N to BSGS_CURRENT*/ +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(bsgs_thread); +#else + pthread_mutex_unlock(&bsgs_thread); +#endif + + intaux.Set(&BSGS_M); + intaux.Mult(CPU_GRP_SIZE/2); + + //if(FLAGDEBUG) { printf("bsgs_aux: %lu\n",bsgs_aux);} + + /* + while base_key is less than n_range_end then: + */ + while(base_key.IsLower(&n_range_end) ) { + if(FLAGMATRIX) { + aux_c = base_key.GetBase16(); + printf("[+] Thread 0x%s \n",aux_c); + fflush(stdout); + free(aux_c); + } + else { + if(FLAGQUIET == 0){ + aux_c = base_key.GetBase16(); + printf("\r[+] Thread 0x%s \r",aux_c); + fflush(stdout); + free(aux_c); + THREADOUTPUT = 1; + } + } + + base_point = secp->ComputePublicKey(&base_key); + + km.Set(&base_key); + km.Neg(); + + km.Add(&secp->order); + km.Sub(&intaux); + point_aux = secp->ComputePublicKey(&km); + + for(k = 0; k < bsgs_point_number ; k++) { + if(bsgs_found[k] == 0) { + if(base_point.equals(OriginalPointsBSGS[k])) { + hextemp = base_key.GetBase16(); + printf("[+] Thread Key found privkey %s \n",hextemp); + aux_c = secp->GetPublicKeyHex(OriginalPointsBSGScompressed[k],base_point); + printf("[+] Publickey %s\n",aux_c); + +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_keys, INFINITE); +#else + pthread_mutex_lock(&write_keys); +#endif + + filekey = fopen("KEYFOUNDKEYFOUND.txt","a"); + if(filekey != NULL) { + fprintf(filekey,"Key found privkey %s\nPublickey %s\n",hextemp,aux_c); + fclose(filekey); + } + free(hextemp); + free(aux_c); +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(write_keys); +#else + pthread_mutex_unlock(&write_keys); +#endif + bsgs_found[k] = 1; + salir = 1; + for(l = 0; l < bsgs_point_number && salir; l++) { + salir &= bsgs_found[l]; + } + if(salir) { + printf("All points were found\n"); + exit(EXIT_FAILURE); + } + } + else { + startP = secp->AddDirect(OriginalPointsBSGS[k],point_aux); + j = 0; + while( j < cycles && bsgs_found[k]== 0 ) { + + for(i = 0; i < hLength; i++) { + dx[i].ModSub(&GSn[i].x,&startP.x); + } + dx[i].ModSub(&GSn[i].x,&startP.x); // For the first point + dx[i+1].ModSub(&_2GSn.x,&startP.x); // For the next center point + + // Grouped ModInv + grp->ModInv(); + + /* + We use the fact that P + i*G and P - i*G has the same deltax, so the same inverse + We compute key in the positive and negative way from the center of the group + */ + + // center point + pts[CPU_GRP_SIZE / 2] = startP; + + for(i = 0; iComputePublicKey(&keyfound); + aux_c = secp->GetPublicKeyHex(OriginalPointsBSGScompressed[k],point_found); + printf("[+] Publickey %s\n",aux_c); +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_keys, INFINITE); +#else + pthread_mutex_lock(&write_keys); +#endif + + filekey = fopen("KEYFOUNDKEYFOUND.txt","a"); + if(filekey != NULL) { + fprintf(filekey,"Key found privkey %s\nPublickey %s\n",hextemp,aux_c); + fclose(filekey); + } + free(hextemp); + free(aux_c); +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(write_keys); +#else + pthread_mutex_unlock(&write_keys); +#endif + bsgs_found[k] = 1; + salir = 1; + for(l = 0; l < bsgs_point_number && salir; l++) { + salir &= bsgs_found[l]; + } + if(salir) { + printf("All points were found\n"); + exit(EXIT_FAILURE); + } + } //End if second check + }//End if first check + + }// For for pts variable + + // Next start point (startP += (bsSize*GRP_SIZE).G) + + pp = startP; + dy.ModSub(&_2GSn.y,&pp.y); + + _s.ModMulK1(&dy,&dx[i + 1]); + _p.ModSquareK1(&_s); + + pp.x.ModNeg(); + pp.x.ModAdd(&_p); + pp.x.ModSub(&_2GSn.x); + + pp.y.ModSub(&_2GSn.x,&pp.x); + pp.y.ModMulK1(&_s); + pp.y.ModSub(&_2GSn.y); + startP = pp; + + j++; + } //while all the aMP points + } // end else + }// End if + } + steps[thread_number]++; +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(bsgs_thread, INFINITE); +#else + pthread_mutex_lock(&bsgs_thread); +#endif + + base_key.Set(&BSGS_CURRENT); + BSGS_CURRENT.Add(&BSGS_N); +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(bsgs_thread); +#else + pthread_mutex_unlock(&bsgs_thread); +#endif + + } + ends[thread_number] = 1; + return NULL; +} + +#if defined(_WIN64) && !defined(__CYGWIN__) +DWORD WINAPI thread_process_bsgs_random(LPVOID vargp) { +#else +void *thread_process_bsgs_random(void *vargp) { +#endif + + FILE *filekey; + struct tothread *tt; + char xpoint_raw[32],*aux_c,*hextemp; + Int base_key,keyfound,n_range_random; + Point base_point,point_aux,point_found; + uint32_t j,k,l,r,salir,thread_number,cycles; + + IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1); + Point startP; + + int hLength = (CPU_GRP_SIZE / 2 - 1); + + Int dx[CPU_GRP_SIZE / 2 + 1]; + Point pts[CPU_GRP_SIZE]; + + Int dy; + Int dyn; + Int _s; + Int _p; + Int km,intaux; + Point pp; + Point pn; + grp->Set(dx); + + + tt = (struct tothread *)vargp; + thread_number = tt->nt; + free(tt); + + cycles = bsgs_aux / 1024; + if(bsgs_aux % 1024 != 0) { + cycles++; + } + + /* | Start Range | End Range | + None | 1 | EC.N | + -b bit | Min bit value | Max bit value | + -r A:B | A | B | + */ +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(bsgs_thread, INFINITE); +#else + pthread_mutex_lock(&bsgs_thread); +#endif + + base_key.Rand(&n_range_start,&n_range_end); +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(bsgs_thread); +#else + pthread_mutex_unlock(&bsgs_thread); +#endif + intaux.Set(&BSGS_M); + intaux.Mult(CPU_GRP_SIZE/2); + + /* + while base_key is less than n_range_end then: + */ + while(base_key.IsLower(&n_range_end)) { + if(FLAGMATRIX) { + aux_c = base_key.GetBase16(); + printf("[+] Thread 0x%s \n",aux_c); + fflush(stdout); + free(aux_c); + } + else{ + if(FLAGQUIET == 0){ + aux_c = base_key.GetBase16(); + printf("\r[+] Thread 0x%s \r",aux_c); + fflush(stdout); + free(aux_c); + THREADOUTPUT = 1; + } + } + base_point = secp->ComputePublicKey(&base_key); + + km.Set(&base_key); + km.Neg(); + + + km.Add(&secp->order); + km.Sub(&intaux); + point_aux = secp->ComputePublicKey(&km); + + + /* We need to test individually every point in BSGS_Q */ + for(k = 0; k < bsgs_point_number ; k++) { + if(bsgs_found[k] == 0) { + if(base_point.equals(OriginalPointsBSGS[k])) { + hextemp = base_key.GetBase16(); + printf("[+] Thread Key found privkey %s \n",hextemp); + aux_c = secp->GetPublicKeyHex(OriginalPointsBSGScompressed[k],base_point); + printf("[+] Publickey %s\n",aux_c); + +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_keys, INFINITE); +#else + pthread_mutex_lock(&write_keys); +#endif + + filekey = fopen("KEYFOUNDKEYFOUND.txt","a"); + if(filekey != NULL) { + fprintf(filekey,"Key found privkey %s\nPublickey %s\n",hextemp,aux_c); + fclose(filekey); + } + free(hextemp); + free(aux_c); +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(write_keys); +#else + pthread_mutex_unlock(&write_keys); +#endif + + + bsgs_found[k] = 1; + salir = 1; + for(l = 0; l < bsgs_point_number && salir; l++) { + salir &= bsgs_found[l]; + } + if(salir) { + printf("All points were found\n"); + exit(EXIT_FAILURE); + } + } + else { + + startP = secp->AddDirect(OriginalPointsBSGS[k],point_aux); + j = 0; + while( j < cycles && bsgs_found[k]== 0 ) { + + int i; + for(i = 0; i < hLength; i++) { + dx[i].ModSub(&GSn[i].x,&startP.x); + } + dx[i].ModSub(&GSn[i].x,&startP.x); // For the first point + dx[i+1].ModSub(&_2GSn.x,&startP.x); // For the next center point + + // Grouped ModInv + grp->ModInv(); + + /* + We use the fact that P + i*G and P - i*G has the same deltax, so the same inverse + We compute key in the positive and negative way from the center of the group + */ + + // center point + pts[CPU_GRP_SIZE / 2] = startP; + + for(i = 0; iComputePublicKey(&keyfound); + aux_c = secp->GetPublicKeyHex(OriginalPointsBSGScompressed[k],point_found); + printf("[+] Publickey %s\n",aux_c); +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_keys, INFINITE); +#else + pthread_mutex_lock(&write_keys); +#endif + + filekey = fopen("KEYFOUNDKEYFOUND.txt","a"); + if(filekey != NULL) { + fprintf(filekey,"Key found privkey %s\nPublickey %s\n",hextemp,aux_c); + fclose(filekey); + } + free(hextemp); + free(aux_c); +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(write_keys); +#else + pthread_mutex_unlock(&write_keys); +#endif + + bsgs_found[k] = 1; + salir = 1; + for(l = 0; l < bsgs_point_number && salir; l++) { + salir &= bsgs_found[l]; + } + if(salir) { + printf("All points were found\n"); + exit(EXIT_FAILURE); + } + } //End if second check + }//End if first check + + }// For for pts variable + + // Next start point (startP += (bsSize*GRP_SIZE).G) + + pp = startP; + dy.ModSub(&_2GSn.y,&pp.y); + + _s.ModMulK1(&dy,&dx[i + 1]); + _p.ModSquareK1(&_s); + + pp.x.ModNeg(); + pp.x.ModAdd(&_p); + pp.x.ModSub(&_2GSn.x); + + pp.y.ModSub(&_2GSn.x,&pp.x); + pp.y.ModMulK1(&_s); + pp.y.ModSub(&_2GSn.y); + startP = pp; + + j++; + + } //End While + + + + } //End else + + + } //End if + } // End for with k bsgs_point_number + + steps[thread_number]++; +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(bsgs_thread, INFINITE); + base_key.Rand(&n_range_start,&n_range_end); + ReleaseMutex(bsgs_thread); +#else + pthread_mutex_lock(&bsgs_thread); + base_key.Rand(&n_range_start,&n_range_end); + pthread_mutex_unlock(&bsgs_thread); +#endif + } + ends[thread_number] = 1; + return NULL; +} + +/* + The bsgs_secondcheck function is made to perform a second BSGS search in a Range of less size. + This funtion is made with the especific purpouse to USE a smaller bPtable in RAM. +*/ +int bsgs_secondcheck(Int *start_range,uint32_t a,uint32_t k_index,Int *privatekey) { + int i = 0,found = 0,r = 0; + Int base_key; + Point base_point,point_aux; + Point BSGS_Q, BSGS_S,BSGS_Q_AMP; + char xpoint_raw[32]; + + base_key.Set(&BSGS_M); + base_key.Mult((uint64_t) a); + base_key.Add(start_range); + + base_point = secp->ComputePublicKey(&base_key); + point_aux = secp->Negation(base_point); + + + BSGS_S = secp->AddDirect(OriginalPointsBSGS[k_index],point_aux); + BSGS_Q.Set(BSGS_S); + do { + BSGS_S.x.Get32Bytes((unsigned char *) xpoint_raw); + r = bloom_check(&bloom_bPx2nd[(uint8_t) xpoint_raw[0]],xpoint_raw,32); + if(r) { + found = bsgs_thirdcheck(&base_key,i,k_index,privatekey); + } + BSGS_Q_AMP = secp->AddDirect(BSGS_Q,BSGS_AMP2[i]); + BSGS_S.Set(BSGS_Q_AMP); + i++; + }while(i < 32 && !found); + return found; +} + +int bsgs_thirdcheck(Int *start_range,uint32_t a,uint32_t k_index,Int *privatekey) { + uint64_t j = 0; + int i = 0,found = 0,r = 0; + Int base_key; + Point base_point,point_aux; + Point BSGS_Q, BSGS_S,BSGS_Q_AMP; + char xpoint_raw[32]; + + base_key.Set(&BSGS_M2); + base_key.Mult((uint64_t) a); + base_key.Add(start_range); + + base_point = secp->ComputePublicKey(&base_key); + point_aux = secp->Negation(base_point); + + BSGS_S = secp->AddDirect(OriginalPointsBSGS[k_index],point_aux); + BSGS_Q.Set(BSGS_S); + + do { + BSGS_S.x.Get32Bytes((unsigned char *)xpoint_raw); + r = bloom_check(&bloom_bPx3rd[(uint8_t)xpoint_raw[0]],xpoint_raw,32); + if(r) { + r = bsgs_searchbinary(bPtable,xpoint_raw,bsgs_m3,&j); + if(r) { + privatekey->Set(&BSGS_M3); + privatekey->Mult((uint64_t)i); + privatekey->Add((uint64_t)(j+1)); + privatekey->Add(&base_key); + point_aux = secp->ComputePublicKey(privatekey); + if(point_aux.x.IsEqual(&OriginalPointsBSGS[k_index].x)) { + found = 1; + } + else { + privatekey->Set(&BSGS_M3); + privatekey->Mult((uint64_t)i); + privatekey->Sub((uint64_t)(j+1)); + privatekey->Add(&base_key); + point_aux = secp->ComputePublicKey(privatekey); + if(point_aux.x.IsEqual(&OriginalPointsBSGS[k_index].x)) { + found = 1; + } + } + } + } + BSGS_Q_AMP = secp->AddDirect(BSGS_Q,BSGS_AMP3[i]); + BSGS_S.Set(BSGS_Q_AMP); + i++; + }while(i < 32 && !found); + return found; +} + + +void sleep_ms(int milliseconds) { // cross-platform sleep function +#if defined(_WIN64) && !defined(__CYGWIN__) + Sleep(milliseconds); +#elif _POSIX_C_SOURCE >= 199309L + struct timespec ts; + ts.tv_sec = milliseconds / 1000; + ts.tv_nsec = (milliseconds % 1000) * 1000000; + nanosleep(&ts, NULL); +#else + if (milliseconds >= 1000) + sleep(milliseconds / 1000); + usleep((milliseconds % 1000) * 1000); +#endif +} + +#if defined(_WIN64) && !defined(__CYGWIN__) +DWORD WINAPI thread_pub2rmd(LPVOID vargp) { +#else +void *thread_pub2rmd(void *vargp) { +#endif + FILE *fd; + Int key_mpz; + struct tothread *tt; + uint64_t i,limit; + char digest160[20]; + char digest256[32]; + char *temphex; + int thread_number,r; + int pub2rmd_continue = 1; + struct publickey pub; + limit = 0xFFFFFFFF; + tt = (struct tothread *)vargp; + thread_number = tt->nt; + do { + if(FLAGRANDOM){ + key_mpz.Rand(&n_range_start,&n_range_diff); + } + else { + if(n_range_start.IsLower(&n_range_end)) { +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_random, INFINITE); + key_mpz.Set(&n_range_start); + n_range_start.Add(N_SEQUENTIAL_MAX); + ReleaseMutex(write_random); +#else + pthread_mutex_lock(&write_random); + key_mpz.Set(&n_range_start); + n_range_start.Add(N_SEQUENTIAL_MAX); + pthread_mutex_lock(&write_random); +#endif + } + else { + pub2rmd_continue = 0; + } + } + if(pub2rmd_continue) { + key_mpz.Get32Bytes(pub.X.data8); + pub.parity = 0x02; + pub.X.data32[7] = 0; + if(FLAGMATRIX) { + temphex = tohex((char*)&pub,33); + printf("[+] Thread 0x%s \n",temphex); + free(temphex); + fflush(stdout); + } + else { + if(FLAGQUIET == 0) { + temphex = tohex((char*)&pub,33); + printf("\r[+] Thread %s \r",temphex); + free(temphex); + fflush(stdout); + THREADOUTPUT = 1; + } + } + for(i = 0 ; i < limit ; i++) { + pub.parity = 0x02; + sha256((uint8_t*)&pub, 33, (uint8_t*)digest256); + rmd160((const unsigned char*)digest256,32,(unsigned char*) digest160); + r = bloom_check(&bloom,digest160,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(addressTable,digest160,N); + if(r) { + temphex = tohex((char*)&pub,33); + printf("\nHit: Publickey found %s\n",temphex); + fd = fopen("KEYFOUNDKEYFOUND.txt","a+"); + if(fd != NULL) { +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_keys, INFINITE); + fprintf(fd,"Publickey found %s\n",temphex); + fclose(fd); + ReleaseMutex(write_keys); +#else + pthread_mutex_lock(&write_keys); + fprintf(fd,"Publickey found %s\n",temphex); + fclose(fd); + pthread_mutex_unlock(&write_keys); +#endif + } + else { + fprintf(stderr,"\nPublickey found %s\nbut the file can't be open\n",temphex); + exit(EXIT_FAILURE); + } + free(temphex); + } + } + pub.parity = 0x03; + sha256((uint8_t*)&pub, 33,(uint8_t*) digest256); + rmd160((const unsigned char*)digest256,32,(unsigned char*) digest160); + r = bloom_check(&bloom,digest160,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(addressTable,digest160,N); + if(r) { + temphex = tohex((char*)&pub,33); + printf("\nHit: Publickey found %s\n",temphex); + fd = fopen("KEYFOUNDKEYFOUND.txt","a+"); + if(fd != NULL) { +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_keys, INFINITE); + fprintf(fd,"Publickey found %s\n",temphex); + fclose(fd); + ReleaseMutex(write_keys); + +#else + pthread_mutex_lock(&write_keys); + fprintf(fd,"Publickey found %s\n",temphex); + fclose(fd); + pthread_mutex_unlock(&write_keys); +#endif + } + else { + fprintf(stderr,"\nPublickey found %s\nbut the file can't be open\n",temphex); + exit(EXIT_FAILURE); + } + free(temphex); + } + } + pub.X.data32[7]++; + if(pub.X.data32[7] % DEBUGCOUNT == 0) { + steps[thread_number]++; + } + } + } + }while(pub2rmd_continue); + ends[thread_number] = 1; + return NULL; +} + +void init_generator() { + Point G = secp->ComputePublicKey(&stride); + Point g; + Gn.resize(CPU_GRP_SIZE / 2,g); + g.Set(G); + Gn[0] = g; + g = secp->DoubleDirect(g); + Gn[1] = g; + for(int i = 2; i < CPU_GRP_SIZE / 2; i++) { + g = secp->AddDirect(g,G); + Gn[i] = g; + } + _2Gn = secp->DoubleDirect(Gn[CPU_GRP_SIZE / 2 - 1]); +} + +#if defined(_WIN64) && !defined(__CYGWIN__) +DWORD WINAPI thread_bPload(LPVOID vargp) { +#else +void *thread_bPload(void *vargp) { +#endif + + char rawvalue[32]; + struct bPload *tt; + uint64_t i_counter,j,nbStep,to; + + IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1); + Point startP; + Int dx[CPU_GRP_SIZE / 2 + 1]; + Point pts[CPU_GRP_SIZE]; + Int dy,dyn,_s,_p; + Point pp,pn; + + int i,bloom_bP_index,hLength = (CPU_GRP_SIZE / 2 - 1) ,threadid; + tt = (struct bPload *)vargp; + Int km((uint64_t)(tt->from + 1)); + threadid = tt->threadid; + //if(FLAGDEBUG) printf("[D] thread %i from %" PRIu64 " to %" PRIu64 "\n",threadid,tt->from,tt->to); + + i_counter = tt->from; + + nbStep = (tt->to - tt->from) / CPU_GRP_SIZE; + + if( ((tt->to - tt->from) % CPU_GRP_SIZE ) != 0) { + nbStep++; + } + //if(FLAGDEBUG) printf("[D] thread %i nbStep %" PRIu64 "\n",threadid,nbStep); + to = tt->to; + + km.Add((uint64_t)(CPU_GRP_SIZE / 2)); + startP = secp->ComputePublicKey(&km); + grp->Set(dx); + for(uint64_t s=0;sModInv(); + + // We use the fact that P + i*G and P - i*G has the same deltax, so the same inverse + // We compute key in the positive and negative way from the center of the group + // center point + + pts[CPU_GRP_SIZE / 2] = startP; //Center point + + for(i = 0; ifinished = 1; + ReleaseMutex(bPload_mutex[threadid]); +#else + pthread_mutex_lock(&bPload_mutex[threadid]); + tt->finished = 1; + pthread_mutex_unlock(&bPload_mutex[threadid]); + pthread_exit(NULL); +#endif + return NULL; +} + +#if defined(_WIN64) && !defined(__CYGWIN__) +DWORD WINAPI thread_bPload_2blooms(LPVOID vargp) { +#else +void *thread_bPload_2blooms(void *vargp) { +#endif + char rawvalue[32]; + struct bPload *tt; + uint64_t i_counter,j,nbStep; //,to; + IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1); + Point startP; + Int dx[CPU_GRP_SIZE / 2 + 1]; + Point pts[CPU_GRP_SIZE]; + Int dy,dyn,_s,_p; + Point pp,pn; + int i,bloom_bP_index,hLength = (CPU_GRP_SIZE / 2 - 1) ,threadid; + tt = (struct bPload *)vargp; + Int km((uint64_t)(tt->from +1 )); + threadid = tt->threadid; + + i_counter = tt->from; + + nbStep = (tt->to - (tt->from)) / CPU_GRP_SIZE; + + if( ((tt->to - (tt->from)) % CPU_GRP_SIZE ) != 0) { + nbStep++; + } + //to = tt->to; + + km.Add((uint64_t)(CPU_GRP_SIZE / 2)); + startP = secp->ComputePublicKey(&km); + grp->Set(dx); + for(uint64_t s=0;sModInv(); + + // We use the fact that P + i*G and P - i*G has the same deltax, so the same inverse + // We compute key in the positive and negative way from the center of the group + // center point + + pts[CPU_GRP_SIZE / 2] = startP; //Center point + + for(i = 0; ifinished = 1; + ReleaseMutex(bPload_mutex[threadid]); +#else + pthread_mutex_lock(&bPload_mutex[threadid]); + tt->finished = 1; + pthread_mutex_unlock(&bPload_mutex[threadid]); + pthread_exit(NULL); +#endif + return NULL; +} + +/* This function perform the KECCAK Opetation +void KECCAK_256(uint8_t *source, size_t size,uint8_t *dst) { + SHA3_256_CTX ctx; + SHA3_256_Init(&ctx); + SHA3_256_Update(&ctx,source,size); + KECCAK_256_Final(dst,&ctx); +} +*/ + +/* This function takes in two parameters: + +publickey: a reference to a Point object representing a public key. +dst_address: a pointer to an unsigned char array where the generated binary address will be stored. +The function is designed to generate a binary address for Ethereum using the given public key. +It first extracts the x and y coordinates of the public key as 32-byte arrays, and concatenates them +to form a 64-byte array called bin_publickey. Then, it applies the KECCAK-256 hashing algorithm to +bin_publickey to generate the binary address, which is stored in dst_address. */ + +void generate_binaddress_eth(Point &publickey,unsigned char *dst_address) { + unsigned char bin_publickey[64]; + publickey.x.Get32Bytes(bin_publickey); + publickey.y.Get32Bytes(bin_publickey+32); + keccak(bin_publickey, 64, dst_address); +} + + +#if defined(_WIN64) && !defined(__CYGWIN__) +DWORD WINAPI thread_process_bsgs_dance(LPVOID vargp) { +#else +void *thread_process_bsgs_dance(void *vargp) { +#endif + + FILE *filekey; + struct tothread *tt; + char xpoint_raw[32],*aux_c,*hextemp; + Int base_key,keyfound; + Point base_point,point_aux,point_found; + uint32_t j,k,l,r,salir,thread_number,entrar,cycles; + + IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1); + Point startP; + + int hLength = (CPU_GRP_SIZE / 2 - 1); + + Int dx[CPU_GRP_SIZE / 2 + 1]; + Point pts[CPU_GRP_SIZE]; + + Int dy; + Int dyn; + Int _s; + Int _p; + Int km,intaux; + Point pp; + Point pn; + grp->Set(dx); + + + tt = (struct tothread *)vargp; + thread_number = tt->nt; + free(tt); + + cycles = bsgs_aux / 1024; + if(bsgs_aux % 1024 != 0) { + cycles++; + } + + entrar = 1; + +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(bsgs_thread, INFINITE); +#else + pthread_mutex_lock(&bsgs_thread); +#endif + + switch(rand() % 3) { + case 0: //TOP + base_key.Set(&n_range_end); + base_key.Sub(&BSGS_N); + n_range_end.Sub(&BSGS_N); + if(base_key.IsLower(&BSGS_CURRENT)) { + entrar = 0; + } + else { + n_range_end.Sub(&BSGS_N); + } + break; + case 1: //BOTTOM + base_key.Set(&BSGS_CURRENT); + if(base_key.IsGreater(&n_range_end)) { + entrar = 0; + } + else { + BSGS_CURRENT.Add(&BSGS_N); + } + break; + case 2: //random - middle + base_key.Rand(&BSGS_CURRENT,&n_range_end); + break; + } +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(bsgs_thread); +#else + pthread_mutex_unlock(&bsgs_thread); +#endif + + + + intaux.Set(&BSGS_M); + intaux.Mult(CPU_GRP_SIZE/2); + + + + /* + while base_key is less than n_range_end then: + */ + while( entrar ) { + + if(FLAGMATRIX) { + aux_c = base_key.GetBase16(); + printf("[+] Thread 0x%s \n",aux_c); + fflush(stdout); + free(aux_c); + } + else { + if(FLAGQUIET == 0){ + aux_c = base_key.GetBase16(); + printf("\r[+] Thread 0x%s \r",aux_c); + fflush(stdout); + free(aux_c); + THREADOUTPUT = 1; + } + } + + base_point = secp->ComputePublicKey(&base_key); + + km.Set(&base_key); + km.Neg(); + + km.Add(&secp->order); + km.Sub(&intaux); + point_aux = secp->ComputePublicKey(&km); + + for(k = 0; k < bsgs_point_number ; k++) { + if(bsgs_found[k] == 0) { + if(base_point.equals(OriginalPointsBSGS[k])) { + hextemp = base_key.GetBase16(); + printf("[+] Thread Key found privkey %s \n",hextemp); + aux_c = secp->GetPublicKeyHex(OriginalPointsBSGScompressed[k],base_point); + printf("[+] Publickey %s\n",aux_c); +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_keys, INFINITE); +#else + pthread_mutex_lock(&write_keys); +#endif + + filekey = fopen("KEYFOUNDKEYFOUND.txt","a"); + if(filekey != NULL) { + fprintf(filekey,"Key found privkey %s\nPublickey %s\n",hextemp,aux_c); + fclose(filekey); + } + free(hextemp); + free(aux_c); +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(write_keys); +#else + pthread_mutex_unlock(&write_keys); +#endif + + + bsgs_found[k] = 1; + salir = 1; + for(l = 0; l < bsgs_point_number && salir; l++) { + salir &= bsgs_found[l]; + } + if(salir) { + printf("All points were found\n"); + exit(EXIT_FAILURE); + } + } + else { + startP = secp->AddDirect(OriginalPointsBSGS[k],point_aux); + j = 0; + while( j < cycles && bsgs_found[k]== 0 ) { + + int i; + + for(i = 0; i < hLength; i++) { + dx[i].ModSub(&GSn[i].x,&startP.x); + } + dx[i].ModSub(&GSn[i].x,&startP.x); // For the first point + dx[i+1].ModSub(&_2GSn.x,&startP.x); // For the next center point + + // Grouped ModInv + grp->ModInv(); + + /* + We use the fact that P + i*G and P - i*G has the same deltax, so the same inverse + We compute key in the positive and negative way from the center of the group + */ + + // center point + pts[CPU_GRP_SIZE / 2] = startP; + + for(i = 0; iComputePublicKey(&keyfound); + aux_c = secp->GetPublicKeyHex(OriginalPointsBSGScompressed[k],point_found); + printf("[+] Publickey %s\n",aux_c); +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_keys, INFINITE); +#else + pthread_mutex_lock(&write_keys); +#endif + + filekey = fopen("KEYFOUNDKEYFOUND.txt","a"); + if(filekey != NULL) { + fprintf(filekey,"Key found privkey %s\nPublickey %s\n",hextemp,aux_c); + fclose(filekey); + } + free(hextemp); + free(aux_c); +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(write_keys); +#else + pthread_mutex_unlock(&write_keys); +#endif + + bsgs_found[k] = 1; + salir = 1; + for(l = 0; l < bsgs_point_number && salir; l++) { + salir &= bsgs_found[l]; + } + if(salir) { + printf("All points were found\n"); + exit(EXIT_FAILURE); + } + } //End if second check + }//End if first check + + }// For for pts variable + + // Next start point (startP += (bsSize*GRP_SIZE).G) + + pp = startP; + dy.ModSub(&_2GSn.y,&pp.y); + + _s.ModMulK1(&dy,&dx[i + 1]); + _p.ModSquareK1(&_s); + + pp.x.ModNeg(); + pp.x.ModAdd(&_p); + pp.x.ModSub(&_2GSn.x); + + pp.y.ModSub(&_2GSn.x,&pp.x); + pp.y.ModMulK1(&_s); + pp.y.ModSub(&_2GSn.y); + startP = pp; + + j++; + }//while all the aMP points + }// end else + }// End if + } + + steps[thread_number]++; + +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(bsgs_thread, INFINITE); +#else + pthread_mutex_lock(&bsgs_thread); +#endif + + switch(rand() % 3) { + case 0: //TOP + base_key.Set(&n_range_end); + base_key.Sub(&BSGS_N); + n_range_end.Sub(&BSGS_N); + if(base_key.IsLower(&BSGS_CURRENT)) { + entrar = 0; + } + else { + n_range_end.Sub(&BSGS_N); + } + break; + case 1: //BOTTOM + base_key.Set(&BSGS_CURRENT); + if(base_key.IsGreater(&n_range_end)) { + entrar = 0; + } + else { + BSGS_CURRENT.Add(&BSGS_N); + } + break; + case 2: //random - middle + base_key.Rand(&BSGS_CURRENT,&n_range_end); + break; + } +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(bsgs_thread); +#else + pthread_mutex_unlock(&bsgs_thread); +#endif + } + ends[thread_number] = 1; + return NULL; +} + +#if defined(_WIN64) && !defined(__CYGWIN__) +DWORD WINAPI thread_process_bsgs_backward(LPVOID vargp) { +#else +void *thread_process_bsgs_backward(void *vargp) { +#endif + FILE *filekey; + struct tothread *tt; + char xpoint_raw[32],*aux_c,*hextemp; + Int base_key,keyfound; + Point base_point,point_aux,point_found; + uint32_t j,k,l,r,salir,thread_number,entrar,cycles; + + IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1); + Point startP; + + int i,hLength = (CPU_GRP_SIZE / 2 - 1); + + Int dx[CPU_GRP_SIZE / 2 + 1]; + Point pts[CPU_GRP_SIZE]; + + Int dy; + Int dyn; + Int _s; + Int _p; + Int km,intaux; + Point pp; + Point pn; + grp->Set(dx); + + + tt = (struct tothread *)vargp; + thread_number = tt->nt; + free(tt); + + cycles = bsgs_aux / 1024; + if(bsgs_aux % 1024 != 0) { + cycles++; + } + +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(bsgs_thread, INFINITE); + n_range_end.Sub(&BSGS_N); + base_key.Set(&n_range_end); + ReleaseMutex(bsgs_thread); +#else + pthread_mutex_lock(&bsgs_thread); + n_range_end.Sub(&BSGS_N); + base_key.Set(&n_range_end); + pthread_mutex_unlock(&bsgs_thread); +#endif + + intaux.Set(&BSGS_M); + intaux.Mult(CPU_GRP_SIZE/2); + + entrar = 1; + + /* + while base_key is less than n_range_end then: + */ + while( entrar ) { + + if(FLAGMATRIX) { + aux_c = base_key.GetBase16(); + printf("[+] Thread 0x%s \n",aux_c); + fflush(stdout); + free(aux_c); + } + else { + if(FLAGQUIET == 0){ + aux_c = base_key.GetBase16(); + printf("\r[+] Thread 0x%s \r",aux_c); + fflush(stdout); + free(aux_c); + THREADOUTPUT = 1; + } + } + + base_point = secp->ComputePublicKey(&base_key); + + km.Set(&base_key); + km.Neg(); + + km.Add(&secp->order); + km.Sub(&intaux); + point_aux = secp->ComputePublicKey(&km); + + for(k = 0; k < bsgs_point_number ; k++) { + if(bsgs_found[k] == 0) { + if(base_point.equals(OriginalPointsBSGS[k])) { + hextemp = base_key.GetBase16(); + printf("[+] Thread Key found privkey %s \n",hextemp); + aux_c = secp->GetPublicKeyHex(OriginalPointsBSGScompressed[k],base_point); + printf("[+] Publickey %s\n",aux_c); + +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_keys, INFINITE); +#else + pthread_mutex_lock(&write_keys); +#endif + + filekey = fopen("KEYFOUNDKEYFOUND.txt","a"); + if(filekey != NULL) { + fprintf(filekey,"Key found privkey %s\nPublickey %s\n",hextemp,aux_c); + fclose(filekey); + } + free(hextemp); + free(aux_c); +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(write_keys); +#else + pthread_mutex_unlock(&write_keys); +#endif + bsgs_found[k] = 1; + salir = 1; + for(l = 0; l < bsgs_point_number && salir; l++) { + salir &= bsgs_found[l]; + } + if(salir) { + printf("All points were found\n"); + exit(EXIT_FAILURE); + } + } + else { + startP = secp->AddDirect(OriginalPointsBSGS[k],point_aux); + j = 0; + while( j < cycles && bsgs_found[k]== 0 ) { + for(i = 0; i < hLength; i++) { + dx[i].ModSub(&GSn[i].x,&startP.x); + } + dx[i].ModSub(&GSn[i].x,&startP.x); // For the first point + dx[i+1].ModSub(&_2GSn.x,&startP.x); // For the next center point + + // Grouped ModInv + grp->ModInv(); + + /* + We use the fact that P + i*G and P - i*G has the same deltax, so the same inverse + We compute key in the positive and negative way from the center of the group + */ + + // center point + pts[CPU_GRP_SIZE / 2] = startP; + + for(i = 0; iComputePublicKey(&keyfound); + aux_c = secp->GetPublicKeyHex(OriginalPointsBSGScompressed[k],point_found); + printf("[+] Publickey %s\n",aux_c); +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_keys, INFINITE); +#else + pthread_mutex_lock(&write_keys); +#endif + + filekey = fopen("KEYFOUNDKEYFOUND.txt","a"); + if(filekey != NULL) { + fprintf(filekey,"Key found privkey %s\nPublickey %s\n",hextemp,aux_c); + fclose(filekey); + } + free(hextemp); + free(aux_c); +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(write_keys); +#else + pthread_mutex_unlock(&write_keys); +#endif + + bsgs_found[k] = 1; + salir = 1; + for(l = 0; l < bsgs_point_number && salir; l++) { + salir &= bsgs_found[l]; + } + if(salir) { + printf("All points were found\n"); + exit(EXIT_FAILURE); + } + } //End if second check + }//End if first check + + }// For for pts variable + + // Next start point (startP += (bsSize*GRP_SIZE).G) + + pp = startP; + dy.ModSub(&_2GSn.y,&pp.y); + + _s.ModMulK1(&dy,&dx[i + 1]); + _p.ModSquareK1(&_s); + + pp.x.ModNeg(); + pp.x.ModAdd(&_p); + pp.x.ModSub(&_2GSn.x); + + pp.y.ModSub(&_2GSn.x,&pp.x); + pp.y.ModMulK1(&_s); + pp.y.ModSub(&_2GSn.y); + startP = pp; + + j++; + }//while all the aMP points + }// end else + }// End if + } + + steps[thread_number]++; + +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(bsgs_thread, INFINITE); +#else + pthread_mutex_lock(&bsgs_thread); +#endif + + n_range_end.Sub(&BSGS_N); + if(n_range_end.IsLower(&n_range_start)) { + entrar = 0; + } + else { + base_key.Set(&n_range_end); + } +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(bsgs_thread); +#else + pthread_mutex_unlock(&bsgs_thread); +#endif + + } + ends[thread_number] = 1; + return NULL; +} + + +#if defined(_WIN64) && !defined(__CYGWIN__) +DWORD WINAPI thread_process_bsgs_both(LPVOID vargp) { +#else +void *thread_process_bsgs_both(void *vargp) { +#endif + FILE *filekey; + struct tothread *tt; + char xpoint_raw[32],*aux_c,*hextemp; + Int base_key,keyfound; + Point base_point,point_aux,point_found; + uint32_t j,k,l,r,salir,thread_number,entrar,cycles; + + IntGroup *grp = new IntGroup(CPU_GRP_SIZE / 2 + 1); + Point startP; + + int i,hLength = (CPU_GRP_SIZE / 2 - 1); + + Int dx[CPU_GRP_SIZE / 2 + 1]; + Point pts[CPU_GRP_SIZE]; + + Int dy; + Int dyn; + Int _s; + Int _p; + Int km,intaux; + Point pp; + Point pn; + grp->Set(dx); + + + tt = (struct tothread *)vargp; + thread_number = tt->nt; + free(tt); + + cycles = bsgs_aux / 1024; + if(bsgs_aux % 1024 != 0) { + cycles++; + } + + entrar = 1; + +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(bsgs_thread, INFINITE); +#else + pthread_mutex_lock(&bsgs_thread); +#endif + + r = rand() % 2; + //if(FLAGDEBUG) printf("[D] was %s\n",r ? "Bottom":"TOP"); + switch(r) { + case 0: //TOP + base_key.Set(&n_range_end); + base_key.Sub(&BSGS_N); + if(base_key.IsLowerOrEqual(&BSGS_CURRENT)) { + entrar = 0; + } + else { + n_range_end.Sub(&BSGS_N); + } + break; + case 1: //BOTTOM + base_key.Set(&BSGS_CURRENT); + if(base_key.IsGreaterOrEqual(&n_range_end)) { + entrar = 0; + } + else { + BSGS_CURRENT.Add(&BSGS_N); + } + break; + } +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(bsgs_thread); +#else + pthread_mutex_unlock(&bsgs_thread); +#endif + + + intaux.Set(&BSGS_M); + intaux.Mult(CPU_GRP_SIZE/2); + + + /* + while BSGS_CURRENT is less than n_range_end + */ + while( entrar ) { + + if(FLAGMATRIX) { + aux_c = base_key.GetBase16(); + printf("[+] Thread 0x%s \n",aux_c); + fflush(stdout); + free(aux_c); + } + else { + if(FLAGQUIET == 0){ + aux_c = base_key.GetBase16(); + printf("\r[+] Thread 0x%s \r",aux_c); + fflush(stdout); + free(aux_c); + THREADOUTPUT = 1; + } + } + + base_point = secp->ComputePublicKey(&base_key); + + km.Set(&base_key); + km.Neg(); + + km.Add(&secp->order); + km.Sub(&intaux); + point_aux = secp->ComputePublicKey(&km); + + for(k = 0; k < bsgs_point_number ; k++) { + if(bsgs_found[k] == 0) { + if(base_point.equals(OriginalPointsBSGS[k])) { + hextemp = base_key.GetBase16(); + printf("[+] Thread Key found privkey %s \n",hextemp); + aux_c = secp->GetPublicKeyHex(OriginalPointsBSGScompressed[k],base_point); + printf("[+] Publickey %s\n",aux_c); +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_keys, INFINITE); +#else + pthread_mutex_lock(&write_keys); +#endif + filekey = fopen("KEYFOUNDKEYFOUND.txt","a"); + if(filekey != NULL) { + fprintf(filekey,"Key found privkey %s\nPublickey %s\n",hextemp,aux_c); + fclose(filekey); + } + free(hextemp); + free(aux_c); +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(write_keys); +#else + pthread_mutex_unlock(&write_keys); +#endif + + bsgs_found[k] = 1; + salir = 1; + for(l = 0; l < bsgs_point_number && salir; l++) { + salir &= bsgs_found[l]; + } + if(salir) { + printf("All points were found\n"); + exit(EXIT_FAILURE); + } + } + else { + startP = secp->AddDirect(OriginalPointsBSGS[k],point_aux); + j = 0; + while( j < cycles && bsgs_found[k]== 0 ) { + + for(i = 0; i < hLength; i++) { + dx[i].ModSub(&GSn[i].x,&startP.x); + } + dx[i].ModSub(&GSn[i].x,&startP.x); // For the first point + dx[i+1].ModSub(&_2GSn.x,&startP.x); // For the next center point + + // Grouped ModInv + grp->ModInv(); + + /* + We use the fact that P + i*G and P - i*G has the same deltax, so the same inverse + We compute key in the positive and negative way from the center of the group + */ + + // center point + pts[CPU_GRP_SIZE / 2] = startP; + + for(i = 0; iComputePublicKey(&keyfound); + aux_c = secp->GetPublicKeyHex(OriginalPointsBSGScompressed[k],point_found); + printf("[+] Publickey %s\n",aux_c); +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_keys, INFINITE); +#else + pthread_mutex_lock(&write_keys); +#endif + + filekey = fopen("KEYFOUNDKEYFOUND.txt","a"); + if(filekey != NULL) { + fprintf(filekey,"Key found privkey %s\nPublickey %s\n",hextemp,aux_c); + fclose(filekey); + } + +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(write_keys); +#else + pthread_mutex_unlock(&write_keys); +#endif + + free(hextemp); + free(aux_c); + bsgs_found[k] = 1; + salir = 1; + for(l = 0; l < bsgs_point_number && salir; l++) { + salir &= bsgs_found[l]; + } + if(salir) { + printf("All points were found\n"); + exit(EXIT_FAILURE); + } + } //End if second check + }//End if first check + + }// For for pts variable + + // Next start point (startP += (bsSize*GRP_SIZE).G) + + pp = startP; + dy.ModSub(&_2GSn.y,&pp.y); + + _s.ModMulK1(&dy,&dx[i + 1]); + _p.ModSquareK1(&_s); + + pp.x.ModNeg(); + pp.x.ModAdd(&_p); + pp.x.ModSub(&_2GSn.x); + + pp.y.ModSub(&_2GSn.x,&pp.x); + pp.y.ModMulK1(&_s); + pp.y.ModSub(&_2GSn.y); + startP = pp; + + j++; + }//while all the aMP points + }// end else + }// End if + } + + steps[thread_number]++; + +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(bsgs_thread, INFINITE); +#else + pthread_mutex_lock(&bsgs_thread); +#endif + + switch(rand() % 2) { + case 0: //TOP + base_key.Set(&n_range_end); + base_key.Sub(&BSGS_N); + if(base_key.IsLowerOrEqual(&BSGS_CURRENT)) { + entrar = 0; + } + else { + n_range_end.Sub(&BSGS_N); + } + break; + case 1: //BOTTOM + base_key.Set(&BSGS_CURRENT); + if(base_key.IsGreaterOrEqual(&n_range_end)) { + entrar = 0; + } + else { + BSGS_CURRENT.Add(&BSGS_N); + } + break; + } +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(bsgs_thread); +#else + pthread_mutex_unlock(&bsgs_thread); +#endif + } + ends[thread_number] = 1; + return NULL; +} + +/* This function takes in three parameters: + +buffer: a pointer to a char array where the minikey will be stored. +rawbuffer: a pointer to a char array that contains the raw data. +length: an integer representing the length of the raw data. +The function is designed to convert the raw data using a lookup table (Ccoinbuffer) and store the result in the buffer. +*/ +void set_minikey(char *buffer,char *rawbuffer,int length) { + for(int i = 0; i < length; i++) { + buffer[i] = Ccoinbuffer[(uint8_t)rawbuffer[i]]; + } +} + +/* This function takes in three parameters: + +buffer: a pointer to a char array where the minikey will be stored. +rawbuffer: a pointer to a char array that contains the raw data. +index: an integer representing the index of the raw data array to be incremented. +The function is designed to increment the value at the specified index in the raw data array, +and update the corresponding value in the buffer using a lookup table (Ccoinbuffer). +If the value at the specified index exceeds 57, it is reset to 0x00 and the function recursively +calls itself to increment the value at the previous index, unless the index is already 0, in which +case the function returns false. The function returns true otherwise. +*/ + +bool increment_minikey_index(char *buffer,char *rawbuffer,int index) { + if(rawbuffer[index] < 57){ + rawbuffer[index]++; + buffer[index] = Ccoinbuffer[(uint8_t)rawbuffer[index]]; + } + else { + rawbuffer[index] = 0x00; + buffer[index] = Ccoinbuffer[0]; + if(index>0) { + return increment_minikey_index(buffer,rawbuffer,index-1); + } + else { + return false; + } + } + return true; +} + +/* This function takes in a single parameter: + +rawbuffer: a pointer to a char array that contains the raw data. +The function is designed to increment the values in the raw data array +using a lookup table (minikeyN), while also handling carry-over to the +previous element in the array if necessary. The maximum number of iterations +is limited by minikey_n_limit. + + +*/ +void increment_minikey_N(char *rawbuffer) { + int i = 20,j = 0; + while( i > 0 && j < minikey_n_limit) { + rawbuffer[i] = rawbuffer[i] + minikeyN[i]; + if(rawbuffer[i] > 57) { // Handling carry-over if value exceeds 57 + rawbuffer[i] = rawbuffer[i] % 58; + rawbuffer[i-1]++; + } + i--; + j++; + } +} + +/* +#define BUFFMINIKEY(buff,src) \ +(buff)[ 0] = (uint32_t)src[ 0] << 24 | (uint32_t)src[ 1] << 16 | (uint32_t)src[ 2] << 8 | (uint32_t)src[ 3]; \ +(buff)[ 1] = (uint32_t)src[ 4] << 24 | (uint32_t)src[ 5] << 16 | (uint32_t)src[ 6] << 8 | (uint32_t)src[ 7]; \ +(buff)[ 2] = (uint32_t)src[ 8] << 24 | (uint32_t)src[ 9] << 16 | (uint32_t)src[10] << 8 | (uint32_t)src[11]; \ +(buff)[ 3] = (uint32_t)src[12] << 24 | (uint32_t)src[13] << 16 | (uint32_t)src[14] << 8 | (uint32_t)src[15]; \ +(buff)[ 4] = (uint32_t)src[16] << 24 | (uint32_t)src[17] << 16 | (uint32_t)src[18] << 8 | (uint32_t)src[19]; \ +(buff)[ 5] = (uint32_t)src[20] << 24 | (uint32_t)src[21] << 16 | 0x8000; \ +(buff)[ 6] = 0; \ +(buff)[ 7] = 0; \ +(buff)[ 8] = 0; \ +(buff)[ 9] = 0; \ +(buff)[10] = 0; \ +(buff)[11] = 0; \ +(buff)[12] = 0; \ +(buff)[13] = 0; \ +(buff)[14] = 0; \ +(buff)[15] = 0xB0; //176 bits => 22 BYTES +*/ + +void sha256sse_22(uint8_t *src0, uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *dst0, uint8_t *dst1, uint8_t *dst2, uint8_t *dst3) { + sha256(src0,22,dst0); + sha256(src1,22,dst1); + sha256(src2,22,dst2); + sha256(src3,22,dst3); +} + +/* +#define BUFFMINIKEYCHECK(buff,src) \ +(buff)[ 0] = (uint32_t)src[ 0] << 24 | (uint32_t)src[ 1] << 16 | (uint32_t)src[ 2] << 8 | (uint32_t)src[ 3]; \ +(buff)[ 1] = (uint32_t)src[ 4] << 24 | (uint32_t)src[ 5] << 16 | (uint32_t)src[ 6] << 8 | (uint32_t)src[ 7]; \ +(buff)[ 2] = (uint32_t)src[ 8] << 24 | (uint32_t)src[ 9] << 16 | (uint32_t)src[10] << 8 | (uint32_t)src[11]; \ +(buff)[ 3] = (uint32_t)src[12] << 24 | (uint32_t)src[13] << 16 | (uint32_t)src[14] << 8 | (uint32_t)src[15]; \ +(buff)[ 4] = (uint32_t)src[16] << 24 | (uint32_t)src[17] << 16 | (uint32_t)src[18] << 8 | (uint32_t)src[19]; \ +(buff)[ 5] = (uint32_t)src[20] << 24 | (uint32_t)src[21] << 16 | (uint32_t)src[22] << 8 | 0x80; \ +(buff)[ 6] = 0; \ +(buff)[ 7] = 0; \ +(buff)[ 8] = 0; \ +(buff)[ 9] = 0; \ +(buff)[10] = 0; \ +(buff)[11] = 0; \ +(buff)[12] = 0; \ +(buff)[13] = 0; \ +(buff)[14] = 0; \ +(buff)[15] = 0xB8; */ //184 bits => 23 BYTES + + + + +void sha256sse_23(uint8_t *src0, uint8_t *src1, uint8_t *src2, uint8_t *src3, uint8_t *dst0, uint8_t *dst1, uint8_t *dst2, uint8_t *dst3) { + sha256(src0,23,dst0); + sha256(src1,23,dst1); + sha256(src2,23,dst2); + sha256(src3,23,dst3); +} + +void menu() { + printf("\nUsage:\n"); + printf("-h show this help\n"); + printf("-B Mode BSGS now have some modes \n"); + printf("-b bits For some puzzles you only need some numbers of bits in the test keys.\n"); + printf("-c crypto Search for specific crypto. valid only w/ -m address\n"); + printf("-C mini Set the minikey Base only 22 character minikeys, ex: SRPqx8QiwnW4WNWnTVa2W5\n"); + printf("-8 alpha Set the bas58 alphabet for minikeys\n"); + printf("-e Enable endomorphism search (Only for address, rmd160 and vanity)\n"); + printf("-f file Specify file name with addresses or xpoints or uncompressed public keys\n"); + printf("-I stride Stride for xpoint, rmd160 and address, this option don't work with bsgs\n"); + printf("-k value Use this only with bsgs mode, k value is factor for M, more speed but more RAM use wisely\n"); + printf("-l look What type of address/hash160 are you looking for Only for rmd160 and address\n"); + printf("-m mode mode of search for cryptos. (bsgs, xpoint, rmd160, address, vanity) default: address\n"); + printf("-M Matrix screen, feel like a h4x0r, but performance will dropped\n"); + printf("-n number Check for N sequential numbers before the random chosen, this only works with -R option\n"); + printf(" Use -n to set the N for the BSGS process. Bigger N more RAM needed\n"); + printf("-q Quiet the thread output\n"); + printf("-r SR:EN StarRange:EndRange, the end range can be omitted for search from start range to N-1 ECC value\n"); + printf("-R Random, this is the default behavior\n"); + printf("-s ns Number of seconds for the stats output, 0 to omit output.\n"); + printf("-S S is for SAVING in files BSGS data (Bloom filters and bPtable)\n"); + printf("-t tn Threads number, must be a positive integer\n"); + printf("-v value Search for vanity Address, only with -m address and rmd160\n"); + printf("-z value Bloom size multiplier, only address,rmd160,vanity, xpoint, value >= 1\n"); + printf("\nExample:\n\n"); + printf("./keyhunt -m rmd160 -f tests/unsolvedpuzzles.rmd -b 66 -l compress -R -q -t 8\n\n"); + printf("This line runs the program with 8 threads from the range 20000000000000000 to 40000000000000000 without stats output\n\n"); + printf("Developed by AlbertoBSD\tTips BTC: 1Coffee1jV4gB5gaXfHgSHDz9xx9QSECVW\n"); + printf("Thanks to Iceland always helping and sharing his ideas.\nTips to Iceland: bc1q39meky2mn5qjq704zz0nnkl0v7kj4uz6r529at\n\n"); + exit(EXIT_FAILURE); +} + +bool vanityrmdmatch(unsigned char *rmdhash) { + bool r = false; + int i,j,cmpA,cmpB,result; + result = bloom_check(vanity_bloom,rmdhash,vanity_rmd_minimun_bytes_check_length); + switch(result) { + case -1: + fprintf(stderr,"[E] Bloom is not initialized\n"); + exit(EXIT_FAILURE); + break; + case 1: + for(i = 0; i < vanity_rmd_targets && !r;i++) { + for(j = 0; j < vanity_rmd_limits[i] && !r; j++) { + cmpA = memcmp(vanity_rmd_limit_values_A[i][j],rmdhash,20); + cmpB = memcmp(vanity_rmd_limit_values_B[i][j],rmdhash,20); + if(cmpA <= 0 && cmpB >= 0) { + //if(FLAGDEBUG ) printf("\n\n[D] cmpA = %i, cmpB = %i \n\n",cmpA,cmpB); + r = true; + } + } + } + break; + default: + r = false; + break; + } + return r; +} + +void writevanitykey(bool compressed,Int *key) { + Point publickey; + FILE *keys; + char *hextemp,*hexrmd,public_key_hex[131],address[50],rmdhash[20]; + hextemp = key->GetBase16(); + publickey = secp->ComputePublicKey(key); + secp->GetPublicKeyHex(compressed,publickey,public_key_hex); + + secp->GetHash160(P2PKH,compressed,publickey,(uint8_t*)rmdhash); + hexrmd = tohex(rmdhash,20); + rmd160toaddress_dst(rmdhash,address); + +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_keys, INFINITE); +#else + pthread_mutex_lock(&write_keys); +#endif + keys = fopen("VANITYKEYFOUND.txt","a+"); + if(keys != NULL) { + fprintf(keys,"Vanity Private Key: %s\npubkey: %s\nAddress %s\nrmd160 %s\n",hextemp,public_key_hex,address,hexrmd); + fclose(keys); + } + printf("\nVanity Private Key: %s\npubkey: %s\nAddress %s\nrmd160 %s\n",hextemp,public_key_hex,address,hexrmd); + +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(write_keys); +#else + pthread_mutex_unlock(&write_keys); +#endif + free(hextemp); + free(hexrmd); +} + + +int addvanity(char *target) { + unsigned char raw_value_A[50],raw_value_B[50]; + char target_copy[50]; + int stringsize,targetsize,j,r = 0; + size_t raw_value_length; + int values_A_size = 0,values_B_size = 0,minimun_bytes; + + //if(FLAGDEBUG) printf("[D] addvanity(%s)\n",target); + raw_value_length = 50; + targetsize = strlen(target); + stringsize = targetsize; + + memset(raw_value_A,0,50); + memset(target_copy,0,50); + + if(targetsize >= 30 ) { + return 0; + } + + memcpy(target_copy,target,targetsize); + + j = 0; + vanity_address_targets = (char**) realloc(vanity_address_targets,(vanity_rmd_targets+1) * sizeof(char*)); + vanity_address_targets[vanity_rmd_targets] = NULL; + checkpointer((void *)vanity_address_targets,__FILE__,"realloc","vanity_address_targets" ,__LINE__ -1 ); + vanity_rmd_limits = (int*) realloc(vanity_rmd_limits,(vanity_rmd_targets+1) * sizeof(int)); + vanity_rmd_limits[vanity_rmd_targets] = 0; + checkpointer((void *)vanity_rmd_limits,__FILE__,"realloc","vanity_rmd_limits" ,__LINE__ -1 ); + vanity_rmd_limit_values_A = (uint8_t***)realloc(vanity_rmd_limit_values_A,(vanity_rmd_targets+1) * sizeof(unsigned char *)); + checkpointer((void *)vanity_rmd_limit_values_A,__FILE__,"realloc","vanity_rmd_limit_values_A" ,__LINE__ -1 ); + vanity_rmd_limit_values_A[vanity_rmd_targets] = NULL; + vanity_rmd_limit_values_B = (uint8_t***)realloc(vanity_rmd_limit_values_B,(vanity_rmd_targets+1) * sizeof(unsigned char *)); + checkpointer((void *)vanity_rmd_limit_values_B,__FILE__,"realloc","vanity_rmd_limit_values_B" ,__LINE__ -1 ); + vanity_rmd_limit_values_B[vanity_rmd_targets] = NULL; + do { + raw_value_length = 50; + b58tobin(raw_value_A,&raw_value_length,target_copy,stringsize); + if(raw_value_length < 25) { + target_copy[stringsize] = '1'; + stringsize++; + } + if(raw_value_length == 25) { + b58tobin(raw_value_A,&raw_value_length,target_copy,stringsize); + + vanity_rmd_limit_values_A[vanity_rmd_targets] = (uint8_t**)realloc(vanity_rmd_limit_values_A[vanity_rmd_targets],(j+1) * sizeof(unsigned char *)); + checkpointer((void *)vanity_rmd_limit_values_A[vanity_rmd_targets],__FILE__,"realloc","vanity_rmd_limit_values_A" ,__LINE__ -1 ); + vanity_rmd_limit_values_A[vanity_rmd_targets][j] = (uint8_t*)calloc(20,1); + checkpointer((void *)vanity_rmd_limit_values_A[vanity_rmd_targets][j],__FILE__,"realloc","vanity_rmd_limit_values_A" ,__LINE__ -1 ); + + memcpy(vanity_rmd_limit_values_A[vanity_rmd_targets][j] ,raw_value_A +1,20); + + j++; + values_A_size = j; + target_copy[stringsize] = '1'; + stringsize++; + } + }while(raw_value_length <= 25); + + stringsize = targetsize; + memset(raw_value_B,0,50); + memset(target_copy,0,50); + memcpy(target_copy,target,targetsize); + + j = 0; + do { + raw_value_length = 50; + b58tobin(raw_value_B,&raw_value_length,target_copy,stringsize); + if(raw_value_length < 25) { + target_copy[stringsize] = 'z'; + stringsize++; + } + if(raw_value_length == 25) { + + b58tobin(raw_value_B,&raw_value_length,target_copy,stringsize); + vanity_rmd_limit_values_B[vanity_rmd_targets] = (uint8_t**)realloc(vanity_rmd_limit_values_B[vanity_rmd_targets],(j+1) * sizeof(unsigned char *)); + checkpointer((void *)vanity_rmd_limit_values_B[vanity_rmd_targets],__FILE__,"realloc","vanity_rmd_limit_values_B" ,__LINE__ -1 ); + checkpointer((void *)vanity_rmd_limit_values_B[vanity_rmd_targets],__FILE__,"realloc","vanity_rmd_limit_values_B" ,__LINE__ -1 ); + vanity_rmd_limit_values_B[vanity_rmd_targets][j] = (uint8_t*)calloc(20,1); + checkpointer((void *)vanity_rmd_limit_values_B[vanity_rmd_targets][j],__FILE__,"calloc","vanity_rmd_limit_values_B" ,__LINE__ -1 ); + memcpy(vanity_rmd_limit_values_B[vanity_rmd_targets][j],raw_value_B+1,20); + + j++; + values_B_size = j; + + target_copy[stringsize] = 'z'; + stringsize++; + } + }while(raw_value_length <= 25); + + if(values_A_size >= 1 && values_B_size >= 1) { + if(values_A_size != values_B_size) { + if(values_A_size > values_B_size) + r = values_B_size; + else + r = values_A_size; + } + else { + r = values_A_size; + } + for(j = 0; j < r; j++) { + minimun_bytes = minimum_same_bytes(vanity_rmd_limit_values_A[vanity_rmd_targets][j],vanity_rmd_limit_values_B[vanity_rmd_targets][j],20); + if(minimun_bytes < vanity_rmd_minimun_bytes_check_length) { + vanity_rmd_minimun_bytes_check_length = minimun_bytes; + } + } + vanity_address_targets[vanity_rmd_targets] = (char*) calloc(targetsize+1,sizeof(char)); + checkpointer((void *)vanity_address_targets[vanity_rmd_targets],__FILE__,"calloc","vanity_address_targets" ,__LINE__ -1 ); + memcpy(vanity_address_targets[vanity_rmd_targets],target,targetsize+1); // +1 to copy the null character + vanity_rmd_limits[vanity_rmd_targets] = r; + vanity_rmd_total+=r; + vanity_rmd_targets++; + } + else { + for(j = 0; j < values_A_size;j++) { + free(vanity_rmd_limit_values_A[vanity_rmd_targets][j]); + } + free(vanity_rmd_limit_values_A[vanity_rmd_targets]); + vanity_rmd_limit_values_A[vanity_rmd_targets] = NULL; + + for(j = 0; j < values_B_size;j++) { + free(vanity_rmd_limit_values_B[vanity_rmd_targets][j]); + } + free(vanity_rmd_limit_values_B[vanity_rmd_targets]); + vanity_rmd_limit_values_B[vanity_rmd_targets] = NULL; + r = 0; + } + return r; +} + + +/* +A and B are binary o string data pointers +length the max lenght to check. + +Caller must by sure that the pointer are valid and have at least length bytes readebles witout causing overflow +*/ +int minimum_same_bytes(unsigned char* A,unsigned char* B, int length) { + int minBytes = 0; // Assume initially that all bytes are the same + if(A == NULL || B == NULL) { // In case of some NULL pointer + return 0; + } + for (int i = 0; i < length; i++) { + if (A[i] != B[i]) { + break; // Exit the loop since we found a mismatch + } + minBytes++; // Update the minimum number of bytes where data is the same + } + + return minBytes; +} + +void checkpointer(void *ptr,const char *file,const char *function,const char *name,int line) { + if(ptr == NULL) { + fprintf(stderr,"[E] error in file %s, %s pointer %s on line %i\n",file,function,name,line); + exit(EXIT_FAILURE); + } +} + +void writekey(bool compressed,Int *key) { + Point publickey; + FILE *keys; + char *hextemp,*hexrmd,public_key_hex[132],address[50],rmdhash[20]; + memset(address,0,50); + memset(public_key_hex,0,132); + hextemp = key->GetBase16(); + publickey = secp->ComputePublicKey(key); + secp->GetPublicKeyHex(compressed,publickey,public_key_hex); + secp->GetHash160(P2PKH,compressed,publickey,(uint8_t*)rmdhash); + hexrmd = tohex(rmdhash,20); + rmd160toaddress_dst(rmdhash,address); + +#if defined(_WIN64) && !defined(__CYGWIN__) + WaitForSingleObject(write_keys, INFINITE); +#else + pthread_mutex_lock(&write_keys); +#endif + keys = fopen("KEYFOUNDKEYFOUND.txt","a+"); + if(keys != NULL) { + fprintf(keys,"Private Key: %s\npubkey: %s\nAddress %s\nrmd160 %s\n",hextemp,public_key_hex,address,hexrmd); + fclose(keys); + } + printf("\nHit! Private Key: %s\npubkey: %s\nAddress %s\nrmd160 %s\n",hextemp,public_key_hex,address,hexrmd); + +#if defined(_WIN64) && !defined(__CYGWIN__) + ReleaseMutex(write_keys); +#else + pthread_mutex_unlock(&write_keys); +#endif + free(hextemp); + free(hexrmd); +} + +bool isBase58(char c) { + // Define the base58 set + const char base58Set[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + // Check if the character is in the base58 set + return strchr(base58Set, c) != NULL; +} + +bool isValidBase58String(char *str) { + int len = strlen(str); + bool continuar = true; + for (int i = 0; i < len && continuar; i++) { + continuar = isBase58(str[i]); + } + return continuar; +} + +bool processOneVanity() { + int i,k; + if(vanity_rmd_targets == 0) { + fprintf(stderr,"[E] There aren't any vanity targets\n"); + return false; + } + if(!initBloomFilter(vanity_bloom, vanity_rmd_total)) + return false; + + for(i = 0;i < vanity_rmd_targets;i++) { + for(k = 0; k < vanity_rmd_limits[i]; k++) { + bloom_add(vanity_bloom, vanity_rmd_limit_values_A[i][k] ,vanity_rmd_minimun_bytes_check_length); + } + } + return true; +} + + +bool readFileVanity(char *fileName) { + FILE *fileDescriptor; + int i,k,len; + char aux[100],*hextemp; + + fileDescriptor = fopen(fileName,"r"); + if(fileDescriptor == NULL) { + if(vanity_rmd_targets == 0) { + fprintf(stderr,"[E] There aren't any vanity targets\n"); + return false; + } + } + else { + while(!feof(fileDescriptor)) { + hextemp = fgets(aux,100,fileDescriptor); + if(hextemp == aux) { + trim(aux," \t\n\r"); + len = strlen(aux); + if(len > 0 && len < 36){ + if(isValidBase58String(aux)) { + addvanity(aux); + } + else { + fprintf(stderr,"[E] the string \"%s\" is not valid Base58, omiting it\n",aux); + } + } + } + } + fclose(fileDescriptor); + } + + N = vanity_rmd_total; + if(!initBloomFilter(vanity_bloom,N)) + return false; + + + for(i = 0;i < vanity_rmd_targets; i++) { + for(k = 0; k < vanity_rmd_limits[i]; k++) { + /* + if(FLAGDEBUG) { + printf("[D] i %i ; k %i\n",i,k); + hextemp = tohex((char*)vanity_rmd_limit_values_A[i][k],vanity_rmd_minimun_bytes_check_length); + printf("[D] Adding %s\n",hextemp); + fflush(stdout); + free(hextemp); + } + */ + bloom_add(vanity_bloom, vanity_rmd_limit_values_A[i][k] ,vanity_rmd_minimun_bytes_check_length); + } + } + return true; +} + +bool readFileAddress(char *fileName) { + FILE *fileDescriptor; + char fileBloomName[30]; /* Actually it is Bloom and Table but just to keep the variable name short*/ + uint8_t checksum[32],hexPrefix[9]; + char dataChecksum[32],bloomChecksum[32]; + size_t bytesRead; + uint64_t dataSize; + /* + if the FLAGSAVEREADFILE is Set to 1 we need to the checksum and check if we have that information already saved + */ + if(FLAGSAVEREADFILE) { /* if the flag is set to REAd and SAVE the file firs we need to check it the file exist*/ + if(!sha256_file((const char*)fileName,checksum)){ + fprintf(stderr,"[E] sha256_file error line %i\n",__LINE__ - 1); + return false; + } + tohex_dst((char*)checksum,4,(char*)hexPrefix); // we save the prefix (last fourt bytes) hexadecimal value + snprintf(fileBloomName,30,"data_%s.dat",hexPrefix); + fileDescriptor = fopen(fileBloomName,"rb"); + if(fileDescriptor != NULL) { + printf("[+] Reading file %s\n",fileBloomName); + + //read bloom checksum (expected value to be checked) + //read bloom filter structure + //read bloom filter data + //calculate checksum of the current readed data + //Compare checksums + //read data checksum (expected value to be checked) + //read data size + //read data + //compare the expected datachecksum againts the current data checksum + //compare the expected bloom checksum againts the current bloom checksum + + + //read bloom checksum (expected value to be checked) + bytesRead = fread(bloomChecksum,1,32,fileDescriptor); + if(bytesRead != 32) { + fprintf(stderr,"[E] Errore reading file, code line %i\n",__LINE__ - 2); + fclose(fileDescriptor); + return false; + } + + //read bloom filter structure + bytesRead = fread(&bloom,1,sizeof(struct bloom),fileDescriptor); + if(bytesRead != sizeof(struct bloom)) { + fprintf(stderr,"[E] Error reading file, code line %i\n",__LINE__ - 2); + fclose(fileDescriptor); + return false; + } + + printf("[+] Bloom filter for %" PRIu64 " elements.\n",bloom.entries); + + bloom.bf = (uint8_t*) malloc(bloom.bytes); + if(bloom.bf == NULL) { + fprintf(stderr,"[E] Error allocating memory, code line %i\n",__LINE__ - 2); + fclose(fileDescriptor); + return false; + } + + //read bloom filter data + bytesRead = fread(bloom.bf,1,bloom.bytes,fileDescriptor); + if(bytesRead != bloom.bytes) { + fprintf(stderr,"[E] Error reading file, code line %i\n",__LINE__ - 2); + fclose(fileDescriptor); + return false; + } + if(FLAGSKIPCHECKSUM == 0){ + + //calculate checksum of the current readed data + sha256((uint8_t*)bloom.bf,bloom.bytes,(uint8_t*)checksum); + + //Compare checksums + if(memcmp(checksum,bloomChecksum,32) != 0) { + fprintf(stderr,"[E] Error checksum mismatch, code line %i\n",__LINE__ - 2); + fclose(fileDescriptor); + return false; + } + } + + bytesRead = fread(dataChecksum,1,32,fileDescriptor); + if(bytesRead != 32) { + fprintf(stderr,"[E] Errore reading file, code line %i\n",__LINE__ - 2); + fclose(fileDescriptor); + return false; + } + + bytesRead = fread(&dataSize,1,sizeof(uint64_t),fileDescriptor); + if(bytesRead != sizeof(uint64_t)) { + fprintf(stderr,"[E] Errore reading file, code line %i\n",__LINE__ - 2); + fclose(fileDescriptor); + return false; + } + N = dataSize / sizeof(struct address_value); + + printf("[+] Allocating memory for %" PRIu64 " elements: %.2f MB\n",N,(double)(((double) sizeof(struct address_value)*N)/(double)1048576)); + + addressTable = (struct address_value*) malloc(dataSize); + if(addressTable == NULL) { + fprintf(stderr,"[E] Error allocating memory, code line %i\n",__LINE__ - 2); + fclose(fileDescriptor); + return false; + } + + bytesRead = fread(addressTable,1,dataSize,fileDescriptor); + if(bytesRead != dataSize) { + fprintf(stderr,"[E] Error reading file, code line %i\n",__LINE__ - 2); + fclose(fileDescriptor); + return false; + } + if(FLAGSKIPCHECKSUM == 0) { + + sha256((uint8_t*)addressTable,dataSize,(uint8_t*)checksum); + if(memcmp(checksum,dataChecksum,32) != 0) { + fprintf(stderr,"[E] Error checksum mismatch, code line %i\n",__LINE__ - 2); + fclose(fileDescriptor); + return false; + } + } + //printf("[D] bloom.bf points to %p\n",bloom.bf); + FLAGREADEDFILE1 = 1; /* We mark the file as readed*/ + fclose(fileDescriptor); + MAXLENGTHADDRESS = sizeof(struct address_value); + } + } + if(FLAGVANITY) { + processOneVanity(); + } + if(!FLAGREADEDFILE1) { + /* + if the data_ file doesn't exist we need read it first: + */ + switch(FLAGMODE) { + case MODE_ADDRESS: + if(FLAGCRYPTO == CRYPTO_BTC) { + return forceReadFileAddress(fileName); + } + if(FLAGCRYPTO == CRYPTO_ETH) { + return forceReadFileAddressEth(fileName); + } + break; + case MODE_MINIKEYS: + case MODE_PUB2RMD: + case MODE_RMD160: + return forceReadFileAddress(fileName); + break; + case MODE_XPOINT: + return forceReadFileXPoint(fileName); + break; + default: + return false; + break; + } + } + return true; +} + +bool forceReadFileAddress(char *fileName) { + /* Here we read the original file as usual */ + FILE *fileDescriptor; + bool validAddress; + uint64_t numberItems,i; + size_t r,raw_value_length; + uint8_t rawvalue[50]; + char aux[100],*hextemp; + fileDescriptor = fopen(fileName,"r"); + if(fileDescriptor == NULL) { + fprintf(stderr,"[E] Error opening the file %s, line %i\n",fileName,__LINE__ - 2); + return false; + } + + /*Count lines in the file*/ + numberItems = 0; + while(!feof(fileDescriptor)) { + hextemp = fgets(aux,100,fileDescriptor); + trim(aux," \t\n\r"); + if(hextemp == aux) { + r = strlen(aux); + if(r > 20) { + numberItems++; + } + } + } + fseek(fileDescriptor,0,SEEK_SET); + MAXLENGTHADDRESS = 20; /*20 bytes beacuase we only need the data in binary*/ + + printf("[+] Allocating memory for %" PRIu64 " elements: %.2f MB\n",numberItems,(double)(((double) sizeof(struct address_value)*numberItems)/(double)1048576)); + addressTable = (struct address_value*) malloc(sizeof(struct address_value)*numberItems); + checkpointer((void *)addressTable,__FILE__,"malloc","addressTable" ,__LINE__ -1 ); + + if(!initBloomFilter(&bloom,numberItems)) + return false; + + i = 0; + while(i < numberItems) { + validAddress = false; + memset(aux,0,100); + memset(addressTable[i].value,0,sizeof(struct address_value)); + hextemp = fgets(aux,100,fileDescriptor); + trim(aux," \t\n\r"); + r = strlen(aux); + if(r > 0 && r <= 40) { + if(r<40 && isValidBase58String(aux)) { //Address + raw_value_length = 25; + b58tobin(rawvalue,&raw_value_length,aux,r); + if(raw_value_length == 25) { + //hextemp = tohex((char*)rawvalue+1,20); + bloom_add(&bloom, rawvalue+1 ,sizeof(struct address_value)); + memcpy(addressTable[i].value,rawvalue+1,sizeof(struct address_value)); + i++; + validAddress = true; + } + } + if(r == 40 && isValidHex(aux)) { //RMD + hexs2bin(aux,rawvalue); + bloom_add(&bloom, rawvalue ,sizeof(struct address_value)); + memcpy(addressTable[i].value,rawvalue,sizeof(struct address_value)); + i++; + validAddress = true; + } + } + if(!validAddress) { + fprintf(stderr,"[I] Ommiting invalid line %s\n",aux); + numberItems--; + } + } + N = numberItems; + return true; +} + +bool forceReadFileAddressEth(char *fileName) { + /* Here we read the original file as usual */ + FILE *fileDescriptor; + bool validAddress; + uint64_t numberItems,i; + size_t r; + uint8_t rawvalue[50]; + char aux[100],*hextemp; + fileDescriptor = fopen(fileName,"r"); + if(fileDescriptor == NULL) { + fprintf(stderr,"[E] Error opening the file %s, line %i\n",fileName,__LINE__ - 2); + return false; + } + /*Count lines in the file*/ + numberItems = 0; + while(!feof(fileDescriptor)) { + hextemp = fgets(aux,100,fileDescriptor); + trim(aux," \t\n\r"); + if(hextemp == aux) { + r = strlen(aux); + if(r >= 40) { + numberItems++; + } + } + } + fseek(fileDescriptor,0,SEEK_SET); + + MAXLENGTHADDRESS = 20; /*20 bytes beacuase we only need the data in binary*/ + N = numberItems; + + printf("[+] Allocating memory for %" PRIu64 " elements: %.2f MB\n",numberItems,(double)(((double) sizeof(struct address_value)*numberItems)/(double)1048576)); + addressTable = (struct address_value*) malloc(sizeof(struct address_value)*numberItems); + checkpointer((void *)addressTable,__FILE__,"malloc","addressTable" ,__LINE__ -1 ); + + + if(!initBloomFilter(&bloom,N)) + return false; + + i = 0; + while(i < numberItems) { + validAddress = false; + memset(aux,0,100); + memset(addressTable[i].value,0,sizeof(struct address_value)); + hextemp = fgets(aux,100,fileDescriptor); + trim(aux," \t\n\r"); + r = strlen(aux); + if(r >= 40 && r <= 42){ + switch(r) { + case 40: + if(isValidHex(aux)){ + hexs2bin(aux,rawvalue); + bloom_add(&bloom, rawvalue ,sizeof(struct address_value)); + memcpy(addressTable[i].value,rawvalue,sizeof(struct address_value)); + i++; + validAddress = true; + } + break; + case 42: + if(isValidHex(aux+2)){ + hexs2bin(aux+2,rawvalue); + bloom_add(&bloom, rawvalue ,sizeof(struct address_value)); + memcpy(addressTable[i].value,rawvalue,sizeof(struct address_value)); + i++; + validAddress = true; + } + break; + } + } + if(!validAddress) { + fprintf(stderr,"[I] Ommiting invalid line %s\n",aux); + numberItems--; + } + } + + fclose(fileDescriptor); + return true; +} + + + +bool forceReadFileXPoint(char *fileName) { + /* Here we read the original file as usual */ + FILE *fileDescriptor; + uint64_t numberItems,i; + size_t r,lenaux; + uint8_t rawvalue[100]; + char aux[1000],*hextemp; + Tokenizer tokenizer_xpoint; //tokenizer + fileDescriptor = fopen(fileName,"r"); + if(fileDescriptor == NULL) { + fprintf(stderr,"[E] Error opening the file %s, line %i\n",fileName,__LINE__ - 2); + return false; + } + /*Count lines in the file*/ + numberItems = 0; + while(!feof(fileDescriptor)) { + hextemp = fgets(aux,1000,fileDescriptor); + trim(aux," \t\n\r"); + if(hextemp == aux) { + r = strlen(aux); + if(r >= 40) { + numberItems++; + } + } + } + fseek(fileDescriptor,0,SEEK_SET); + + MAXLENGTHADDRESS = 20; /*20 bytes beacuase we only need the data in binary*/ + + printf("[+] Allocating memory for %" PRIu64 " elements: %.2f MB\n",numberItems,(double)(((double) sizeof(struct address_value)*numberItems)/(double)1048576)); + addressTable = (struct address_value*) malloc(sizeof(struct address_value)*numberItems); + checkpointer((void *)addressTable,__FILE__,"malloc","addressTable" ,__LINE__ - 1); + + N = numberItems; + + if(!initBloomFilter(&bloom,N)) + return false; + + i = 0; + while(i < N) { + memset(aux,0,1000); + hextemp = fgets(aux,1000,fileDescriptor); + memset((void *)&addressTable[i],0,sizeof(struct address_value)); + if(hextemp == aux) { + trim(aux," \t\n\r"); + stringtokenizer(aux,&tokenizer_xpoint); + hextemp = nextToken(&tokenizer_xpoint); + lenaux = strlen(hextemp); + if(isValidHex(hextemp)) { + switch(lenaux) { + case 64: /*X value*/ + r = hexs2bin(aux,(uint8_t*) rawvalue); + if(r) { + memcpy(addressTable[i].value,rawvalue,20); + bloom_add(&bloom,rawvalue,MAXLENGTHADDRESS); + } + else { + fprintf(stderr,"[E] error hexs2bin\n"); + } + break; + case 66: /*Compress publickey*/ + r = hexs2bin(aux+2, (uint8_t*)rawvalue); + if(r) { + memcpy(addressTable[i].value,rawvalue,20); + bloom_add(&bloom,rawvalue,MAXLENGTHADDRESS); + } + else { + fprintf(stderr,"[E] error hexs2bin\n"); + } + break; + case 130: /* Uncompress publickey length*/ + r = hexs2bin(aux, (uint8_t*) rawvalue); + if(r) { + memcpy(addressTable[i].value,rawvalue+2,20); + bloom_add(&bloom,rawvalue,MAXLENGTHADDRESS); + } + else { + fprintf(stderr,"[E] error hexs2bin\n"); + } + break; + default: + fprintf(stderr,"[E] Omiting line unknow length size %li: %s\n",lenaux,aux); + break; + } + } + else { + fprintf(stderr,"[E] Ignoring invalid hexvalue %s\n",aux); + } + freetokenizer(&tokenizer_xpoint); + } + else { + fprintf(stderr,"[E] Omiting line : %s\n",aux); + N--; + } + i++; + } + fclose(fileDescriptor); + return true; +} + + +/* + I write this as a function because i have the same segment of code in 3 different functions +*/ + +bool initBloomFilter(struct bloom *bloom_arg,uint64_t items_bloom) { + bool r = true; + printf("[+] Bloom filter for %" PRIu64 " elements.\n",items_bloom); + if(items_bloom <= 10000) { + if(bloom_init2(bloom_arg,10000,0.000001) == 1){ + fprintf(stderr,"[E] error bloom_init for 10000 elements.\n"); + r = false; + } + } + else { + if(bloom_init2(bloom_arg,FLAGBLOOMMULTIPLIER*items_bloom,0.000001) == 1){ + fprintf(stderr,"[E] error bloom_init for %" PRIu64 " elements.\n",items_bloom); + r = false; + } + } + printf("[+] Loading data to the bloomfilter total: %.2f MB\n",(double)(((double) bloom_arg->bytes)/(double)1048576)); + return r; +} + +void writeFileIfNeeded(const char *fileName) { + //printf("[D] FLAGSAVEREADFILE %i, FLAGREADEDFILE1 %i\n",FLAGSAVEREADFILE,FLAGREADEDFILE1); + if(FLAGSAVEREADFILE && !FLAGREADEDFILE1) { + FILE *fileDescriptor; + char fileBloomName[30]; + uint8_t checksum[32],hexPrefix[9]; + char dataChecksum[32],bloomChecksum[32]; + size_t bytesWrite; + uint64_t dataSize; + if(!sha256_file((const char*)fileName,checksum)){ + fprintf(stderr,"[E] sha256_file error line %i\n",__LINE__ - 1); + exit(EXIT_FAILURE); + } + tohex_dst((char*)checksum,4,(char*)hexPrefix); // we save the prefix (last fourt bytes) hexadecimal value + snprintf(fileBloomName,30,"data_%s.dat",hexPrefix); + fileDescriptor = fopen(fileBloomName,"wb"); + dataSize = N * (sizeof(struct address_value)); + printf("[D] size data %li\n",dataSize); + if(fileDescriptor != NULL) { + printf("[+] Writing file %s ",fileBloomName); + + + //calculate bloom checksum + //write bloom checksum (expected value to be checked) + //write bloom filter structure + //write bloom filter data + + + //calculate dataChecksum + //write data checksum (expected value to be checked) + //write data size + //write data + + + + + sha256((uint8_t*)bloom.bf,bloom.bytes,(uint8_t*)bloomChecksum); + printf("."); + bytesWrite = fwrite(bloomChecksum,1,32,fileDescriptor); + if(bytesWrite != 32) { + fprintf(stderr,"[E] Errore writing file, code line %i\n",__LINE__ - 2); + exit(EXIT_FAILURE); + } + printf("."); + + bytesWrite = fwrite(&bloom,1,sizeof(struct bloom),fileDescriptor); + if(bytesWrite != sizeof(struct bloom)) { + fprintf(stderr,"[E] Error writing file, code line %i\n",__LINE__ - 2); + exit(EXIT_FAILURE); + } + printf("."); + + bytesWrite = fwrite(bloom.bf,1,bloom.bytes,fileDescriptor); + if(bytesWrite != bloom.bytes) { + fprintf(stderr,"[E] Error writing file, code line %i\n",__LINE__ - 2); + fclose(fileDescriptor); + exit(EXIT_FAILURE); + } + printf("."); + + + sha256((uint8_t*)addressTable,dataSize,(uint8_t*)dataChecksum); + printf("."); + + bytesWrite = fwrite(dataChecksum,1,32,fileDescriptor); + if(bytesWrite != 32) { + fprintf(stderr,"[E] Errore writing file, code line %i\n",__LINE__ - 2); + exit(EXIT_FAILURE); + } + printf("."); + + bytesWrite = fwrite(&dataSize,1,sizeof(uint64_t),fileDescriptor); + if(bytesWrite != sizeof(uint64_t)) { + fprintf(stderr,"[E] Errore writing file, code line %i\n",__LINE__ - 2); + exit(EXIT_FAILURE); + } + printf("."); + + bytesWrite = fwrite(addressTable,1,dataSize,fileDescriptor); + if(bytesWrite != dataSize) { + fprintf(stderr,"[E] Error writing file, code line %i\n",__LINE__ - 2); + exit(EXIT_FAILURE); + } + printf("."); + + FLAGREADEDFILE1 = 1; + fclose(fileDescriptor); + printf("\n"); + } + } +} diff --git a/oldbloom/bloom.cpp b/oldbloom/bloom.cpp index 0b870e6..7af35ae 100644 --- a/oldbloom/bloom.cpp +++ b/oldbloom/bloom.cpp @@ -146,7 +146,6 @@ int oldbloom_check(struct oldbloom * bloom, const void * buffer, int len) uint64_t b = XXH64(buffer, len, a); uint64_t x; uint8_t i; - int r; for (i = 0; i < bloom->hashes; i++) { x = (a + b*i) % bloom->bits; if (oldtest_bit(bloom->bf, x)) { diff --git a/oldbloom/bloom.h b/oldbloom/bloom.h deleted file mode 100644 index 22c2a05..0000000 --- a/oldbloom/bloom.h +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (c) 2012-2019, Jyri J. Virkki - * All rights reserved. - * - * This file is under BSD license. See LICENSE file. - */ - -#ifndef _OLDBLOOM_H -#define _OLDBLOOM_H - -#ifdef _WIN64 -#include -#else -#endif -#ifdef __cplusplus -extern "C" { -#endif - - -/** *************************************************************************** - * Structure to keep track of one bloom filter. Caller needs to - * allocate this and pass it to the functions below. First call for - * every struct must be to bloom_init(). - * - */ -struct oldbloom -{ - // These fields are part of the public interface of this structure. - // Client code may read these values if desired. Client code MUST NOT - // modify any of these. - uint64_t entries; - uint64_t bits; - uint64_t bytes; - uint8_t hashes; - long double error; - - // Fields below are private to the implementation. These may go away or - // change incompatibly at any moment. Client code MUST NOT access or rely - // on these. - uint8_t ready; - uint8_t major; - uint8_t minor; - double bpe; - uint8_t checksum[32]; - uint8_t checksum_backup[32]; - uint8_t *bf; -#ifdef _WIN64 - HANDLE mutex; -#else - pthread_mutex_t mutex; -#endif -}; -/* -Customs -*/ -/* -int oldbloom_loadcustom(struct oldbloom * bloom, char * filename); -int oldbloom_savecustom(struct oldbloom * bloom, char * filename); -*/ - -/** *************************************************************************** - * Initialize the bloom filter for use. - * - * The filter is initialized with a bit field and number of hash functions - * according to the computations from the wikipedia entry: - * http://en.wikipedia.org/wiki/Bloom_filter - * - * Optimal number of bits is: - * bits = (entries * ln(error)) / ln(2)^2 - * - * Optimal number of hash functions is: - * hashes = bpe * ln(2) - * - * Parameters: - * ----------- - * bloom - Pointer to an allocated struct bloom (see above). - * entries - The expected number of entries which will be inserted. - * Must be at least 1000 (in practice, likely much larger). - * error - Probability of collision (as long as entries are not - * exceeded). - * - * Return: - * ------- - * 0 - on success - * 1 - on failure - * - */ -int oldbloom_init2(struct oldbloom * bloom, uint64_t entries, long double error); - - -/** - * DEPRECATED. - * Kept for compatibility with libbloom v.1. To be removed in v3.0. - * - */ -int oldbloom_init(struct oldbloom * bloom, uint64_t entries, long double error); - - -/** *************************************************************************** - * Check if the given element is in the bloom filter. Remember this may - * return false positive if a collision occurred. - * - * Parameters: - * ----------- - * bloom - Pointer to an allocated struct bloom (see above). - * buffer - Pointer to buffer containing element to check. - * len - Size of 'buffer'. - * - * Return: - * ------- - * 0 - element is not present - * 1 - element is present (or false positive due to collision) - * -1 - bloom not initialized - * - */ -int oldbloom_check(struct oldbloom * bloom, const void * buffer, int len); - - -/** *************************************************************************** - * Add the given element to the bloom filter. - * The return code indicates if the element (or a collision) was already in, - * so for the common check+add use case, no need to call check separately. - * - * Parameters: - * ----------- - * bloom - Pointer to an allocated struct bloom (see above). - * buffer - Pointer to buffer containing element to add. - * len - Size of 'buffer'. - * - * Return: - * ------- - * 0 - element was not present and was added - * 1 - element (or a collision) had already been added previously - * -1 - bloom not initialized - * - */ -int oldbloom_add(struct oldbloom * bloom, const void * buffer, int len); - - -/** *************************************************************************** - * Print (to stdout) info about this bloom filter. Debugging aid. - * - */ -void oldbloom_print(struct oldbloom * bloom); - - -/** *************************************************************************** - * Deallocate internal storage. - * - * Upon return, the bloom struct is no longer usable. You may call bloom_init - * again on the same struct to reinitialize it again. - * - * Parameters: - * ----------- - * bloom - Pointer to an allocated struct bloom (see above). - * - * Return: none - * - */ -void oldbloom_free(struct oldbloom * bloom); - - -/** *************************************************************************** - * Erase internal storage. - * - * Erases all elements. Upon return, the bloom struct returns to its initial - * (initialized) state. - * - * Parameters: - * ----------- - * bloom - Pointer to an allocated struct bloom (see above). - * - * Return: - * 0 - on success - * 1 - on failure - * - */ -int oldbloom_reset(struct oldbloom * bloom); - - -/** *************************************************************************** - * Save a bloom filter to a file. - * - * Parameters: - * ----------- - * bloom - Pointer to an allocated struct bloom (see above). - * filename - Create (or overwrite) bloom data to this file. - * - * Return: - * 0 - on success - * 1 - on failure - * - */ -//int oldbloom_save(struct oldbloom * bloom, char * filename); - - -/** *************************************************************************** - * Load a bloom filter from a file. - * - * This functions loads a file previously saved with bloom_save(). - * - * Parameters: - * ----------- - * bloom - Pointer to an allocated struct bloom (see above). - * filename - Load bloom filter data from this file. - * - * Return: - * 0 - on success - * > 0 - on failure - * - */ -//int oldbloom_load(struct oldbloom * bloom, char * filename); - - -/** *************************************************************************** - * Returns version string compiled into library. - * - * Return: version string - * - */ -const char * oldbloom_version(); - -#ifdef __cplusplus -} -#endif - -#endif \ No newline at end of file