From 1f1a9bd3479fa84ac8b959d8340084d9324826bb Mon Sep 17 00:00:00 2001 From: AlbertoBSD Date: Thu, 17 Dec 2020 19:05:34 +0100 Subject: [PATCH] Added basecode, sha256, rmd160, bas58 and bloomfilter --- .gitignore | 1 + Makefile | 11 + base58/base58.c | 205 +++++++ base58/libbase58.h | 23 + bloom/LICENSE | 26 + bloom/bloom.c | 167 ++++++ bloom/bloom.h | 173 ++++++ bloom/murmur2/MurmurHash2.c | 64 +++ bloom/murmur2/README | 9 + bloom/murmur2/murmurhash2.h | 7 + keyhunt.c | 1067 +++++++++++++++++++++++++++++++++++ rmd160/rmd160.c | 450 +++++++++++++++ rmd160/rmd160.h | 41 ++ sha256/sha256.c | 142 +++++ sha256/sha256.h | 17 + util.h | 186 ++++++ 16 files changed, 2589 insertions(+) create mode 100755 Makefile create mode 100644 base58/base58.c create mode 100644 base58/libbase58.h create mode 100644 bloom/LICENSE create mode 100644 bloom/bloom.c create mode 100644 bloom/bloom.h create mode 100644 bloom/murmur2/MurmurHash2.c create mode 100644 bloom/murmur2/README create mode 100644 bloom/murmur2/murmurhash2.h create mode 100644 keyhunt.c create mode 100644 rmd160/rmd160.c create mode 100644 rmd160/rmd160.h create mode 100644 sha256/sha256.c create mode 100644 sha256/sha256.h create mode 100644 util.h diff --git a/.gitignore b/.gitignore index c6127b3..a9e2e34 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.txt # Prerequisites *.d diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..eea6689 --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +default: + gcc -O3 -c bloom/bloom.c -o bloom.o -I./bloom/murmur2 + gcc -O3 -c bloom/murmur2/MurmurHash2.c -o murmurhash2.o + gcc -O3 -c sha256/sha256.c -o sha256.o + gcc -O3 -c base58/base58.c -o base58.o + gcc -O3 -c rmd160/rmd160.c -o rmd160.o + gcc -O3 -c keyhunt.c -o keyhunt.o + gcc -o keyhunt keyhunt.o base58.o rmd160.o sha256.o bloom.o murmurhash2.o -lgmp -lm -lpthread +clean: + rm -r *.o + diff --git a/base58/base58.c b/base58/base58.c new file mode 100644 index 0000000..6265741 --- /dev/null +++ b/base58/base58.c @@ -0,0 +1,205 @@ +/* + * Copyright 2012-2014 Luke Dashjr + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the standard MIT license. See COPYING for more details. + */ + +#ifndef WIN32 +#include +#else +#include +#endif + +#include +#include +#include +#include + +#include "libbase58.h" + +bool (*b58_sha256_impl)(void *, const void *, size_t) = NULL; + +static const int8_t b58digits_map[] = { + -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1, + -1, 9,10,11,12,13,14,15, 16,-1,17,18,19,20,21,-1, + 22,23,24,25,26,27,28,29, 30,31,32,-1,-1,-1,-1,-1, + -1,33,34,35,36,37,38,39, 40,41,42,43,-1,44,45,46, + 47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1, +}; + +typedef uint64_t b58_maxint_t; +typedef uint32_t b58_almostmaxint_t; +#define b58_almostmaxint_bits (sizeof(b58_almostmaxint_t) * 8) +static const b58_almostmaxint_t b58_almostmaxint_mask = ((((b58_maxint_t)1) << b58_almostmaxint_bits) - 1); + +bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz) +{ + size_t binsz = *binszp; + const unsigned char *b58u = (void*)b58; + unsigned char *binu = bin; + size_t outisz = (binsz + sizeof(b58_almostmaxint_t) - 1) / sizeof(b58_almostmaxint_t); + b58_almostmaxint_t outi[outisz]; + b58_maxint_t t; + b58_almostmaxint_t c; + size_t i, j; + uint8_t bytesleft = binsz % sizeof(b58_almostmaxint_t); + b58_almostmaxint_t zeromask = bytesleft ? (b58_almostmaxint_mask << (bytesleft * 8)) : 0; + unsigned zerocount = 0; + + if (!b58sz) + b58sz = strlen(b58); + + for (i = 0; i < outisz; ++i) { + outi[i] = 0; + } + + // Leading zeros, just count + for (i = 0; i < b58sz && b58u[i] == '1'; ++i) + ++zerocount; + + for ( ; i < b58sz; ++i) + { + if (b58u[i] & 0x80) + // High-bit set on invalid digit + return false; + if (b58digits_map[b58u[i]] == -1) + // Invalid base58 digit + return false; + c = (unsigned)b58digits_map[b58u[i]]; + for (j = outisz; j--; ) + { + t = ((b58_maxint_t)outi[j]) * 58 + c; + c = t >> b58_almostmaxint_bits; + outi[j] = t & b58_almostmaxint_mask; + } + if (c) + // Output number too big (carry to the next int32) + return false; + if (outi[0] & zeromask) + // Output number too big (last int32 filled too far) + return false; + } + + j = 0; + if (bytesleft) { + for (i = bytesleft; i > 0; --i) { + *(binu++) = (outi[0] >> (8 * (i - 1))) & 0xff; + } + ++j; + } + + for (; j < outisz; ++j) + { + for (i = sizeof(*outi); i > 0; --i) { + *(binu++) = (outi[j] >> (8 * (i - 1))) & 0xff; + } + } + + // Count canonical base58 byte count + binu = bin; + for (i = 0; i < binsz; ++i) + { + if (binu[i]) + break; + --*binszp; + } + *binszp += zerocount; + + return true; +} + +static +bool my_dblsha256(void *hash, const void *data, size_t datasz) +{ + uint8_t buf[0x20]; + return b58_sha256_impl(buf, data, datasz) && b58_sha256_impl(hash, buf, sizeof(buf)); +} + +int b58check(const void *bin, size_t binsz, const char *base58str, size_t b58sz) +{ + unsigned char buf[32]; + const uint8_t *binc = bin; + unsigned i; + if (binsz < 4) + return -4; + if (!my_dblsha256(buf, bin, binsz - 4)) + return -2; + if (memcmp(&binc[binsz - 4], buf, 4)) + return -1; + + // Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end) + for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i) + {} // Just finding the end of zeros, nothing to do in loop + if (binc[i] == '\0' || base58str[i] == '1') + return -3; + + return binc[0]; +} + +static const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + +bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz) +{ + const uint8_t *bin = data; + int carry; + size_t i, j, high, zcount = 0; + size_t size; + + while (zcount < binsz && !bin[zcount]) + ++zcount; + + size = (binsz - zcount) * 138 / 100 + 1; + uint8_t buf[size]; + memset(buf, 0, size); + + for (i = zcount, high = size - 1; i < binsz; ++i, high = j) + { + for (carry = bin[i], j = size - 1; (j > high) || carry; --j) + { + carry += 256 * buf[j]; + buf[j] = carry % 58; + carry /= 58; + if (!j) { + // Otherwise j wraps to maxint which is > high + break; + } + } + } + + for (j = 0; j < size && !buf[j]; ++j); + + if (*b58sz <= zcount + size - j) + { + *b58sz = zcount + size - j + 1; + return false; + } + + if (zcount) + memset(b58, '1', zcount); + for (i = zcount; j < size; ++i, ++j) + b58[i] = b58digits_ordered[buf[j]]; + b58[i] = '\0'; + *b58sz = i + 1; + + return true; +} + +bool b58check_enc(char *b58c, size_t *b58c_sz, uint8_t ver, const void *data, size_t datasz) +{ + uint8_t buf[1 + datasz + 0x20]; + uint8_t *hash = &buf[1 + datasz]; + + buf[0] = ver; + memcpy(&buf[1], data, datasz); + if (!my_dblsha256(hash, buf, datasz + 1)) + { + *b58c_sz = 0; + return false; + } + + return b58enc(b58c, b58c_sz, buf, 1 + datasz + 4); +} diff --git a/base58/libbase58.h b/base58/libbase58.h new file mode 100644 index 0000000..fafe653 --- /dev/null +++ b/base58/libbase58.h @@ -0,0 +1,23 @@ +#ifndef LIBBASE58_H +#define LIBBASE58_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern bool (*b58_sha256_impl)(void *, const void *, size_t); + +extern bool b58tobin(void *bin, size_t *binsz, const char *b58, size_t b58sz); +extern int b58check(const void *bin, size_t binsz, const char *b58, size_t b58sz); + +extern bool b58enc(char *b58, size_t *b58sz, const void *bin, size_t binsz); +extern bool b58check_enc(char *b58c, size_t *b58c_sz, uint8_t ver, const void *data, size_t datasz); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bloom/LICENSE b/bloom/LICENSE new file mode 100644 index 0000000..0263dae --- /dev/null +++ b/bloom/LICENSE @@ -0,0 +1,26 @@ + +Copyright (c) 2012,2015,2016,2017 Jyri J. Virkki +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/bloom/bloom.c b/bloom/bloom.c new file mode 100644 index 0000000..4b7a19e --- /dev/null +++ b/bloom/bloom.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2012-2019, Jyri J. Virkki + * All rights reserved. + * + * This file is under BSD license. See LICENSE file. + */ + +/* + * Refer to bloom.h for documentation on the public interfaces. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bloom.h" +#include "murmurhash2.h" + +#define MAKESTRING(n) STRING(n) +#define STRING(n) #n + + +inline static int test_bit_set_bit(unsigned char * buf, + unsigned int x, int set_bit) +{ + unsigned int byte = x >> 3; + unsigned char c = buf[byte]; // expensive memory access + unsigned int mask = 1 << (x % 8); + + if (c & mask) { + return 1; + } else { + if (set_bit) { + buf[byte] = c | mask; + } + return 0; + } +} + + +static int bloom_check_add(struct bloom * bloom, + const void * buffer, int len, int add) +{ + if (bloom->ready == 0) { + printf("bloom at %p not initialized!\n", (void *)bloom); + return -1; + } + + int hits = 0; + register unsigned int a = murmurhash2(buffer, len, 0x9747b28c); + register unsigned int b = murmurhash2(buffer, len, a); + register unsigned int x; + register unsigned int i; + + for (i = 0; i < bloom->hashes; i++) { + x = (a + i*b) % bloom->bits; + if (test_bit_set_bit(bloom->bf, x, add)) { + hits++; + } else if (!add) { + // Don't care about the presence of all the bits. Just our own. + return 0; + } + } + + if (hits == bloom->hashes) { + return 1; // 1 == element already in (or collision) + } + + return 0; +} + + +int bloom_init_size(struct bloom * bloom, int entries, double error, + unsigned int cache_size) +{ + return bloom_init(bloom, entries, error); +} + + +int bloom_init(struct bloom * bloom, int entries, double error) +{ + bloom->ready = 0; + + if (entries < 1000 || error == 0) { + return 1; + } + + bloom->entries = entries; + bloom->error = error; + + double num = log(bloom->error); + double denom = 0.480453013918201; // ln(2)^2 + bloom->bpe = -(num / denom); + + double dentries = (double)entries; + bloom->bits = (int)(dentries * bloom->bpe); + + if (bloom->bits % 8) { + bloom->bytes = (bloom->bits / 8) + 1; + } else { + bloom->bytes = bloom->bits / 8; + } + + bloom->hashes = (int)ceil(0.693147180559945 * bloom->bpe); // ln(2) + + bloom->bf = (unsigned char *)calloc(bloom->bytes, sizeof(unsigned char)); + if (bloom->bf == NULL) { // LCOV_EXCL_START + return 1; + } // LCOV_EXCL_STOP + + bloom->ready = 1; + return 0; +} + + +int bloom_check(struct bloom * bloom, const void * buffer, int len) +{ + return bloom_check_add(bloom, buffer, len, 0); +} + + +int bloom_add(struct bloom * bloom, const void * buffer, int len) +{ + return bloom_check_add(bloom, buffer, len, 1); +} + + +void bloom_print(struct bloom * bloom) +{ + printf("bloom at %p\n", (void *)bloom); + printf(" ->entries = %d\n", bloom->entries); + printf(" ->error = %f\n", bloom->error); + printf(" ->bits = %d\n", bloom->bits); + printf(" ->bits per elem = %f\n", bloom->bpe); + printf(" ->bytes = %d\n", bloom->bytes); + printf(" ->hash functions = %d\n", bloom->hashes); +} + + +void bloom_free(struct bloom * bloom) +{ + if (bloom->ready) { + free(bloom->bf); + } + bloom->ready = 0; +} + + +int bloom_reset(struct bloom * bloom) +{ + if (!bloom->ready) return 1; + memset(bloom->bf, 0, bloom->bytes); + return 0; +} + + +const char * bloom_version() +{ + return MAKESTRING(BLOOM_VERSION); +} diff --git a/bloom/bloom.h b/bloom/bloom.h new file mode 100644 index 0000000..61cd60c --- /dev/null +++ b/bloom/bloom.h @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2012-2017, Jyri J. Virkki + * All rights reserved. + * + * This file is under BSD license. See LICENSE file. + */ + +#ifndef _BLOOM_H +#define _BLOOM_H + +#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 bloom +{ + // 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. + int entries; + double error; + int bits; + int bytes; + int hashes; + + // 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. + double bpe; + unsigned char * bf; + int ready; +}; + + +/** *************************************************************************** + * 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 bloom_init(struct bloom * bloom, int entries, double error); + + +/** *************************************************************************** + * Deprecated, use bloom_init() + * + */ +int bloom_init_size(struct bloom * bloom, int entries, double error, + unsigned int cache_size); + + +/** *************************************************************************** + * 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 bloom_check(struct bloom * 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 bloom_add(struct bloom * bloom, const void * buffer, int len); + + +/** *************************************************************************** + * Print (to stdout) info about this bloom filter. Debugging aid. + * + */ +void bloom_print(struct bloom * 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 bloom_free(struct bloom * 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 bloom_reset(struct bloom * bloom); + + +/** *************************************************************************** + * Returns version string compiled into library. + * + * Return: version string + * + */ +const char * bloom_version(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bloom/murmur2/MurmurHash2.c b/bloom/murmur2/MurmurHash2.c new file mode 100644 index 0000000..32c4c32 --- /dev/null +++ b/bloom/murmur2/MurmurHash2.c @@ -0,0 +1,64 @@ +//----------------------------------------------------------------------------- +// MurmurHash2, by Austin Appleby + +// Note - This code makes a few assumptions about how your machine behaves - + +// 1. We can read a 4-byte value from any address without crashing +// 2. sizeof(int) == 4 + +// And it has a few limitations - + +// 1. It will not work incrementally. +// 2. It will not produce the same results on little-endian and big-endian +// machines. + +unsigned int murmurhash2(const void * key, int len, const unsigned int seed) +{ + // 'm' and 'r' are mixing constants generated offline. + // They're not really 'magic', they just happen to work well. + + const unsigned int m = 0x5bd1e995; + const int r = 24; + + // Initialize the hash to a 'random' value + + unsigned int h = seed ^ len; + + // Mix 4 bytes at a time into the hash + + const unsigned char * data = (const unsigned char *)key; + + while(len >= 4) + { + unsigned int k = *(unsigned int *)data; + + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + + data += 4; + len -= 4; + } + + // Handle the last few bytes of the input array + + switch(len) + { + case 3: h ^= data[2] << 16; + case 2: h ^= data[1] << 8; + case 1: h ^= data[0]; + h *= m; + }; + + // Do a few final mixes of the hash to ensure the last few + // bytes are well-incorporated. + + h ^= h >> 13; + h *= m; + h ^= h >> 15; + + return h; +} diff --git a/bloom/murmur2/README b/bloom/murmur2/README new file mode 100644 index 0000000..ce24d71 --- /dev/null +++ b/bloom/murmur2/README @@ -0,0 +1,9 @@ + +MurmurHash2.c is taken from + +http://sites.google.com/site/murmurhash/ + +According to the above document: + + All code is released to the public domain. For business purposes, + Murmurhash is under the MIT license. diff --git a/bloom/murmur2/murmurhash2.h b/bloom/murmur2/murmurhash2.h new file mode 100644 index 0000000..e607381 --- /dev/null +++ b/bloom/murmur2/murmurhash2.h @@ -0,0 +1,7 @@ + +#ifndef _BLOOM_MURMURHASH2 +#define _BLOOM_MURMURHASH2 + +unsigned int murmurhash2(const void * key, int len, const unsigned int seed); + +#endif diff --git a/keyhunt.c b/keyhunt.c new file mode 100644 index 0000000..1eab136 --- /dev/null +++ b/keyhunt.c @@ -0,0 +1,1067 @@ +/* +gcc -O3 -c -o keyhunt.o keyhunt.c +gcc -O3 -c -o rmd160.o rmd160/rmd160.c +gcc -O3 -c -o sha256.o sha256/sha256.c + +gcc -o keyhunt keyhunt.o base58.o rmd160.o sha256.o bloom.o murmurhash2.o -lgmp -lm -lpthread +./keyhunt +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "base58/libbase58.h" +#include "rmd160/rmd160.h" +#include "sha256/sha256.h" +#include "bloom/bloom.h" +#include "util.h" + + +#define CRYPTO_NONE 0 +#define CRYPTO_BTC 1 +#define CRYPTO_ETH 2 +#define CRYPTO_ALL 3 + + +struct Point { + mpz_t x; + mpz_t y; +}; + +struct Elliptic_Curve { + mpz_t p; + mpz_t n; +}; + +struct tothread { + int nt; //Number thread + char *rs; //range start + char *rpt; //rng per thread +}; + +const char *version = "0.1.20201217"; +const char *EC_constant_N = "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"; +const char *EC_constant_P = "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"; +const char *EC_constant_Gx = "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"; +const char *EC_constant_Gy = "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"; +struct Point DoublingG[256]; + +void Point_Doubling(struct Point *P, struct Point *R); +void Point_Addition(struct Point *P, struct Point *Q, struct Point *R); +void Scalar_Multiplication(struct Point P, struct Point *R, mpz_t m); +void Point_Negation(struct Point A, struct Point *S); +int searchbinary(char *BUFFER,char *data,int length,int N); +void quicksort(char *arr, int low, int high); +int partition (char *arr, int low, int high); +void swap(char *a,char *b); + + +void *thread_process(void *vargp); +void *thread_process_range(void *vargp); + +void init_doublingG(struct Point *P); +char *pubkeytopubaddress(char *pkey,int length); +char *bit_range_str_min; +char *bit_range_str_max; + + + +const char *modes[2] = {"address","xpoint"}; +const char *cryptos[3] = {"btc","eth","all"}; +const char *default_filename = "addresses.txt"; + +pthread_t *tid = NULL; +pthread_mutex_t write_keys; +pthread_mutex_t write_range; +pthread_mutex_t write_random; + +struct Elliptic_Curve EC; +struct bloom bloom; +struct Point G; +unsigned int *steps = NULL; +unsigned int *ends = NULL; +char *DATABUFFER; +int N = 0; +gmp_randstate_t state; + +uint64_t N_SECUENTIAL_MAX = 0xffffffff; +int MAXLENGTHADDRESS = -1; +int NTHREADS = 1; +int DEBUGCOUNT = 0x100000; +int OUTPUTSECONDS = 30; +int FLAGBITRANGE = 0; +int FLAGRANGE = 0; +int FLAGHELP = 0; +int FLAGFILE = 0; +int FLAGVANITY = 0; +int FLAGMODE = 1; +int FLAGCRYPTO = 0; + +int len_vanity; +int bitrange; +char *vanity; +char *range_start; +char *range_end; + +int main(int argc, char **argv) { + struct tothread *tt; //tothread + Tokenizer t; //tokenizar + char *filename; + FILE *fd; + char *hextemp,*aux; + int readed,i,s,continue_flag,check_flag,r; + uint64_t total = 0; + uint32_t seconds = 0; + mpz_t n_range_start; + mpz_t n_range_end; + mpz_t n_range_diff; + mpz_t n_range_per_threads; + mpz_t n_range_aux; + mpz_t n_range_r; + int c; + + mpz_init_set_str(EC.p, EC_constant_P, 16); + mpz_init_set_str(EC.n, EC_constant_N, 16); + mpz_init_set_str(G.x , EC_constant_Gx, 16); + mpz_init_set_str(G.y , EC_constant_Gy, 16); + while ((c = getopt (argc, argv, "hb:c:f:g:m:r:R:s:t:v:")) != -1) { + switch(c) { + case 'h': + FLAGHELP = 1; + printf("keyhunt version %s\n\n",version); + printf("\nUsage:\n-h\t\tshow this help\n"); + printf("-b bits\t\tFor some puzzles you only need some numbers of bits in the test keys.\n"); + printf("\t\tThis option only is valid with the Random option -R\n"); + printf("-c crypto\tSearch for specific crypo. < btc, eth, all > default: btc valid only w/ -m address \n"); + printf("\t\teth option is under develop sorry :(\n"); + printf("-f filename\tfile name with addresses default: addresses.txt\n"); + printf("-g debugcount\tJust for the stats, mark as counted every debugcount keys default: 1048576\n"); + printf("-m mode\t\tmode of search for cryptos. < xpoint , address > default: address (more slow)\n"); + printf("-r SR:EN\tStarRange:EndRange, the end range can be omited for search from start range to N-1 ECC value\n"); + printf("-R upto\t\tRandom/Secuential this is the default behaivor, can't use this with range option -r\n"); + printf("\t\tupto is a Decimal number, this is how many secuential keys you want to test until next random, default: 4294967295\n"); + printf("-s ns\t\tNumber of seconds for the stats output, 0 to omit output, Default 30 seconds\n"); + printf("-t tn\t\tThreads number, must be positive integer, default : 1\n\n"); + printf("-v va\t\tSearch for vanity Address, only with -m address\n"); + printf("\nExample\n\n"); + printf("%s -t 16 -r 00000001:FFFFFFFF -s 0\n\n",argv[0]); + printf("This line run the program with 16 threads from the range 00000001 to FFFFFFFF without stats output\n\n"); + printf("Developed by AlbertoBSD\tTips BTC: 1H3TAVNZFZfiLUp9o9E93oTVY9WgYZ5knX\n\n"); + exit(0); + break; + case 'b': + bitrange = strtol(optarg,NULL,10); + if(bitrange > 0 && bitrange <=256 ) { + bit_range_str_min = malloc(bitrange+1); + bit_range_str_max = malloc(bitrange+1); + if(bit_range_str_min == NULL||bit_range_str_max == NULL) { + fprintf(stderr,"erorr malloc()\n"); + exit(0); + } + memset(bit_range_str_min,'1',bitrange); + memset(bit_range_str_max,'1',bitrange); + bit_range_str_min[0] = '0'; + printf("bit min range: %s\n",bit_range_str_min); + printf("bit max range: %s\n",bit_range_str_max); + FLAGBITRANGE = 1; + } + else { + printf("invalid bits param: %s\n",optarg); + } + break; + case 'c': + switch(indexOf(optarg,cryptos,3)) { + case 0: //btc + FLAGCRYPTO = CRYPTO_BTC; + printf("Setting search for btc adddress\n"); + break; + case 1: //eth + FLAGCRYPTO = CRYPTO_ETH; + printf("Setting search for eth adddress\n"); + break; + case 2: //all + FLAGCRYPTO = CRYPTO_ALL; + printf("Setting search for all cryptos\nFor each crypto there are many hash and base_algo operations and the performance down slow\n"); + break; + default: + FLAGCRYPTO = CRYPTO_NONE; + printf("Unknow crypto value %s\n",optarg); + break; + } + optarg; + break; + case 'f': + FLAGFILE = 1; + filename = optarg; + break; + case 'g': + DEBUGCOUNT = strtol(optarg,NULL,10); + if(DEBUGCOUNT == 0) { + DEBUGCOUNT = 0x100000; + fprintf(stderr,"invalid -g option value: %s\n",optarg); + } + break; + case 'm': + switch(indexOf(optarg,modes,2)) { + case 0: //xpoint + FLAGMODE = 0; + printf("Setting mode xpoint"); + break; + case 1: //address + FLAGMODE = 1; + printf("Setting mode address"); + break; + default: + FLAGMODE = 1; + printf("Unknow mode value %s\n",optarg); + break; + } + break; + case 'v': + FLAGVANITY = 1; + vanity = optarg; + len_vanity = strlen(optarg); + break; + case 'R': + N_SECUENTIAL_MAX = strtol(optarg,NULL,10); + if(N_SECUENTIAL_MAX == 0) { + N_SECUENTIAL_MAX = 0xFFFFFFFF; + } + break; + case 'r': + if(optarg != NULL) { + stringtokenizer(optarg,&t); + switch(t.n) { + case 1: + range_start = nextToken(&t); + if(isValidHex(range_start)) { + FLAGRANGE = 1; + range_end = (char*) EC_constant_N; + } + else { + printf("Invalid hexstring : %s\n",range_start); + } + break; + case 2: + range_start = nextToken(&t); + range_end = nextToken(&t); + if(isValidHex(range_start) && isValidHex(range_end)) { + FLAGRANGE = 1; + } + else { + if(isValidHex(range_start)) { + printf("Invalid hexstring : %s\n",range_start); + } + else { + printf("Invalid hexstring : %s\n",range_end); + } + } + break; + default: + printf("Unknow number of Range Params: %i\n",t.n); + break; + } + } + break; + case 's': + OUTPUTSECONDS = strtol(optarg,NULL,10); + if(OUTPUTSECONDS < 0) { + OUTPUTSECONDS = 30; + } + if(OUTPUTSECONDS == 0) { + printf("Turn off stats output\n"); + } + else { + printf("Stats output every %u seconds\n",OUTPUTSECONDS); + } + break; + case 't': + NTHREADS = strtol(optarg,NULL,10); + if(NTHREADS <= 0) { + NTHREADS = 1; + } + printf((NTHREADS > 1) ? "Setting %u threads\n": "Setting %u thread\n",NTHREADS); + break; + default: + printf("Unknow opcion %c\n",c); + if(optarg == NULL){ + printf("optarg es NULL\n"); + } + else { + printf("optarg No es NULL: %s\n",optarg); + } + break; + } + } + if(FLAGMODE == 1 && 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(FLAGFILE == 0) { + filename =(char*) default_filename; + } + if(FLAGRANGE) { + mpz_init_set_str(n_range_start,range_start,16); + mpz_init_set_str(n_range_end,range_end,16); + if(mpz_cmp(n_range_start,n_range_end) != 0 ) { + if(mpz_cmp(n_range_start,EC.n) < 0 && mpz_cmp(n_range_end,EC.n) <= 0) { + if(mpz_cmp(n_range_start,n_range_end) > 0) { + printf("Opps, start and range can't be great than End range. Swapping them\n"); + mpz_init_set(n_range_aux,n_range_start); + mpz_set(n_range_start,n_range_end); + mpz_set(n_range_end,n_range_aux); + mpz_clear(n_range_aux); + } + mpz_init(n_range_per_threads); + mpz_init(n_range_diff); + mpz_init(n_range_r); + mpz_sub(n_range_diff,n_range_end,n_range_start); + mpz_fdiv_q_ui(n_range_per_threads,n_range_diff,NTHREADS); + mpz_mod_ui(n_range_r,n_range_diff,NTHREADS); + } + else { + printf("Start and End range can't be great than N\nFallback to random mode!\n"); + FLAGRANGE = 0; + } + } + else { + printf("Start and End range can't be the same\nFallback to random mode!\n"); + FLAGRANGE = 0; + } + } + fd = fopen(filename,"rb"); + if(fd == NULL) { + fprintf(stderr,"cant open file %s\n",filename); + exit(0); + } + N =0; + aux = malloc(1000); + while(!feof(fd)) { + hextemp = fgets(aux,1000,fd); + if(hextemp == aux) { + trim(aux," \t\n\r"); + //printf("reading %s\n",aux); + r = strlen(aux); + if(r > 10) { //Any length for invalid Address? + if(r > MAXLENGTHADDRESS) { + MAXLENGTHADDRESS = r; + } + N++; + } + } + } + free(aux); + fseek(fd,0,SEEK_SET); + if(FLAGMODE == 0) { + MAXLENGTHADDRESS = 32; + } + do { + DATABUFFER = malloc(MAXLENGTHADDRESS*N); + } while(DATABUFFER == NULL); + //printf("Max address: %u\n",MAXLENGTHADDRESS); + printf("init bloom filter for %u elements\n",N); + if(bloom_init(&bloom,2*N,0.001) == 1){ + fprintf(stderr,"error bloom_init\n"); + exit(0); + } + printf("loading data and making bloomfilter\n"); + i = 0; + aux = malloc(2*MAXLENGTHADDRESS); + if(FLAGMODE) { //Address + while(i < N) { + memset(aux,0,2*MAXLENGTHADDRESS); + memset(DATABUFFER + (i*MAXLENGTHADDRESS),0,MAXLENGTHADDRESS); + hextemp = fgets(aux,2*MAXLENGTHADDRESS,fd); + if(hextemp == aux) { + trim(aux," \t\n\r"); + bloom_add(&bloom, aux,MAXLENGTHADDRESS); + memcpy(DATABUFFER + (i*MAXLENGTHADDRESS),aux,MAXLENGTHADDRESS); + i++; + } + else { + trim(aux," \t\n\r"); + printf("Omiting line : %s\n",aux); + } + } + } + else { + while(i < N) { + hextemp == fgets(aux,MAXLENGTHADDRESS,fd); + if(hextemp == aux) { + trim(aux," \t\n\r"); + memset(DATABUFFER + (i*MAXLENGTHADDRESS),0,MAXLENGTHADDRESS); + if(isValidHex(aux)) { + hexs2bin(aux,DATABUFFER + (i*MAXLENGTHADDRESS)); + } + else { + printf("Ignoring invalid hexvalue %s\nAre you sure that your file are X points?",aux); + } + bloom_add(&bloom, DATABUFFER + (i*MAXLENGTHADDRESS),MAXLENGTHADDRESS); + i++; + } + else { + trim(aux," \t\n\r"); + printf("Omiting line : %s\n",aux); + } + } + } + free(aux); + fclose(fd); + printf("bloomfilter completed\n"); + printf("sorting data\n"); + quicksort(DATABUFFER,0,N-1); + printf("%i values were loaded and sorted\n",N); + + init_doublingG(&G); + + if(FLAGRANGE == 0) { + gmp_randinit_mt(state); + gmp_randseed_ui(state, time(NULL)); + } + steps = (unsigned int *) calloc(NTHREADS,sizeof(int)); + ends = (unsigned int *) calloc(NTHREADS,sizeof(int)); + tid = (pthread_t *) calloc(NTHREADS,sizeof(pthread_t)); + if(FLAGRANGE == 0) { + for(i= 0;i < NTHREADS; i++) { + tt = malloc(sizeof(struct tothread)); + tt->nt = i; + steps[i] = 0; + s = pthread_create(&tid[i],NULL,thread_process,(void *)tt); + if(s != 0) { + fprintf(stderr,"error: pthread_create thread_process\n"); + } + } + } + else { + for(i= 0;i < NTHREADS; i++) { + if(i == (NTHREADS)-1) { + mpz_add(n_range_per_threads,n_range_per_threads,n_range_r); + } + tt = malloc(sizeof(struct tothread)); + tt->nt = i; + tt->rs = malloc(65); + mpz_get_str(tt->rs,16,n_range_start); + + tt->rpt = malloc(65); + mpz_get_str(tt->rpt,16,n_range_per_threads); + + steps[i] = 0; + s = pthread_create(&tid[i],NULL,thread_process_range,(void *)tt); + if(s != 0) { + fprintf(stderr,"error: pthread_create thread_process\n"); + } + mpz_add(n_range_start,n_range_start,n_range_per_threads); + } + } + if(FLAGRANGE) { + mpz_clear(n_range_per_threads); + mpz_clear(n_range_start); + mpz_clear(n_range_end); + mpz_clear(n_range_diff); + mpz_clear(n_range_r); + } + continue_flag = 1; + do { + sleep(1); + seconds+=1; + if(FLAGRANGE) { + check_flag = 1; + for(i = 0; i 0){ + if(seconds % OUTPUTSECONDS == 0) { + total = 0; + i = 0; + while(i < NTHREADS) { + total += steps[i] * DEBUGCOUNT; + i++; + } + printf("Total %lu keys in %u secods: %lu keys/s\n",total,seconds,(uint64_t) ((uint64_t)total/(uint64_t)seconds)); + } + } + }while(continue_flag); +} + +void Point_Doubling(struct Point *P, struct Point *R) { + mpz_t slope, temp; + mpz_init(temp); + mpz_init(slope); + if(mpz_cmp_ui(P->y, 0) != 0) { + mpz_mul_ui(temp, P->y, 2); + mpz_invert(temp, temp, EC.p); + mpz_mul(slope, P->x, P->x); + mpz_mul_ui(slope, slope, 3); + mpz_mul(slope, slope, temp); + mpz_mod(slope, slope, EC.p); + mpz_mul(R->x, slope, slope); + mpz_sub(R->x, R->x, P->x); + mpz_sub(R->x, R->x, P->x); + mpz_mod(R->x, R->x, EC.p); + mpz_sub(temp, P->x, R->x); + mpz_mul(R->y, slope, temp); + mpz_sub(R->y, R->y, P->y); + mpz_mod(R->y, R->y, EC.p); + } else { + mpz_set_ui(R->x, 0); + mpz_set_ui(R->y, 0); + } + mpz_clear(temp); + mpz_clear(slope); +} + +void Point_Addition(struct Point *P, struct Point *Q, struct Point *R) { + mpz_t PA_temp,PA_slope; + mpz_init(PA_temp); + mpz_init(PA_slope); + mpz_mod(Q->x, Q->x, EC.p); + mpz_mod(Q->y, Q->y, EC.p); + mpz_mod(P->x, P->x, EC.p); + mpz_mod(P->y, P->y, EC.p); + if(mpz_cmp_ui(P->x, 0) == 0 && mpz_cmp_ui(P->y, 0) == 0) { + mpz_set(R->x, Q->x); + mpz_set(R->y, Q->y); + } + else { + /* This is commented because Q never 0,0, always is kG point*/ + /* + if(mpz_cmp_ui(Q->x, 0) == 0 && mpz_cmp_ui(Q->y, 0) == 0) { + mpz_set(R->x, P->x); + mpz_set(R->y, P->y); + } + else { + */ + if(mpz_cmp_ui(Q->y, 0) != 0) { + mpz_sub(PA_temp, EC.p, Q->y); + mpz_mod(PA_temp, PA_temp, EC.p); + } + else { + mpz_set_ui(PA_temp, 0); + } + if(mpz_cmp(P->y, PA_temp) == 0 && mpz_cmp(P->x, Q->x) == 0) { + mpz_set_ui(R->x, 0); + mpz_set_ui(R->y, 0); + } + else { + if(mpz_cmp(P->x, Q->x) == 0 && mpz_cmp(P->y, Q->y) == 0) { + Point_Doubling(P, R); + } + else { + mpz_set_ui(PA_slope, 0); + mpz_sub(PA_temp, P->x, Q->x); + mpz_mod(PA_temp, PA_temp, EC.p); + mpz_invert(PA_temp, PA_temp, EC.p); + mpz_sub(PA_slope, P->y, Q->y); + mpz_mul(PA_slope, PA_slope, PA_temp); + mpz_mod(PA_slope, PA_slope, EC.p); + mpz_mul(R->x, PA_slope, PA_slope); + mpz_sub(R->x, R->x, P->x); + mpz_sub(R->x, R->x, Q->x); + mpz_mod(R->x, R->x, EC.p); + mpz_sub(PA_temp, P->x, R->x); + mpz_mul(R->y, PA_slope, PA_temp); + mpz_sub(R->y, R->y, P->y); + mpz_mod(R->y, R->y, EC.p); + } + } + //} + } + mpz_clear(PA_temp); + mpz_clear(PA_slope); +} + +void Scalar_Multiplication(struct Point P, struct Point *R, mpz_t m) { + char strtemp[65]; + struct Point SM_T,SM_Q; + long no_of_bits, i; + no_of_bits = mpz_sizeinbase(m, 2); + mpz_init_set_ui(SM_Q.x,0); + mpz_init_set_ui(SM_Q.y,0); + mpz_init_set_ui(SM_T.x,0); + mpz_init_set_ui(SM_T.y,0); + mpz_set_ui(R->x, 0); + mpz_set_ui(R->y, 0); + if(mpz_cmp_ui(m, 0) != 0) { + mpz_set(SM_Q.x, P.x); + mpz_set(SM_Q.y, P.y); + for(i = 0; i < no_of_bits; i++) { + if(mpz_tstbit(m, i)) { + mpz_set(SM_T.x, R->x); + mpz_set(SM_T.y, R->y); + mpz_set(SM_Q.x,DoublingG[i].x); + mpz_set(SM_Q.y,DoublingG[i].y); + Point_Addition(&SM_T, &SM_Q, R); + } + } + } + mpz_clear(SM_T.x); + mpz_clear(SM_T.y); + mpz_clear(SM_Q.x); + mpz_clear(SM_Q.y); +} + +void Point_Negation(struct Point A, struct Point *S) { + struct Point PN_Q; + mpz_t PN_temp; + mpz_init(PN_temp); + mpz_init(PN_Q.x); + mpz_init(PN_Q.y); + mpz_set(PN_Q.x, A.x); + mpz_set(PN_Q.y, A.y); + mpz_sub(PN_temp, EC.p, PN_Q.y); + mpz_set(S->x, PN_Q.x); + mpz_set(S->y, PN_temp); + mpz_clear(PN_temp); + mpz_clear(PN_Q.x); + mpz_clear(PN_Q.y); +} + +/* + Precalculate G Doublings for Scalar_Multiplication +*/ +void init_doublingG(struct Point *P) { + int i = 0; + mpz_init(DoublingG[i].x); + mpz_init(DoublingG[i].y); + mpz_set(DoublingG[i].x,P->x); + mpz_set(DoublingG[i].y,P->y); + i = 1; + while(i < 256){ + mpz_init(DoublingG[i].x); + mpz_init(DoublingG[i].y); + Point_Doubling(&DoublingG[i-1] ,&DoublingG[i]); + mpz_mod(DoublingG[i].x, DoublingG[i].x, EC.p); + mpz_mod(DoublingG[i].y, DoublingG[i].y, EC.p); + i++; + } +} + +char *pubkeytopubaddress(char *pkey,int length) { + char *pubaddress = calloc(MAXLENGTHADDRESS,1); + char *digest = malloc(60); + long unsigned int pubaddress_size = MAXLENGTHADDRESS; + if(pubaddress == NULL || digest == NULL) { + fprintf(stderr,"error malloc()\n"); + exit(0); + } + memset(digest,0,60); + //digest [000...0] + sha256(pkey, length, digest); + //digest [SHA256 32 bytes+000....0] + RMD160Data(digest,32, digest+1); + //digest [? +RMD160 20 bytes+????000....0] + digest[0] = 0; + //digest [0 +RMD160 20 bytes+????000....0] + sha256(digest, 21, digest+21); + //digest [0 +RMD160 20 bytes+SHA256 32 bytes+....0] + sha256(digest+21, 32, digest+21); + //digest [0 +RMD160 20 bytes+SHA256 32 bytes+....0] + b58enc(pubaddress,&pubaddress_size,digest,25); + free(digest); + return pubaddress; // pubaddress need to be free by te caller funtion +} + +int searchbinary(char *buffer,char *data,int length,int N) { + char *temp_read; + int r = 0,rcmp,current_offset,half,min,max,current; + min = 0; + current = 0; + max = N; + half = N; + //c =0; + while(!r && half >= 1) { + half = half/2; + temp_read = buffer + ((current+half) * length); + rcmp = memcmp(data,temp_read,length); + if(rcmp == 0) { + r = 1; //Found!! + } + else { + if(rcmp < 0) { //data < temp_read + max = (max-half-1); + } + else { // data > temp_read + min = (min+half+1); + } + current = min; + } + //c++; + } + //printf("Searchs %i\n",c); + return r; +} + +void *thread_process(void *vargp) { + struct tothread *tt; + struct Point R,temporal; + uint64_t count = 0; + int r,thread_number; + char *public_key_compressed,*public_key_uncompressed; + char *hextemp,*public_key_compressed_hex,*public_key_uncompressed_hex; + char *eth_address; + char *public_address_compressed,*public_address_uncompressed; + unsigned long longtemp; + FILE *keys,*range_file,*vanityKeys; + mpz_t random_key_mpz,mpz_bit_range_min,mpz_bit_range_max,mpz_bit_range_diff; + mpz_init(random_key_mpz); + mpz_init(R.x); + mpz_init(R.y); + mpz_init(temporal.x); + mpz_init(temporal.y); + if(FLAGBITRANGE) { + mpz_init_set_str(mpz_bit_range_min,bit_range_str_min,2); + mpz_init_set_str(mpz_bit_range_max,bit_range_str_max,2); + mpz_init(mpz_bit_range_diff); + mpz_sub(mpz_bit_range_diff,mpz_bit_range_max,mpz_bit_range_min); + } + public_key_compressed = malloc(33); + public_key_uncompressed = malloc(65); + tt = (struct tothread *)vargp; + thread_number = tt->nt; + free(tt); + if(public_key_compressed == NULL || public_key_uncompressed == NULL) { + fprintf(stderr,"error malloc!\n"); + exit(0); + } + do { + pthread_mutex_lock(&write_random); + if(FLAGBITRANGE) { + mpz_urandomm(random_key_mpz,state,mpz_bit_range_diff); + mpz_add(random_key_mpz,random_key_mpz,mpz_bit_range_min); + } + else { + mpz_urandomm(random_key_mpz,state,EC.n); + } + pthread_mutex_unlock(&write_random); + hextemp = malloc(65); + mpz_get_str(hextemp,16,random_key_mpz); + pthread_mutex_lock(&write_range); + printf("Thread %i : Setting up base key: %s\n",thread_number,hextemp); + range_file = fopen("./ranges.txt","a+"); + if(range_file != NULL) { + fprintf(range_file,"%s\n",hextemp); + fclose(range_file); + } + pthread_mutex_unlock(&write_range); + free(hextemp); + Scalar_Multiplication(G, &R, random_key_mpz); + count = 0; + public_key_uncompressed[0] = 0x04; + do { + mpz_set(temporal.x,R.x); + mpz_set(temporal.y,R.y); + mpz_export((public_key_compressed+1),&longtemp,1,8,1,0,R.x); + if(mpz_tstbit(R.y, 0) == 0) { // Even + public_key_compressed[0] = 0x02; + } + else { + public_key_compressed[0] = 0x03; + } + if(FLAGMODE ) { // FLAGMODE == 1 search for address but for what crypto ? + if( FLAGCRYPTO & CRYPTO_BTC != 0) { + mpz_export((public_key_uncompressed+1),&longtemp,1,8,1,0,R.x); + mpz_export((public_key_uncompressed+33),&longtemp,1,8,1,0,R.y); + public_address_compressed = pubkeytopubaddress(public_key_compressed,33); + public_address_uncompressed = pubkeytopubaddress(public_key_uncompressed,65); + if(FLAGVANITY) { + if(strncmp(public_address_uncompressed,vanity,len_vanity) == 0) { + hextemp = malloc(65); + mpz_get_str(hextemp,16,random_key_mpz); + vanityKeys = fopen("vanitykeys.txt","a+"); + if(vanityKeys != NULL) { + fprintf(vanityKeys,"PrivKey: %s\n%s\n",hextemp,public_address_uncompressed); + fclose(vanityKeys); + } + free(hextemp); + } + if(strncmp(public_address_compressed,vanity,len_vanity) == 0) { + hextemp = malloc(65); + mpz_get_str(hextemp,16,random_key_mpz); + vanityKeys = fopen("vanitykeys.txt","a+"); + if(vanityKeys != NULL) { + fprintf(vanityKeys,"PrivKey: %s\n%s\n",hextemp,public_address_compressed); + fclose(vanityKeys); + } + free(hextemp); + } + } + r = bloom_check(&bloom,public_address_compressed,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(DATABUFFER,public_address_compressed,MAXLENGTHADDRESS,N); + if(r) { + hextemp = malloc(65); + mpz_get_str(hextemp,16,random_key_mpz); + public_key_compressed_hex = tohex(public_key_compressed,33); + pthread_mutex_lock(&write_keys); + keys = fopen("keys.txt","a+"); + if(keys != NULL) { + fprintf(keys,"PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_compressed_hex,public_address_compressed); + fclose(keys); + } + printf("HIT!! PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_compressed_hex,public_address_compressed); + pthread_mutex_unlock(&write_keys); + free(public_key_compressed_hex); + free(hextemp); + } + } + + r = bloom_check(&bloom,public_address_uncompressed,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(DATABUFFER,public_address_uncompressed,MAXLENGTHADDRESS,N); + if(r) { + hextemp = malloc(65); + mpz_get_str(hextemp,16,random_key_mpz); + public_key_uncompressed_hex = tohex(public_key_uncompressed,65); + pthread_mutex_lock(&write_keys); + keys = fopen("keys.txt","a+"); + if(keys != NULL) { + fprintf(keys,"PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); + fclose(keys); + } + printf("HIT!! PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); + pthread_mutex_unlock(&write_keys); + free(public_key_uncompressed_hex); + free(hextemp); + } + } + free(public_address_compressed); + free(public_address_uncompressed); + } + if( FLAGCRYPTO & CRYPTO_ETH != 0) { + + } + } + else { //FLAGMODE == 0 + r = bloom_check(&bloom,public_key_compressed+1,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(DATABUFFER,public_key_compressed+1,MAXLENGTHADDRESS,N); + if(r) { + hextemp = malloc(65); + mpz_get_str(hextemp,16,random_key_mpz); + public_key_compressed_hex = tohex(public_key_compressed,33); + pthread_mutex_lock(&write_keys); + keys = fopen("./keys.txt","a+"); + if(keys != NULL) { + fprintf(keys,"PrivKey: %s\npubkey: %s\n",hextemp,public_key_compressed_hex); + fclose(keys); + } + printf("HIT!! PrivKey: %s\npubkey: %s\n",hextemp,public_key_compressed_hex); + pthread_mutex_unlock(&write_keys); + free(public_key_compressed_hex); + free(hextemp); + } + } + } + count++; + if(count % DEBUGCOUNT == 0) { + steps[thread_number]++; + } + mpz_add_ui(random_key_mpz,random_key_mpz,1); + Point_Addition(&temporal,&G,&R); + }while(count <= N_SECUENTIAL_MAX); + } while(1); + printf("Testing Keys %lu\n",count); +} + +void *thread_process_range(void *vargp) { + struct tothread *tt; + struct Point R,temporal; + uint64_t count = 0; + int r,thread_number; + char *public_key_compressed,*public_key_uncompressed; + char *hextemp,*public_key_compressed_hex,*public_key_uncompressed_hex; + char *eth_address; + char *public_address_compressed,*public_address_uncompressed; + unsigned long longtemp; + FILE *keys,*range_file,*vanityKeys; + mpz_t key_mpz,max_mpz; + mpz_init(R.x); + mpz_init(R.y); + mpz_init(temporal.x); + mpz_init(temporal.y); + tt = (struct tothread *) vargp; + thread_number = tt->nt; + + mpz_init_set_str(key_mpz,tt->rs,16); + mpz_init_set_str(max_mpz,tt->rpt,16); + mpz_add(max_mpz,key_mpz,max_mpz); + + public_key_compressed = malloc(33); + public_key_uncompressed = malloc(65); + + if(public_key_compressed == NULL || public_key_uncompressed == NULL) { + fprintf(stderr,"error malloc!\n"); + exit(0); + } + printf("Thread %i : Setting up base key: %s\n",thread_number,tt->rs); + pthread_mutex_lock(&write_range); + range_file = fopen("./ranges.txt","a+"); + if(range_file != NULL) { + fprintf(range_file,"%s\n",tt->rs); + fclose(range_file); + } + pthread_mutex_unlock(&write_range); + free(tt->rs); + free(tt->rpt); + free(tt); + Scalar_Multiplication(G, &R, key_mpz); + + + public_key_uncompressed[0] = 0x04; + count = 0; + + while(mpz_cmp(key_mpz,max_mpz) < 0 ) { + mpz_set(temporal.x,R.x); + mpz_set(temporal.y,R.y); + mpz_export((public_key_compressed+1),&longtemp,1,8,1,0,R.x); + if(mpz_tstbit(R.y, 0) == 0) { // Even + public_key_compressed[0] = 0x02; + } + else { + public_key_compressed[0] = 0x03; + } + if(FLAGMODE) { // FLAGMODE == 1 + if( FLAGCRYPTO & CRYPTO_BTC != 0) { + mpz_export((public_key_uncompressed+1),&longtemp,1,8,1,0,R.x); + mpz_export((public_key_uncompressed+33),&longtemp,1,8,1,0,R.y); + public_address_compressed = pubkeytopubaddress(public_key_compressed,33); + public_address_uncompressed = pubkeytopubaddress(public_key_uncompressed,65); + if(FLAGVANITY) { + if(strncmp(public_address_uncompressed,vanity,len_vanity) == 0) { + hextemp = malloc(65); + mpz_get_str(hextemp,16,key_mpz); + vanityKeys = fopen("vanitykeys.txt","a+"); + if(vanityKeys != NULL) { + fprintf(vanityKeys,"PrivKey: %s\n%s\n",hextemp,public_address_uncompressed); + fclose(vanityKeys); + } + free(hextemp); + } + if(strncmp(public_address_compressed,vanity,len_vanity) == 0) { + hextemp = malloc(65); + mpz_get_str(hextemp,16,key_mpz); + vanityKeys = fopen("vanitykeys.txt","a+"); + if(vanityKeys != NULL) { + fprintf(vanityKeys,"PrivKey: %s\n%s\n",hextemp,public_address_compressed); + fclose(vanityKeys); + } + free(hextemp); + } + } + r = bloom_check(&bloom,public_address_compressed,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(DATABUFFER,public_address_compressed,MAXLENGTHADDRESS,N); + if(r) { + hextemp = malloc(65); + mpz_get_str(hextemp,16,key_mpz); + public_key_compressed_hex = tohex(public_key_compressed,33); + pthread_mutex_lock(&write_keys); + keys = fopen("keys.txt","a+"); + if(keys != NULL) { + fprintf(keys,"PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_compressed_hex,public_address_compressed); + fclose(keys); + } + printf("HIT!! PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_compressed_hex,public_address_compressed); + pthread_mutex_unlock(&write_keys); + free(public_key_compressed_hex); + free(hextemp); + } + } + r = bloom_check(&bloom,public_address_uncompressed,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(DATABUFFER,public_address_uncompressed,MAXLENGTHADDRESS,N); + if(r) { + hextemp = malloc(65); + mpz_get_str(hextemp,16,key_mpz); + public_key_uncompressed_hex = tohex(public_key_uncompressed,65); + pthread_mutex_lock(&write_keys); + keys = fopen("keys.txt","a+"); + if(keys != NULL) { + fprintf(keys,"PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); + fclose(keys); + } + printf("HIT!! PrivKey: %s\npubkey: %s\naddress: %s\n",hextemp,public_key_uncompressed_hex,public_address_uncompressed); + pthread_mutex_unlock(&write_keys); + free(public_key_uncompressed_hex); + free(hextemp); + } + } + free(public_address_compressed); + free(public_address_uncompressed); + } + if( ( FLAGCRYPTO & CRYPTO_ETH ) != 0) { + + } + } + else { // FLAGMODE == 0 + r = bloom_check(&bloom,public_key_compressed+1,MAXLENGTHADDRESS); + if(r) { + r = searchbinary(DATABUFFER,public_key_compressed+1,MAXLENGTHADDRESS,N); + if(r) { + hextemp = malloc(65); + mpz_get_str(hextemp,16,key_mpz); + public_key_compressed_hex = tohex(public_key_compressed,33); + pthread_mutex_lock(&write_keys); + keys = fopen("./keys.txt","a+"); + if(keys != NULL) { + fprintf(keys,"PrivKey: %s\npubkey: %s\n",hextemp,public_key_compressed_hex); + fclose(keys); + } + printf("HIT!! PrivKey: %s\npubkey: %s\n",hextemp,public_key_compressed_hex); + pthread_mutex_unlock(&write_keys); + free(public_key_compressed_hex); + free(hextemp); + } + } + } + count++; + if(count % DEBUGCOUNT == 0) { + steps[thread_number]++; + } + mpz_add_ui(key_mpz,key_mpz,1); + Point_Addition(&temporal,&G,&R); + } + printf("Testing Keys %lu\n",count); + ends[thread_number] = 1; +} + +void swap(char *a,char *b) { + char t[MAXLENGTHADDRESS]; + memcpy(t,a,MAXLENGTHADDRESS); + memcpy(a,b,MAXLENGTHADDRESS); + memcpy(b,t,MAXLENGTHADDRESS); +} + +int partition (char *arr, int low, int high) { + char *pivot = arr + (high*MAXLENGTHADDRESS); // pivot + //printf("Pivot : %s\n",pivot); + int j,i = (low - 1); // Index of smaller element + for (j = low; j < high; j++) { + // If current element is smaller than the pivot + if (memcmp(arr + (j*MAXLENGTHADDRESS),pivot,MAXLENGTHADDRESS) < 0) { + i++; // increment index of smaller element + swap(arr + (i*MAXLENGTHADDRESS), arr + (j*MAXLENGTHADDRESS)); + } + } + swap(arr + ((i+1)*MAXLENGTHADDRESS), arr + (high*MAXLENGTHADDRESS)); + return (i + 1); +} + +void quicksort(char *arr, int low, int high) { + int pi; + if (low < high) { + //putc('.',stdout); + pi = partition(arr, low, high); + quicksort(arr, low, pi - 1); + quicksort(arr, pi + 1, high); + } +} diff --git a/rmd160/rmd160.c b/rmd160/rmd160.c new file mode 100644 index 0000000..ad257f0 --- /dev/null +++ b/rmd160/rmd160.c @@ -0,0 +1,450 @@ +/* + * RIPEMD160.c - European RIPE Message Digest, 160 bit (RIPEMD-160) + * + * The algorithm is by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel. + * + * The code below is based on the reference implementation by Bosselaers. + * It is available at the time of writing from + * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html + * + * Hacked for use in libmd by Martin Hinner + */ + +#include + +#include "rmd160.h" + +/* macro definitions */ + +/* ROL(x, n) cyclically rotates x over n bits to the left */ +/* x must be of an unsigned 32 bits type and 0 <= n < 32. */ +#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* the three basic functions F(), G() and H() */ +#define F(x, y, z) ((x) ^ (y) ^ (z)) +#define G(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define H(x, y, z) (((x) | ~(y)) ^ (z)) +#define I(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define J(x, y, z) ((x) ^ ((y) | ~(z))) + +/* the eight basic operations FF() through III() */ +#define FF(a, b, c, d, e, x, s) {\ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } + +#define GG(a, b, c, d, e, x, s) {\ + (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } + +#define HH(a, b, c, d, e, x, s) {\ + (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } + +#define II(a, b, c, d, e, x, s) {\ + (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } + +#define JJ(a, b, c, d, e, x, s) {\ + (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } + +#define FFF(a, b, c, d, e, x, s) {\ + (a) += F((b), (c), (d)) + (x);\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } + +#define GGG(a, b, c, d, e, x, s) {\ + (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } + +#define HHH(a, b, c, d, e, x, s) {\ + (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } + +#define III(a, b, c, d, e, x, s) {\ + (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } + +#define JJJ(a, b, c, d, e, x, s) {\ + (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\ + (a) = ROL((a), (s)) + (e);\ + (c) = ROL((c), 10);\ + } + +/* + initializes MDbuffer to "magic constants" + */ +static void +RMDinit (u_int32_t * MDbuf) +{ + MDbuf[0] = 0x67452301UL; + MDbuf[1] = 0xefcdab89UL; + MDbuf[2] = 0x98badcfeUL; + MDbuf[3] = 0x10325476UL; + MDbuf[4] = 0xc3d2e1f0UL; +} + + +/* + the compression function. + transforms MDbuf using message bytes X[0] through X[15] + */ +static void +RMDcompress (u_int32_t * MDbuf, u_int32_t * X) +{ + u_int32_t aa = MDbuf[0], bb = MDbuf[1], cc = MDbuf[2], + dd = MDbuf[3], ee = MDbuf[4]; + u_int32_t aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2], + ddd = MDbuf[3], eee = MDbuf[4]; + + +/* round 1 */ + FF (aa, bb, cc, dd, ee, X[0], 11); + FF (ee, aa, bb, cc, dd, X[1], 14); + FF (dd, ee, aa, bb, cc, X[2], 15); + FF (cc, dd, ee, aa, bb, X[3], 12); + FF (bb, cc, dd, ee, aa, X[4], 5); + FF (aa, bb, cc, dd, ee, X[5], 8); + FF (ee, aa, bb, cc, dd, X[6], 7); + FF (dd, ee, aa, bb, cc, X[7], 9); + FF (cc, dd, ee, aa, bb, X[8], 11); + FF (bb, cc, dd, ee, aa, X[9], 13); + FF (aa, bb, cc, dd, ee, X[10], 14); + FF (ee, aa, bb, cc, dd, X[11], 15); + FF (dd, ee, aa, bb, cc, X[12], 6); + FF (cc, dd, ee, aa, bb, X[13], 7); + FF (bb, cc, dd, ee, aa, X[14], 9); + FF (aa, bb, cc, dd, ee, X[15], 8); + +/* round 2 */ + GG (ee, aa, bb, cc, dd, X[7], 7); + GG (dd, ee, aa, bb, cc, X[4], 6); + GG (cc, dd, ee, aa, bb, X[13], 8); + GG (bb, cc, dd, ee, aa, X[1], 13); + GG (aa, bb, cc, dd, ee, X[10], 11); + GG (ee, aa, bb, cc, dd, X[6], 9); + GG (dd, ee, aa, bb, cc, X[15], 7); + GG (cc, dd, ee, aa, bb, X[3], 15); + GG (bb, cc, dd, ee, aa, X[12], 7); + GG (aa, bb, cc, dd, ee, X[0], 12); + GG (ee, aa, bb, cc, dd, X[9], 15); + GG (dd, ee, aa, bb, cc, X[5], 9); + GG (cc, dd, ee, aa, bb, X[2], 11); + GG (bb, cc, dd, ee, aa, X[14], 7); + GG (aa, bb, cc, dd, ee, X[11], 13); + GG (ee, aa, bb, cc, dd, X[8], 12); + +/* round 3 */ + HH (dd, ee, aa, bb, cc, X[3], 11); + HH (cc, dd, ee, aa, bb, X[10], 13); + HH (bb, cc, dd, ee, aa, X[14], 6); + HH (aa, bb, cc, dd, ee, X[4], 7); + HH (ee, aa, bb, cc, dd, X[9], 14); + HH (dd, ee, aa, bb, cc, X[15], 9); + HH (cc, dd, ee, aa, bb, X[8], 13); + HH (bb, cc, dd, ee, aa, X[1], 15); + HH (aa, bb, cc, dd, ee, X[2], 14); + HH (ee, aa, bb, cc, dd, X[7], 8); + HH (dd, ee, aa, bb, cc, X[0], 13); + HH (cc, dd, ee, aa, bb, X[6], 6); + HH (bb, cc, dd, ee, aa, X[13], 5); + HH (aa, bb, cc, dd, ee, X[11], 12); + HH (ee, aa, bb, cc, dd, X[5], 7); + HH (dd, ee, aa, bb, cc, X[12], 5); + +/* round 4 */ + II (cc, dd, ee, aa, bb, X[1], 11); + II (bb, cc, dd, ee, aa, X[9], 12); + II (aa, bb, cc, dd, ee, X[11], 14); + II (ee, aa, bb, cc, dd, X[10], 15); + II (dd, ee, aa, bb, cc, X[0], 14); + II (cc, dd, ee, aa, bb, X[8], 15); + II (bb, cc, dd, ee, aa, X[12], 9); + II (aa, bb, cc, dd, ee, X[4], 8); + II (ee, aa, bb, cc, dd, X[13], 9); + II (dd, ee, aa, bb, cc, X[3], 14); + II (cc, dd, ee, aa, bb, X[7], 5); + II (bb, cc, dd, ee, aa, X[15], 6); + II (aa, bb, cc, dd, ee, X[14], 8); + II (ee, aa, bb, cc, dd, X[5], 6); + II (dd, ee, aa, bb, cc, X[6], 5); + II (cc, dd, ee, aa, bb, X[2], 12); + +/* round 5 */ + JJ (bb, cc, dd, ee, aa, X[4], 9); + JJ (aa, bb, cc, dd, ee, X[0], 15); + JJ (ee, aa, bb, cc, dd, X[5], 5); + JJ (dd, ee, aa, bb, cc, X[9], 11); + JJ (cc, dd, ee, aa, bb, X[7], 6); + JJ (bb, cc, dd, ee, aa, X[12], 8); + JJ (aa, bb, cc, dd, ee, X[2], 13); + JJ (ee, aa, bb, cc, dd, X[10], 12); + JJ (dd, ee, aa, bb, cc, X[14], 5); + JJ (cc, dd, ee, aa, bb, X[1], 12); + JJ (bb, cc, dd, ee, aa, X[3], 13); + JJ (aa, bb, cc, dd, ee, X[8], 14); + JJ (ee, aa, bb, cc, dd, X[11], 11); + JJ (dd, ee, aa, bb, cc, X[6], 8); + JJ (cc, dd, ee, aa, bb, X[15], 5); + JJ (bb, cc, dd, ee, aa, X[13], 6); + +/* parallel round 1 */ + JJJ (aaa, bbb, ccc, ddd, eee, X[5], 8); + JJJ (eee, aaa, bbb, ccc, ddd, X[14], 9); + JJJ (ddd, eee, aaa, bbb, ccc, X[7], 9); + JJJ (ccc, ddd, eee, aaa, bbb, X[0], 11); + JJJ (bbb, ccc, ddd, eee, aaa, X[9], 13); + JJJ (aaa, bbb, ccc, ddd, eee, X[2], 15); + JJJ (eee, aaa, bbb, ccc, ddd, X[11], 15); + JJJ (ddd, eee, aaa, bbb, ccc, X[4], 5); + JJJ (ccc, ddd, eee, aaa, bbb, X[13], 7); + JJJ (bbb, ccc, ddd, eee, aaa, X[6], 7); + JJJ (aaa, bbb, ccc, ddd, eee, X[15], 8); + JJJ (eee, aaa, bbb, ccc, ddd, X[8], 11); + JJJ (ddd, eee, aaa, bbb, ccc, X[1], 14); + JJJ (ccc, ddd, eee, aaa, bbb, X[10], 14); + JJJ (bbb, ccc, ddd, eee, aaa, X[3], 12); + JJJ (aaa, bbb, ccc, ddd, eee, X[12], 6); + +/* parallel round 2 */ + III (eee, aaa, bbb, ccc, ddd, X[6], 9); + III (ddd, eee, aaa, bbb, ccc, X[11], 13); + III (ccc, ddd, eee, aaa, bbb, X[3], 15); + III (bbb, ccc, ddd, eee, aaa, X[7], 7); + III (aaa, bbb, ccc, ddd, eee, X[0], 12); + III (eee, aaa, bbb, ccc, ddd, X[13], 8); + III (ddd, eee, aaa, bbb, ccc, X[5], 9); + III (ccc, ddd, eee, aaa, bbb, X[10], 11); + III (bbb, ccc, ddd, eee, aaa, X[14], 7); + III (aaa, bbb, ccc, ddd, eee, X[15], 7); + III (eee, aaa, bbb, ccc, ddd, X[8], 12); + III (ddd, eee, aaa, bbb, ccc, X[12], 7); + III (ccc, ddd, eee, aaa, bbb, X[4], 6); + III (bbb, ccc, ddd, eee, aaa, X[9], 15); + III (aaa, bbb, ccc, ddd, eee, X[1], 13); + III (eee, aaa, bbb, ccc, ddd, X[2], 11); + +/* parallel round 3 */ + HHH (ddd, eee, aaa, bbb, ccc, X[15], 9); + HHH (ccc, ddd, eee, aaa, bbb, X[5], 7); + HHH (bbb, ccc, ddd, eee, aaa, X[1], 15); + HHH (aaa, bbb, ccc, ddd, eee, X[3], 11); + HHH (eee, aaa, bbb, ccc, ddd, X[7], 8); + HHH (ddd, eee, aaa, bbb, ccc, X[14], 6); + HHH (ccc, ddd, eee, aaa, bbb, X[6], 6); + HHH (bbb, ccc, ddd, eee, aaa, X[9], 14); + HHH (aaa, bbb, ccc, ddd, eee, X[11], 12); + HHH (eee, aaa, bbb, ccc, ddd, X[8], 13); + HHH (ddd, eee, aaa, bbb, ccc, X[12], 5); + HHH (ccc, ddd, eee, aaa, bbb, X[2], 14); + HHH (bbb, ccc, ddd, eee, aaa, X[10], 13); + HHH (aaa, bbb, ccc, ddd, eee, X[0], 13); + HHH (eee, aaa, bbb, ccc, ddd, X[4], 7); + HHH (ddd, eee, aaa, bbb, ccc, X[13], 5); + +/* parallel round 4 */ + GGG (ccc, ddd, eee, aaa, bbb, X[8], 15); + GGG (bbb, ccc, ddd, eee, aaa, X[6], 5); + GGG (aaa, bbb, ccc, ddd, eee, X[4], 8); + GGG (eee, aaa, bbb, ccc, ddd, X[1], 11); + GGG (ddd, eee, aaa, bbb, ccc, X[3], 14); + GGG (ccc, ddd, eee, aaa, bbb, X[11], 14); + GGG (bbb, ccc, ddd, eee, aaa, X[15], 6); + GGG (aaa, bbb, ccc, ddd, eee, X[0], 14); + GGG (eee, aaa, bbb, ccc, ddd, X[5], 6); + GGG (ddd, eee, aaa, bbb, ccc, X[12], 9); + GGG (ccc, ddd, eee, aaa, bbb, X[2], 12); + GGG (bbb, ccc, ddd, eee, aaa, X[13], 9); + GGG (aaa, bbb, ccc, ddd, eee, X[9], 12); + GGG (eee, aaa, bbb, ccc, ddd, X[7], 5); + GGG (ddd, eee, aaa, bbb, ccc, X[10], 15); + GGG (ccc, ddd, eee, aaa, bbb, X[14], 8); + +/* parallel round 5 */ + FFF (bbb, ccc, ddd, eee, aaa, X[12], 8); + FFF (aaa, bbb, ccc, ddd, eee, X[15], 5); + FFF (eee, aaa, bbb, ccc, ddd, X[10], 12); + FFF (ddd, eee, aaa, bbb, ccc, X[4], 9); + FFF (ccc, ddd, eee, aaa, bbb, X[1], 12); + FFF (bbb, ccc, ddd, eee, aaa, X[5], 5); + FFF (aaa, bbb, ccc, ddd, eee, X[8], 14); + FFF (eee, aaa, bbb, ccc, ddd, X[7], 6); + FFF (ddd, eee, aaa, bbb, ccc, X[6], 8); + FFF (ccc, ddd, eee, aaa, bbb, X[2], 13); + FFF (bbb, ccc, ddd, eee, aaa, X[13], 6); + FFF (aaa, bbb, ccc, ddd, eee, X[14], 5); + FFF (eee, aaa, bbb, ccc, ddd, X[0], 15); + FFF (ddd, eee, aaa, bbb, ccc, X[3], 13); + FFF (ccc, ddd, eee, aaa, bbb, X[9], 11); + FFF (bbb, ccc, ddd, eee, aaa, X[11], 11); + +/* combine results */ + ddd += cc + MDbuf[1]; /* final result for MDbuf[0] */ + MDbuf[1] = MDbuf[2] + dd + eee; + MDbuf[2] = MDbuf[3] + ee + aaa; + MDbuf[3] = MDbuf[4] + aa + bbb; + MDbuf[4] = MDbuf[0] + bb + ccc; + MDbuf[0] = ddd; +} + + +/* + puts bytes from strptr into X and pad out; appends length + and finally, compresses the last block(s) + note: length in bits == 8 * (lswlen + 2^32 mswlen). + note: there are (lswlen mod 64) bytes left in strptr. + */ +static void +RMDFinish (u_int32_t * MDbuf, u_int8_t * strptr, u_int32_t lswlen, + u_int32_t mswlen) +{ + u_int32_t i; /* counter */ + u_int32_t X[16]; /* message words */ + + memset (X, 0, 16 * sizeof (u_int32_t)); + +/* put bytes from strptr into X */ + for (i = 0; i < (lswlen & 63); i++) + { + /* byte i goes into word X[i div 4] at pos. 8*(i mod 4) */ + X[i >> 2] ^= (u_int32_t) * strptr++ << (8 * (i & 3)); + } + + /* append the bit m_n == 1 */ + X[(lswlen >> 2) & 15] ^= (u_int32_t) 1 << (8 * (lswlen & 3) + 7); + + if ((lswlen & 63) > 55) + { + /* length goes to next block */ + RMDcompress (MDbuf, X); + memset (X, 0, 16 * sizeof (u_int32_t)); + } + + /* append length in bits */ + X[14] = lswlen << 3; + X[15] = (lswlen >> 29) | (mswlen << 3); + RMDcompress (MDbuf, X); +} + +/* + Shuffle the bytes into little-endian order within words, as per the + RIPEMD-160 spec (which follows MD4 conventions). + */ +static void +rmd160ByteSwap (u_int32_t * dest, u_int8_t const *src, unsigned int words) +{ + do + { + *dest++ = (u_int32_t) ((unsigned) src[3] << 8 | src[2]) << 16 | + ((unsigned) src[1] << 8 | src[0]); + src += 4; + } + while (--words); +} + + +/* + Initialize the RIPEMD-160 values + */ +void +RMD160Init (RMD160_CTX * ctx) +{ + /* Set the h-vars to their initial values */ + RMDinit (ctx->iv); + + /* Initialise bit count */ + ctx->bytesHi = 0; + ctx->bytesLo = 0; +} + +/* + Update the RIPEMD-160 hash state for a block of data. + */ +void RMD160Update(RMD160_CTX *ctx, const unsigned char *buf, unsigned int len) +{ + unsigned i; + + /* Update bitcount */ + u_int32_t t = ctx->bytesLo; + if ((ctx->bytesLo = t + len) < t) + ctx->bytesHi++; /* Carry from low to high */ + + i = (unsigned) t % RIPEMD160_BLOCKBYTES; /* Bytes already in ctx->key */ + + /* i is always less than RIPEMD160_BLOCKBYTES. */ + if (RIPEMD160_BLOCKBYTES - i > len) + { + memcpy ((u_int8_t *) ctx->key + i, buf, len); + return; + } + + if (i) + { /* First chunk is an odd size */ + memcpy ((u_int8_t *) ctx->key + i, buf, RIPEMD160_BLOCKBYTES - i); + rmd160ByteSwap (ctx->key, (u_int8_t *) ctx->key, RIPEMD160_BLOCKWORDS); + RMDcompress (ctx->iv, ctx->key); + buf += RIPEMD160_BLOCKBYTES - i; + len -= RIPEMD160_BLOCKBYTES - i; + } + + /* Process data in 64-byte chunks */ + while (len >= RIPEMD160_BLOCKBYTES) + { + rmd160ByteSwap (ctx->key, buf, RIPEMD160_BLOCKWORDS); + RMDcompress (ctx->iv, ctx->key); + buf += RIPEMD160_BLOCKBYTES; + len -= RIPEMD160_BLOCKBYTES; + } + + /* Handle any remaining bytes of data. */ + if (len) + memcpy (ctx->key, buf, len); +} + + +/* + Final wrapup - MD4 style padding on last block. + */ +void +RMD160Final (unsigned char digest[20], RMD160_CTX * ctx) +{ + int i; + u_int32_t t; + + RMDFinish (ctx->iv, (u_int8_t *) ctx->key, ctx->bytesLo, ctx->bytesHi); + + for (i = 0; i < RIPEMD160_HASHWORDS; i++) + { + t = ctx->iv[i]; + digest[i * 4 + 0] = (u_int8_t) t; + digest[i * 4 + 1] = (u_int8_t) (t >> 8); + digest[i * 4 + 2] = (u_int8_t) (t >> 16); + digest[i * 4 + 3] = (u_int8_t) (t >> 24); + } + + memset (ctx, 0, sizeof (RMD160_CTX)); /* In case it's sensitive */ +} + +void RMD160Data(const unsigned char *buf, unsigned int len, char *out) { + RMD160_CTX ctx; + RMD160Init(&ctx); + RMD160Update(&ctx,(unsigned char *)buf,len); + RMD160Final((unsigned char *)out,&ctx); +} diff --git a/rmd160/rmd160.h b/rmd160/rmd160.h new file mode 100644 index 0000000..7980015 --- /dev/null +++ b/rmd160/rmd160.h @@ -0,0 +1,41 @@ +/* RMD160.H - header file for RMD160.C + */ +#ifndef _RMD160_H_ +#define _RMD160_H_ + +#include + +#define RMD160_BLOCKBYTES 64 +#define RMD160_BLOCKWORDS 16 + +#define RMD160_HASHBYTES 20 +#define RMD160_HASHWORDS 5 + +/* For compatibility */ +#define RIPEMD160_BLOCKBYTES 64 +#define RIPEMD160_BLOCKWORDS 16 + +#define RIPEMD160_HASHBYTES 20 +#define RIPEMD160_HASHWORDS 5 + +/* RIPEMD160 context. */ +typedef struct RMD160Context { + u_int32_t key[RIPEMD160_BLOCKWORDS]; + u_int32_t iv[RIPEMD160_HASHWORDS]; + u_int32_t bytesHi, bytesLo; +} RMD160_CTX; + +#define RIPEMD160Context RMD160Context + +#include + +__BEGIN_DECLS +void RMD160Init(RMD160_CTX *); +void RMD160Update(RMD160_CTX *, const unsigned char *, unsigned int); +void RMD160Final(unsigned char [RMD160_HASHBYTES], RMD160_CTX *); +char * RMD160End(RMD160_CTX *, char *); +char * RMD160File(const char *, char *); +void RMD160Data(const unsigned char *, unsigned int, char *); +__END_DECLS + +#endif /* _RMD160_H_ */ diff --git a/sha256/sha256.c b/sha256/sha256.c new file mode 100644 index 0000000..6b1c579 --- /dev/null +++ b/sha256/sha256.c @@ -0,0 +1,142 @@ +/* + SHA256 implementation, source file. + + This implementation was written by Kent "ethereal" Williams-King and is + hereby released into the public domain. Do what you wish with it. + + No guarantees as to the correctness of the implementation are provided. +*/ + +#include +#include + +const uint32_t sha256_initial_h[8] + = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; + +const uint32_t sha256_round_k[64] + = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, + 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, + 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, + 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, + 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, + 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; + +void sha256_endian_reverse64(uint64_t input, uint8_t *output) { + output[7] = (input >> 0) & 0xff; + output[6] = (input >> 8) & 0xff; + output[5] = (input >> 16) & 0xff; + output[4] = (input >> 24) & 0xff; + output[3] = (input >> 32) & 0xff; + output[2] = (input >> 40) & 0xff; + output[1] = (input >> 48) & 0xff; + output[0] = (input >> 56) & 0xff; +} + +uint32_t sha256_endian_read32(uint8_t *input) { + uint32_t output = 0; + output |= (input[0] << 24); + output |= (input[1] << 16); + output |= (input[2] << 8); + output |= (input[3] << 0); + + return output; +} + +void sha256_endian_reverse32(uint32_t input, uint8_t *output) { + output[3] = (input >> 0) & 0xff; + output[2] = (input >> 8) & 0xff; + output[1] = (input >> 16) & 0xff; + output[0] = (input >> 24) & 0xff; +} + +uint32_t sha256_ror(uint32_t input, uint32_t by) { + return (input >> by) | (((input & ((1 << by) - 1))) << (32 - by)); +} + +void sha256(const void *data, uint64_t len, void *output) { + uint8_t padding[80]; + uint64_t current = (len + 1) % 64; + // want to be == 56 % 64. + uint64_t needed = (64 + 56 - current) % 64; + uint64_t extra = needed + 9; + uint64_t total = len + extra; + + for(int i = 1; i < 80; i++) + padding[i] = 0; + padding[0] = 0x80; + sha256_endian_reverse64(len * 8, padding + total - len - 8); + + uint32_t v[8]; + for(int i = 0; i < 8; i++) + v[i] = sha256_initial_h[i]; + + for(uint64_t cursor = 0; cursor * 64 < total; cursor++) { + uint32_t t[8]; + for(int i = 0; i < 8; i++) + t[i] = v[i]; + + uint32_t w[64]; + if(cursor * 64 + 64 <= len) { + for(int j = 0; j < 16; j++) { + w[j] = sha256_endian_read32( + (uint8_t *)data + cursor * 64 + j * 4); + } + } + else { + if(cursor * 64 < len) { + uint64_t size = len - cursor * 64; + if(size > 0) memcpy(w, (uint8_t *)data + cursor * 64, size); + memcpy((uint8_t *)w + size, padding, 64 - size); + } + else { + uint64_t off = (cursor * 64 - len) % 64; + memcpy((uint8_t *)w, padding + off, 64); + } + + for(int j = 0; j < 16; j++) { + w[j] = sha256_endian_read32((uint8_t *)&w[j]); + } + } + + for(int j = 16; j < 64; j++) { + uint32_t s1 = sha256_ror(w[j - 2], 17) ^ sha256_ror(w[j - 2], 19) + ^ (w[j - 2] >> 10); + uint32_t s0 = sha256_ror(w[j - 15], 7) ^ sha256_ror(w[j - 15], 18) + ^ (w[j - 15] >> 3); + w[j] = s1 + w[j - 7] + s0 + w[j - 16]; + } + + for(int j = 0; j < 64; j++) { + uint32_t ch = (t[4] & t[5]) ^ (~t[4] & t[6]); + uint32_t maj = (t[0] & t[1]) ^ (t[0] & t[2]) ^ (t[1] & t[2]); + uint32_t S0 = sha256_ror(t[0], 2) ^ sha256_ror(t[0], 13) + ^ sha256_ror(t[0], 22); + uint32_t S1 = sha256_ror(t[4], 6) ^ sha256_ror(t[4], 11) + ^ sha256_ror(t[4], 25); + + uint32_t t1 = t[7] + S1 + ch + sha256_round_k[j] + w[j]; + uint32_t t2 = S0 + maj; + + t[7] = t[6]; + t[6] = t[5]; + t[5] = t[4]; + t[4] = t[3] + t1; + t[3] = t[2]; + t[2] = t[1]; + t[1] = t[0]; + t[0] = t1 + t2; + } + + for(int i = 0; i < 8; i++) + v[i] += t[i]; + } + + for(int i = 0; i < 8; i++) + sha256_endian_reverse32(v[i], (uint8_t *)output + i * 4); +} diff --git a/sha256/sha256.h b/sha256/sha256.h new file mode 100644 index 0000000..5b169b9 --- /dev/null +++ b/sha256/sha256.h @@ -0,0 +1,17 @@ +/* + SHA256 implementation, header file. + + This implementation was written by Kent "ethereal" Williams-King and is + hereby released into the public domain. Do what you wish with it. + + No guarantees as to the correctness of the implementation are provided. +*/ + +#ifndef SHA256_H +#define SHA256_H + +#include + +void sha256(const void *data, uint64_t len, void *output); + +#endif diff --git a/util.h b/util.h new file mode 100644 index 0000000..75966c5 --- /dev/null +++ b/util.h @@ -0,0 +1,186 @@ +typedef struct str_list { + int n; + char **data; + int *lengths; +}List; + +typedef struct str_tokenizer { + int current; + int n; + char **tokens; +}Tokenizer; + +char *ltrim(char *str, const char *seps); +char *rtrim(char *str, const char *seps); +char *trim(char *str, const char *seps); +int indexOf(char *s,const char **array,int length_array); + +int hexchr2bin(char hex, char *out); +int hexs2bin(char *hex, unsigned char *out); +char *tohex(char *ptr,int length); + +int hasMoreTokens(Tokenizer *t); +char *nextToken(Tokenizer *t); + +char *ltrim(char *str, const char *seps) { + size_t totrim; + if (seps == NULL) { + seps = "\t\n\v\f\r "; + } + totrim = strspn(str, seps); + if (totrim > 0) { + size_t len = strlen(str); + if (totrim == len) { + str[0] = '\0'; + } + else { + memmove(str, str + totrim, len + 1 - totrim); + } + } + return str; +} + +char *rtrim(char *str, const char *seps) { + int i; + if (seps == NULL) { + seps = "\t\n\v\f\r "; + } + i = strlen(str) - 1; + while (i >= 0 && strchr(seps, str[i]) != NULL) { + str[i] = '\0'; + i--; + } + return str; +} + +char *trim(char *str, const char *seps) { + return ltrim(rtrim(str, seps), seps); +} + +int indexOf(char *s,const char **array,int length_array) { + int index = -1,i,continuar = 1; + for(i = 0; i current < t->n) { + t->current++; + return t->tokens[t->current-1]; + } + else { + return NULL; + } +} +int hasMoreTokens(Tokenizer *t) { + return (t->current < t->n); +} + +void stringtokenizer(char *data,Tokenizer *t) { + char *token; + t->tokens = NULL; + t->n = 0; + t->current = 0; + trim(data,"\t\n\r "); + token = strtok(data," \t:"); + while(token != NULL) { + t->n++; + t->tokens = realloc(t->tokens,sizeof(char*)*t->n); + if(t->tokens == NULL) { + printf("Out of memory\n"); + exit(0); + } + t->tokens[t->n - 1] = token; + token = strtok(NULL," \t"); + } +} + +void freetokenizer(Tokenizer *t) { + if(t->n > 0) { + free(t-> tokens); + } + memset(t,0,sizeof(Tokenizer)); +} + + +/* + Aux function to get the hexvalues of the data +*/ + +char *tohex(char *ptr,int length){ + char *buffer; + int offset = 0; + unsigned char c; + buffer = (char *) malloc((length * 2)+1); + for (int i = 0; i = '0' && hex <= '9') { + *out = hex - '0'; + } else if (hex >= 'A' && hex <= 'F') { + *out = hex - 'A' + 10; + } else if (hex >= 'a' && hex <= 'f') { + *out = hex - 'a' + 10; + } else { + return 0; + } + + return 1; +} + +void addItemList(char *data, List *l) { + l->data = realloc(l->data,sizeof(char*)* (l->n +1)); + l->data[l->n] = data; + l->n++; +} + +int isValidHex(char *data) { + char c; + int len,i,valid = 1; + len = strlen(data); + for(i = 0 ; i < len && valid ;i++ ) { + c = data[i]; + valid = ( (c >= '0' && c <='9') || (c >= 'A' && c <='F' ) || (c >= 'a' && c <='f' ) ); + } + return valid; +}