sygcpp.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. /**
  2. *
  3. * IRC: irc.ilita.i2p port 6667 || 303:60d4:3d32:a2b9::3 port 16667
  4. * general channels: #ru and #howtoygg
  5. *
  6. * acetone (default) git: notabug.org/acetone/SimpleYggGen-CPP
  7. * Vort (member) git: notabug.org/Vort/SimpleYggGen-CPP
  8. *
  9. * developers: Vort, acetone, R4SAS, lialh4, orignal
  10. * developers team, 2020 (c) GPLv3
  11. *
  12. */
  13. #include <x86intrin.h>
  14. #include <string.h> // memcmp
  15. #include <sodium.h> // библиотека libsodium
  16. #include <iostream> // вывод на экран
  17. #include <string>
  18. #include <sstream>
  19. #include <fstream> // файловые потоки
  20. #include <iomanip> // форматированный вывод строк
  21. #include <bitset> // побитовое чтение
  22. #include <vector>
  23. #include <thread> // многопоточность
  24. #include <mutex> // блокирование данных при многопоточности
  25. #include <chrono> // для вычисления скорости
  26. #include <ctime>
  27. #include <regex> // регулярные выражения
  28. #ifdef _WIN32 // преобразование в IPv6
  29. #include <ws2tcpip.h>
  30. #else
  31. #include <arpa/inet.h>
  32. #endif
  33. #include "x25519.h"
  34. #include "sha512.h"
  35. #include "cppcodec/base32_rfc4648.hpp"
  36. #define BLOCKSIZE 10000
  37. //#define SELF_CHECK // debug
  38. ////////////////////////////////////////////////// Заставка
  39. void Intro()
  40. {
  41. std::cout <<
  42. std::endl <<
  43. " +--------------------------------------------------------------------------+" << std::endl <<
  44. " | [ SimpleYggGen C++ 3.3-worldwide ] |" << std::endl <<
  45. " | X25519 -> SHA512 -> IPv6 -> Meshname |" << std::endl <<
  46. " | notabug.org/acetone/SimpleYggGen-CPP |" << std::endl <<
  47. " | |" << std::endl <<
  48. " | GPLv3 (c) 2020 |" << std::endl <<
  49. " +--------------------------------------------------------------------------+" << std::endl <<
  50. std::endl;
  51. }
  52. ////////////////////////////////////////////////// Суть вопроса
  53. std::mutex mtx;
  54. std::time_t sygstartedin = std::time(NULL); // для вывода времени работы
  55. int countsize = 0; // определяет периодичность вывода счетчика
  56. uint64_t block_count = 0; // количество вычисленных блоков
  57. uint64_t totalcountfortune = 0; // счетчик нахождений
  58. bool newline = false; // форматирует вывод после нахождения адреса
  59. std::chrono::steady_clock::duration blocks_duration(0);
  60. #include "basefiles.cpp"
  61. int getOnes(const unsigned char HashValue[crypto_hash_sha512_BYTES])
  62. {
  63. int lOnes = 0; // кол-во лидирующих единиц
  64. for (int i = 0; i < 32; ++i) // всего 32 байта, т.к. лидирующих единиц больше быть не может (32*8 = 256 бит, а ff = 255)
  65. {
  66. std::bitset<8> bits(HashValue[i]);
  67. for (int i = 7; i >= 0; --i)
  68. {
  69. if (bits[i] == 1) // обращение к i-тому элементу битсета
  70. ++lOnes;
  71. else
  72. return lOnes;
  73. }
  74. }
  75. return -421; // это никогда не случится
  76. }
  77. void getRawAddress(int lErase, unsigned char * HashValue, uint8_t * rawAddr) // ожидается 64 и 16 байт
  78. {
  79. // функция портит массив хэша, вызывать повторно со старым массивом нельзя
  80. ++lErase; // лидирующие единицы и первый ноль
  81. bool changeit = false;
  82. int bigbyte = 0;
  83. int needlen = 15 + (lErase/8); // количество байт адреса + байты лид.единиц
  84. for(int j = 0; j < lErase; ++j) // побитовое смещение
  85. {
  86. for(int i = needlen; i >= 0; --i)
  87. {
  88. if(bigbyte == i+1) // предыдущий байт требует переноса
  89. changeit = true;
  90. if(HashValue[i] & 0x80)
  91. bigbyte = i;
  92. HashValue[i] <<= 1;
  93. if(changeit)
  94. {
  95. HashValue[i] |= 0x01;
  96. changeit = false;
  97. }
  98. }
  99. }
  100. rawAddr[0] = 0x02;
  101. rawAddr[1] = lErase - 1;
  102. for (int i = 0; i < 14; ++i)
  103. rawAddr[i + 2] = HashValue[i];
  104. // char ipStrBuf[46];
  105. // inet_ntop(AF_INET6, rawAddr, ipStrBuf, 46);
  106. // std::cout << std::string(ipStrBuf) << std::endl;
  107. }
  108. std::string getAddress(const uint8_t * rawAddr)
  109. {
  110. char ipStrBuf[46];
  111. inet_ntop(AF_INET6, rawAddr, ipStrBuf, 46);
  112. return std::string(ipStrBuf);
  113. }
  114. std::string getMeshname(const uint8_t * rawAddr)
  115. {
  116. return std::string(cppcodec::base32_rfc4648::encode(rawAddr, 16));
  117. }
  118. void logStatistics()
  119. {
  120. if (++block_count % countsize == 0)
  121. {
  122. auto timedays = (std::time(NULL) - sygstartedin) / 86400;
  123. auto timehours = ((std::time(NULL) - sygstartedin) - (timedays * 86400)) / 3600;
  124. auto timeminutes = ((std::time(NULL) - sygstartedin) - (timedays * 86400) - (timehours * 3600)) / 60;
  125. auto timeseconds = (std::time(NULL) - sygstartedin) - (timedays * 86400) - (timehours * 3600) - (timeminutes * 60);
  126. std::chrono::duration<double, std::milli> df = blocks_duration;
  127. blocks_duration = std::chrono::steady_clock::duration::zero();
  128. int khs = conf.proc * countsize * BLOCKSIZE / df.count();
  129. std::cout <<
  130. " kH/s: [" << std::setw(7) << std::setfill('_') << khs <<
  131. "] Total: [" << std::setw(19) << block_count * BLOCKSIZE <<
  132. "] Found: [" << std::setw(3) << totalcountfortune <<
  133. "] Time: [" << timedays << ":" << std::setw(2) << std::setfill('0') <<
  134. timehours << ":" << std::setw(2) << timeminutes << ":" << std::setw(2) << timeseconds << "]" << std::endl;
  135. newline = true;
  136. }
  137. }
  138. std::string hexArrayToString(const uint8_t* bytes, int length)
  139. {
  140. std::stringstream ss;
  141. for (int i = 0; i < length; i++)
  142. ss << std::setw(2) << std::setfill('0') << std::hex << (int)bytes[i];
  143. return ss.str();
  144. }
  145. std::string keyToString(const key25519 key)
  146. {
  147. return hexArrayToString(key, KEYSIZE);
  148. }
  149. std::string hashToString(const uint8_t hash[crypto_hash_sha512_BYTES])
  150. {
  151. return hexArrayToString(hash, crypto_hash_sha512_BYTES);
  152. }
  153. void logKeys(uint8_t * raw, const key25519 publicKey, const key25519 privateKey)
  154. {
  155. if(newline) // добавляем пустую строку на экране между счетчиком и новым адресом
  156. {
  157. std::cout << std::endl;
  158. newline = false;
  159. }
  160. if (conf.mesh)
  161. std::cout << " Domain: " << getMeshname(raw) + ".meshname" << std::endl;
  162. std::cout << " Address: " << getAddress(raw) << std::endl;
  163. std::cout << " PublicKey: " << keyToString(publicKey) << std::endl;
  164. std::cout << " PrivateKey: " << keyToString(privateKey) << std::endl;
  165. std::cout << std::endl;
  166. if (conf.log) // запись в файл
  167. {
  168. std::ofstream output(conf.outputfile, std::ios::app);
  169. output << std::endl;
  170. if (conf.mesh)
  171. output << "Domain: " << getMeshname(raw) + ".meshname" << std::endl;
  172. output << "Address: " << getAddress(raw) << std::endl;
  173. output << "EncryptionPublicKey: " << keyToString(publicKey) << std::endl;
  174. output << "EncryptionPrivateKey: " << keyToString(privateKey) << std::endl;
  175. output.close();
  176. }
  177. }
  178. void process_fortune_key(const keys_block& block, int index)
  179. {
  180. if (index == -1)
  181. return;
  182. key25519 public_key;
  183. key25519 private_key;
  184. block.get_public_key(public_key, index);
  185. block.get_private_key(private_key, index);
  186. uint8_t sha512_hash[crypto_hash_sha512_BYTES];
  187. crypto_hash_sha512(sha512_hash, public_key);
  188. int ones = getOnes(sha512_hash);
  189. uint8_t raw[16];
  190. getRawAddress(ones, sha512_hash, raw);
  191. logKeys(raw, public_key, private_key);
  192. ++totalcountfortune;
  193. }
  194. template <int T>
  195. void miner_thread()
  196. {
  197. key25519 public_key;
  198. keys_block block(BLOCKSIZE);
  199. uint8_t random_bytes[KEYSIZE];
  200. uint8_t sha512_hash[crypto_hash_sha512_BYTES];
  201. std::regex regx(conf.rgx_search, std::regex_constants::egrep);
  202. for (;;)
  203. {
  204. auto start_time = std::chrono::steady_clock::now();
  205. int fortune_key_index = -1;
  206. randombytes(random_bytes, KEYSIZE);
  207. block.calculate_public_keys(random_bytes);
  208. for (int i = 0; i < BLOCKSIZE; i++)
  209. {
  210. block.get_public_key(public_key, i);
  211. crypto_hash_sha512(sha512_hash, public_key);
  212. int newones = getOnes(sha512_hash);
  213. uint8_t rawAddr[16];
  214. getRawAddress(newones, sha512_hash, rawAddr);
  215. if (T == 0) // IPv6 pattern mining
  216. {
  217. if (getAddress(rawAddr).find(
  218. conf.str_search.c_str()) != std::string::npos)
  219. {
  220. fortune_key_index = i;
  221. break; // можно использовать только один ключ из блока
  222. }
  223. }
  224. if (T == 1) // high mining
  225. {
  226. if (newones > conf.high)
  227. {
  228. conf.high = newones;
  229. fortune_key_index = i;
  230. }
  231. }
  232. if (T == 2) // pattern & high mining
  233. {
  234. if (getAddress(rawAddr).find(
  235. conf.str_search.c_str()) != std::string::npos &&
  236. newones > conf.high)
  237. {
  238. conf.high = newones;
  239. fortune_key_index = i;
  240. break;
  241. }
  242. }
  243. if (T == 3) // IPv6 regexp mining
  244. {
  245. if (std::regex_search((getAddress(rawAddr)), regx))
  246. {
  247. fortune_key_index = i;
  248. break;
  249. }
  250. }
  251. if (T == 4) // meshname pattern mining
  252. {
  253. if (getMeshname(rawAddr).find(
  254. conf.str_search.c_str()) != std::string::npos)
  255. {
  256. fortune_key_index = i;
  257. break; // можно использовать только один ключ из блока
  258. }
  259. }
  260. if (T == 5) // meshname regex mining
  261. {
  262. if (std::regex_search((getMeshname(rawAddr)), regx))
  263. {
  264. fortune_key_index = i;
  265. break;
  266. }
  267. }
  268. }
  269. auto stop_time = std::chrono::steady_clock::now();
  270. mtx.lock();
  271. blocks_duration += stop_time - start_time;
  272. process_fortune_key(block, fortune_key_index);
  273. logStatistics();
  274. mtx.unlock();
  275. }
  276. }
  277. #ifdef SELF_CHECK // debug
  278. void selfCheck()
  279. {
  280. std::cout << "Self-check started." << std::endl;
  281. for (int i = 0; i < 16; i++)
  282. {
  283. int block_size = 1 << i;
  284. keys_block block(block_size);
  285. uint8_t random_bytes[KEYSIZE];
  286. randombytes(random_bytes, KEYSIZE);
  287. block.calculate_public_keys(random_bytes);
  288. key25519 public_key1;
  289. key25519 public_key2;
  290. key25519 private_key;
  291. uint8_t sha512_hash1[crypto_hash_sha512_BYTES];
  292. uint8_t sha512_hash2[crypto_hash_sha512_BYTES];
  293. for (int j = 0; j < block_size; j++)
  294. {
  295. block.get_public_key(public_key1, j);
  296. block.get_private_key(private_key, j);
  297. crypto_scalarmult_curve25519_base(public_key2, private_key);
  298. crypto_hash_sha512(sha512_hash1, public_key2);
  299. crypto_hash_sha512(sha512_hash2, public_key2, KEYSIZE);
  300. if (memcmp(public_key1, public_key2, KEYSIZE) != 0 ||
  301. memcmp(sha512_hash1, sha512_hash2, crypto_hash_sha512_BYTES))
  302. {
  303. std::cout << "!!! Self-check failed !!!" << std::endl;
  304. std::cout << " PrivateKey: " << keyToString(private_key) << std::endl;
  305. std::cout << " PublicKey1: " << keyToString(public_key1) << std::endl;
  306. std::cout << " PublicKey2: " << keyToString(public_key2) << std::endl;
  307. std::cout << " SHA512Hash1: " << hashToString(sha512_hash1) << std::endl;
  308. std::cout << " SHA512Hash2: " << hashToString(sha512_hash2) << std::endl;
  309. std::cout << "!!! Self-check failed !!!" << std::endl;
  310. return;
  311. }
  312. else
  313. {
  314. //std::cout << " Self-check ok" << std::endl;
  315. //std::cout << " PrivateKey: " << keyToString(private_key) << std::endl;
  316. }
  317. }
  318. }
  319. std::cout << "Self-check finished." << std::endl;
  320. }
  321. #endif // debug
  322. // ------------------------------------------------------
  323. int main()
  324. {
  325. Intro();
  326. #ifdef SELF_CHECK
  327. selfCheck();
  328. return 0;
  329. #endif
  330. int configcheck = config(); // функция получения конфигурации
  331. if(configcheck < 0)
  332. {
  333. std::cerr << " Error code: " << configcheck;
  334. std::this_thread::sleep_for(std::chrono::seconds(15));
  335. return configcheck;
  336. }
  337. DisplayConfig();
  338. testoutput();
  339. std::thread* lastThread;
  340. for (int i = 0; i < conf.proc; i++)
  341. {
  342. lastThread = new std::thread(
  343. conf.mode == 0 ? miner_thread<0> :
  344. conf.mode == 1 ? miner_thread<1> :
  345. conf.mode == 2 ? miner_thread<2> :
  346. conf.mode == 3 ? miner_thread<3> :
  347. conf.mode == 4 ? miner_thread<4> :
  348. miner_thread<5>
  349. );
  350. }
  351. lastThread->join();
  352. std::cerr << "SYG has stopped working unexpectedly! Please, report about this.";
  353. std::this_thread::sleep_for(std::chrono::seconds(15));
  354. return -420;
  355. }