diff --git a/CMakeLists.txt b/CMakeLists.txt index ead58d1..dc8d912 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ project(eosio-keygen VERSION 0.1.3) # Options option(USE_THREADS "Compile with support for threads (if available)." ON) +option(FORCE_ANSI "Force ANSI console colors even on windows" OFF) # Use installpath from GNUInstallDirs as default. include(GNUInstallDirs) @@ -26,6 +27,13 @@ set (PROGRAM_SOURCE src/main.cpp ) +if (WIN32 AND NOT FORCE_ANSI) + set (PROGRAM_SOURCE ${PROGRAM_SOURCE} src/console_win32.cpp) +else() + # *nix should have ansi support. + set (PROGRAM_SOURCE ${PROGRAM_SOURCE} src/console_ansi.cpp) +endif() + # Configure the compiler options set( CMAKE_CXX_STANDARD 11 ) set( CMAKE_CXX_STANDARD_REQUIRED ON ) diff --git a/src/console.h b/src/console.h new file mode 100644 index 0000000..c81a5b7 --- /dev/null +++ b/src/console.h @@ -0,0 +1,83 @@ +/** + * MIT License + * + * Copyright (c) 2019-2020 EOS Sw/eden + * + * 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 CONSOLE_H +#define CONSOLE_H + +#include + +namespace console { + + // enum for all supported colors. + enum Color { + default_fg, + black, + white, + red, + green, + blue, + yellow, + magenta, + cyan, + + // Light colors. + light_grey, + light_red, + light_green, + light_blue, + light_yellow, + light_magenta, + light_cyan, + + // Dark colors + dark_grey + }; + + enum Attribute { + normal, + bold, + italic + }; + + // Resets all colors/attributes + std::ostream& reset(std::ostream& os); + + // Foreground color + // Defined as a class with overloaded "<<" operator so you can write: + // std::cout << fg(red) << "Text"; + class fg + { + public: + fg(Color color, Attribute attribute = normal) + : _color(color), _attr(attribute) {} + + friend std::ostream& operator<<(std::ostream& os, const fg& obj); + + protected : + Color _color; + Attribute _attr; + }; + +} // namespace console + +#endif /* CONSOLE_H */ diff --git a/src/console_ansi.cpp b/src/console_ansi.cpp new file mode 100644 index 0000000..ed37b0a --- /dev/null +++ b/src/console_ansi.cpp @@ -0,0 +1,49 @@ + +#include +#include "console.h" + +namespace console { + +std::ostream& reset(std::ostream& os) { + return os << "\033[0m"; +} + +// Foreground +std::ostream& operator<<(std::ostream& os, const fg& obj) { + + int attr; + int code; + + switch(obj._color) { + case black : code = 30; break; + case red : code = 31; break; + case green : code = 32; break; + case yellow : code = 33; break; + case blue : code = 34; break; + case magenta : code = 35; break; + case cyan : code = 36; break; + case light_grey : code = 37; break; + case dark_grey : code = 90; break; + case light_red : code = 91; break; + case light_green : code = 92; break; + case light_yellow : code = 93; break; + case light_blue : code = 94; break; + case light_magenta : code = 95; break; + case light_cyan : code = 96; break; + case white : code = 97; break; + case default_fg : default : + code = 39; + } + + switch(obj._attr) { + + case bold : attr = 1; break; + case italic : attr = 2; break; + case normal : default : + attr = 0; + } + + return os << "\033[" << attr << ";" << code << "m"; +} + +} // namespace console diff --git a/src/console_win32.cpp b/src/console_win32.cpp new file mode 100644 index 0000000..d250dfa --- /dev/null +++ b/src/console_win32.cpp @@ -0,0 +1,68 @@ + +#include +#include +#include "console.h" + +// WinAPI colors +#define FG_BLACK 0 +#define FG_BLUE FOREGROUND_BLUE +#define FG_GREEN FOREGROUND_GREEN +#define FG_RED FOREGROUND_RED +#define FG_CYAN (FOREGROUND_GREEN | FOREGROUND_BLUE) +#define FG_YELLOW (FOREGROUND_RED | FOREGROUND_GREEN) +#define FG_MAGENTA (FOREGROUND_RED | FOREGROUND_BLUE) +#define FG_DARKGREY FOREGROUND_INTENSITY +#define FG_GREY (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) +#define FG_LIGHTBLUE (FOREGROUND_INTENSITY | FOREGROUND_BLUE) +#define FG_LIGHTGREEN (FOREGROUND_INTENSITY | FOREGROUND_GREEN) +#define FG_LIGHTCYAN (FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE) +#define FG_LIGHTRED (FOREGROUND_INTENSITY | FOREGROUND_RED) +#define FG_LIGHTMAGENTA (FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE) +#define FG_LIGHTYELLOW (FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN) +#define FG_WHITE (FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) +#define FG_DEFAULT FG_GREY + +namespace console { + +std::ostream& reset(std::ostream& os) { + + ::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), FG_DEFAULT); + + return os; +} + +// Foreground +std::ostream& operator<<(std::ostream& os, const fg& obj) { + + int code; + + switch(obj._color) { + case black : code = FG_BLACK; break; + case red : code = FG_RED; break; + case green : code = FG_GREEN; break; + case blue : code = FG_BLUE; break; + case yellow : code = FG_YELLOW; break; + case magenta : code = FG_MAGENTA; break; + case cyan : code = FG_CYAN; break; + case light_grey : code = FG_GREY; break; + case light_red : code = FG_LIGHTRED; break; + case light_green : code = FG_LIGHTGREEN; break; + case light_yellow : code = FG_LIGHTYELLOW; break; + case light_blue : code = FG_LIGHTBLUE; break; + case light_magenta : code = FG_LIGHTMAGENTA; break; + case light_cyan : code = FG_LIGHTCYAN; break; + case dark_grey : code = FG_DARKGREY; break; + case white : code = FG_WHITE; break; + case default_fg : default : + code = FG_DEFAULT; + } + + ::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), code); + + // WinAPI does not support text attributes in the console. + // so we ignore those. + + return os; +} + +} // namespace console diff --git a/src/key_search.cpp b/src/key_search.cpp index e55b808..ddff617 100644 --- a/src/key_search.cpp +++ b/src/key_search.cpp @@ -35,10 +35,10 @@ void KeySearch::_search_linear(size_t n) { struct ec_keypair pair; while (count < n) { - std::string word; + struct key_result res; ec_generate_key(&pair); - if (key_contains_word(&pair, m_words, word)) { - key_search_result(word, &pair); + if (key_contains_word(&pair, m_words, &res)) { + key_search_result(&pair, &res); count++; } } diff --git a/src/key_search_helpers.cpp b/src/key_search_helpers.cpp index 7b6cf2c..007d979 100644 --- a/src/key_search_helpers.cpp +++ b/src/key_search_helpers.cpp @@ -1,24 +1,37 @@ #include #include "WIF.h" +#include "console.h" #include "key_search_helpers.h" -void key_search_result(const std::string& word, const struct ec_keypair* pair) { +void key_search_result(const struct ec_keypair* key, const struct key_result* result) { + + std::string pub = wif_pub_encode(key->pub); + std::string word = pub.substr(result->pos, result->len); std::cout << "----" << std::endl; std::cout << "Found: " << word << std::endl; - wif_print_key(pair); + + std::cout << "Public: " + << pub.substr(0, result->pos) + << console::fg(console::red, console::bold) << word << console::reset + << pub.substr(result->pos + result->len) + << std::endl; + + std::cout << "Private: " << wif_priv_encode(key->secret) << std::endl; } -bool key_contains_word(const struct ec_keypair* key, const strlist_t& word_list, std::string& word) { +bool key_contains_word(const struct ec_keypair* key, const strlist_t& word_list, struct key_result *result) { // skip first 3 chars, as those are always "EOS" std::string pubstr = wif_pub_encode(key->pub).substr(3); strtolower(pubstr); for(auto const& w: word_list) { - if (pubstr.find(w) != std::string::npos) { - word = w; + size_t p = pubstr.find(w); + if (p != std::string::npos) { + result->pos = p + 3; + result->len = w.length(); return true; } } diff --git a/src/key_search_helpers.h b/src/key_search_helpers.h index 66d4291..66e7783 100644 --- a/src/key_search_helpers.h +++ b/src/key_search_helpers.h @@ -27,10 +27,15 @@ #include "string.h" #include "ec.h" -void key_search_result(const std::string& word, const struct ec_keypair* pair); +struct key_result { + size_t pos; // position where the word was found. + size_t len; // the length of the word. +}; + +void key_search_result(const struct ec_keypair* key, const struct key_result* result); // Check if any word in appears in 's public key. -// returns true if a word was found (stored in ), false otherwise. -bool key_contains_word(const struct ec_keypair* key, const strlist_t& word_list, std::string& word); +// returns true if a word was found (stored in ), false otherwise. +bool key_contains_word(const struct ec_keypair* key, const strlist_t& word_list, struct key_result *result); #endif /* KEY_SEARCH_HELPERS_H */ diff --git a/src/key_search_mt.cpp b/src/key_search_mt.cpp index 3854529..881ed53 100644 --- a/src/key_search_mt.cpp +++ b/src/key_search_mt.cpp @@ -21,10 +21,10 @@ static void _thr_proc(const strlist_t& word_list) { struct ec_keypair pair; while (g_count < g_max) { - std::string word; + struct key_result res; ec_generate_key(&pair); - if (key_contains_word(&pair, word_list, word)) { + if (key_contains_word(&pair, word_list, &res)) { // Guard output with mutex, so we don't get // interrupted mid write and can write to g_count safely. @@ -39,7 +39,7 @@ static void _thr_proc(const strlist_t& word_list) { // Update count and print result. g_count++; - key_search_result(word, &pair); + key_search_result(&pair, &res); } } }