sygcppv1.0.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /*
  2. * Thanks PurpleI2P Project for support to writing that code.
  3. *
  4. * IRC: irc.ilita.i2p port 6667 || 303:60d4:3d32:a2b9::3 port 16667
  5. * general channels: #ru and #howtoygg
  6. *
  7. * git: notabug.org/acetone/SimpleYggGen-CPP
  8. *
  9. * acetone, 2020 (c) GPLv3
  10. *
  11. */
  12. #include <openssl/evp.h> // библиотека OpenSSL
  13. #include <openssl/sha.h>
  14. #include <openssl/bn.h>
  15. #include <iostream> // вывод на экран
  16. #include <string>
  17. #include <sstream>
  18. #include <fstream> // файловые потоки
  19. #include <iomanip> // форматированный вывод строк
  20. #include <bitset> // побитовое чтение
  21. #include <vector>
  22. #include <thread> // многопоточность
  23. #include <mutex>
  24. #include <chrono> // для паузы в заставке
  25. #include <ctime>
  26. ////////////////////////////////////////////////// Заставка
  27. void intro()
  28. {
  29. std::cout << std::endl
  30. << " +--------------------------------------------------------------------------+" << std::endl
  31. << " | SimpleYggGen C++ 1.0-hothead |" << std::endl
  32. << " | OpenSSL inside: x25519 -> sha512 |" << std::endl
  33. << " | notabug.org/acetone/SimpleYggGen-CPP |" << std::endl
  34. << " | |" << std::endl
  35. << " | developers: acetone, lialh4, orignal |" << std::endl
  36. << " | GPLv3 (c) 2020 |" << std::endl
  37. << " +";
  38. for(int i = 0; i < 74; ++i)
  39. {
  40. std::cout << "-";
  41. std::cout.flush();
  42. std::this_thread::sleep_for(std::chrono::milliseconds(20));
  43. }
  44. std::cout << "+" << std::endl;
  45. }
  46. ////////////////////////////////////////////////// Суть вопроса
  47. #define KEYSIZE 32
  48. std::mutex mtx;
  49. int conf_proc = 100;
  50. int conf_mode = 100;
  51. int conf_log = 100;
  52. int conf_high = 100;
  53. std::string conf_search;
  54. std::string log_file;
  55. uint64_t totalcount = 0; // счетчик основного цикла
  56. uint64_t totalcountfortune = 0; // счетчик нахождений
  57. bool newline = true; // используется для вывода счетчика
  58. int config()
  59. {
  60. std::ifstream conffile ("sygcpp.conf");
  61. if(!conffile) // проверка наличия конфига
  62. {
  63. std::cout << " Configuration file not found..." << std::endl;
  64. conffile.close();
  65. std::ofstream newconf ("sygcpp.conf"); // создание конфига
  66. if(!newconf)
  67. {
  68. std::cerr << " Config (sygcpp.conf) creation failed :(" << std::endl;
  69. return -1;
  70. }
  71. newconf << "1 0 1 9 ::\n"
  72. << "| | | | ^Pattern for search by name.\n"
  73. << "| | | ^Start position for high addresses search.\n"
  74. << "| | ^Logging mode (0 - console output only, 1 - log to file).\n"
  75. << "| ^Mining mode (0 - by name, 1 - high address).\n"
  76. << "^Count of thread (mining streams).\n\n"
  77. << "Parameters are separated by spaces.";
  78. newconf.close();
  79. std::ifstream conffile ("sygcpp.conf");
  80. if(conffile)
  81. std::cout << " Config successfully created :)" << std::endl;
  82. config();
  83. return 0;
  84. } else {
  85. conffile >> conf_proc >> conf_mode >> conf_log >> conf_high >> conf_search;
  86. conffile.close();
  87. if(conf_mode > 1 || conf_mode < 0 || conf_log > 1 || conf_log < 0 || conf_high < 0) // проверка полученных значений
  88. {
  89. std::cerr << " Invalid config found!\n"
  90. << " Check it:\n"
  91. << " - 2 field - mining mode: 0 or 1 only\n"
  92. << " - 3 field - logging mode: 0 or 1 only\n"
  93. << " - 5 field - string to search by name: a-z, 0-9 and ':' symbols only\n"
  94. << " Remove or correct sygcpp.conf and run SYG again."<< std::endl;
  95. return -2;
  96. }
  97. unsigned int processor_count = std::thread::hardware_concurrency(); // кол-во процессоров
  98. if(conf_proc > (int)processor_count)
  99. conf_proc = (int)processor_count;
  100. }
  101. // вывод конфигурации на экран
  102. std::cout << " Threads: " << conf_proc << ", ";
  103. if(conf_mode == 1)
  104. std::cout << "search high addresses (" << conf_high << "), ";
  105. else
  106. std::cout << "search by name (" << conf_search << "), ";
  107. if(conf_log == 1)
  108. std::cout << "logging to text file." << std::endl;
  109. else
  110. std::cout << "console log only." << std::endl;
  111. return 0;
  112. }
  113. void testoutput()
  114. {
  115. if(conf_log == 1) // проверка включено ли логирование
  116. {
  117. if(conf_mode == 1)
  118. log_file = "syg-high.txt";
  119. else
  120. log_file = "syg-byname.txt";
  121. std::ifstream test(log_file);
  122. if(!test) // проверка наличия выходного файла
  123. {
  124. test.close();
  125. std::ofstream output(log_file);
  126. output << "**************************************************************************\n"
  127. << "Change EncryptionPublicKey and EncryptionPrivateKey to your yggdrasil.conf\n"
  128. << "Windows: C:\\ProgramData\\Yggdrasil\\yggdrasil.conf\n"
  129. << "Debian: /etc/yggdrasil.conf\n\n"
  130. << "Visit HowTo.Ygg wiki for more information (russian language page):\n"
  131. << "http://[300:529f:150c:eafe::6]/doku.php?id=yggdrasil:simpleygggen_cpp\n"
  132. << "**************************************************************************\n";
  133. output.close();
  134. } else test.close();
  135. }
  136. }
  137. struct BoxKeys
  138. {
  139. uint8_t PublicKey[KEYSIZE];
  140. uint8_t PrivateKey[KEYSIZE];
  141. };
  142. BoxKeys getKeyPair()
  143. {
  144. BoxKeys keys;
  145. size_t len = KEYSIZE;
  146. EVP_PKEY_CTX * Ctx;
  147. EVP_PKEY * Pkey = nullptr;
  148. Ctx = EVP_PKEY_CTX_new_id (NID_X25519, NULL);
  149. EVP_PKEY_keygen_init (Ctx);
  150. EVP_PKEY_keygen (Ctx, &Pkey);
  151. EVP_PKEY_get_raw_public_key (Pkey, keys.PublicKey, &len);
  152. EVP_PKEY_get_raw_private_key (Pkey, keys.PrivateKey, &len);
  153. EVP_PKEY_CTX_free(Ctx);
  154. EVP_PKEY_free(Pkey);
  155. return keys;
  156. }
  157. int getOnes(const unsigned char HashValue[SHA512_DIGEST_LENGTH])
  158. {
  159. bool done = false;
  160. int lOnes = 0; // кол-во лидирующих единиц
  161. std::vector<std::bitset<8>> bytes; // вектор с однобайтовыми битсетами (двумерный массив)
  162. for(int i = 0; i < 32; ++i) // всего 32 байта, т.к. лидирующих единиц больше быть не может (32*8 = 256 бит, а ff = 255)
  163. bytes.push_back(HashValue[i]); // вставка в вектор с битсетами одного i-того байта хэша
  164. for(auto vector_count = bytes.begin(); vector_count != bytes.end() && !done; vector_count++)
  165. {
  166. for(int i = 7; i >= 0 && !done; --i)
  167. {
  168. if((*vector_count)[i] == 1) // обращение к i-тому элементу битсета
  169. ++lOnes;
  170. if((*vector_count)[i] == 0)
  171. done = true;
  172. }
  173. }
  174. return lOnes;
  175. }
  176. std::string getAddress(unsigned char HashValue[SHA512_DIGEST_LENGTH])
  177. {
  178. // функция "портит" массив хэша, т.к. копирование массива не происходит
  179. int lErase = getOnes(HashValue) + 1; // лидирующие единицы и первый ноль
  180. bool changeit = false;
  181. int bigbyte = 0;
  182. for(int j = 0; j < lErase; ++j) // побитовое смещение
  183. {
  184. for(int i = 63; i >= 0; --i)
  185. {
  186. if(bigbyte == i+1) // предыдущий байт требует переноса
  187. changeit = true;
  188. if(HashValue[i] & 0x80)
  189. bigbyte = i;
  190. HashValue[i] <<= 1;
  191. if(changeit)
  192. {
  193. HashValue[i] |= 0x01;
  194. changeit = false;
  195. }
  196. }
  197. }
  198. std::string address;
  199. std::stringstream ss(address);
  200. ss << 0x02 << std::setw(2) << std::setfill('0') << std::hex << lErase - 1 << ":";
  201. // 2 - константа подсети Yggdrasil, второй байт - кол-во лидирующих единиц в хешэ
  202. for(int i = 0; i < 14; ++i)
  203. {
  204. if(HashValue[i] == 0) // большая вложенность if-ов (не одним условием) для большей производительности
  205. {
  206. if(HashValue[i+1] == 0)
  207. {
  208. if(i % 2 == 0)
  209. {
  210. if(HashValue[i+2] == 0 && HashValue[i+3] == 0)
  211. {
  212. ss << ":";
  213. i += 3;
  214. } else {
  215. ss << "0";
  216. ++i;
  217. if(i != 13) // не выводим двоеточие в конце адреса
  218. ss << ":";
  219. }
  220. }
  221. }
  222. } else if(HashValue[i] == 0 && i % 2 == 0) { // не выводим первые нулевый байты секции
  223. } else {
  224. if(i % 2 == 0 || ((HashValue[i-1] == 0 && i % 2 != 0))) // если выводится первый байт секции, нули сокращаем
  225. ss << std::hex << (int)HashValue[i];
  226. else
  227. {
  228. ss << std::setw(2) << std::setfill('0') << std::hex << (int)HashValue[i];
  229. if(i != 13) // не выводим двоеточие в конце адреса
  230. ss << ":";
  231. }
  232. }
  233. }
  234. return ss.str();
  235. }
  236. void getConsoleLog()
  237. {
  238. mtx.lock();
  239. ++totalcount;
  240. if(totalcount % 250000 == 0)
  241. {
  242. if(newline)
  243. {
  244. std::cout << std::endl;
  245. newline = false;
  246. }
  247. std::time_t realtime = std::time(NULL);
  248. std::cout << " # count [ " << std::dec << std::setfill('.') << std::setw(19) << totalcount << " ] [ "
  249. << std::setw(15) << totalcountfortune << " ] " << std::asctime(std::localtime(&realtime));
  250. std::cout.flush();
  251. }
  252. mtx.unlock();
  253. }
  254. void highminer()
  255. {
  256. unsigned char HashValue[SHA512_DIGEST_LENGTH];
  257. uint8_t PublicKeyBest[KEYSIZE];
  258. uint8_t PrivateKeyBest[KEYSIZE];
  259. while(true)
  260. {
  261. BoxKeys myKeys = getKeyPair();
  262. SHA512(myKeys.PublicKey, KEYSIZE, HashValue);
  263. int newones = getOnes(HashValue);
  264. if(newones > conf_high) // сохранение лучших ключей
  265. {
  266. conf_high = newones;
  267. for(int i = 0; i < KEYSIZE; ++i)
  268. {
  269. PublicKeyBest[i] = myKeys.PublicKey[i];
  270. PrivateKeyBest[i] = myKeys.PrivateKey[i];
  271. }
  272. std::string address = getAddress(HashValue);
  273. mtx.lock();
  274. std::cout << "\n Address: " << address << std::endl;
  275. std::cout << " PublicKey: ";
  276. for(int i = 0; i < 32; ++i)
  277. {
  278. std::cout << std::setw(2) << std::setfill('0') << std::hex << (int)PublicKeyBest[i];
  279. }
  280. std::cout << std::endl;
  281. std::cout << " PrivateKey: ";
  282. for(int i = 0; i < 32; ++i)
  283. {
  284. std::cout << std::setw(2) << std::setfill('0') << std::hex << (int)PrivateKeyBest[i];
  285. }
  286. std::cout << std::endl;
  287. if(conf_log == 1) // запись в файл
  288. {
  289. std::ofstream output(log_file, std::ios::app);
  290. output << "\nAddress: " << address << std::endl;
  291. output << "EncryptionPublicKey: ";
  292. for(int i = 0; i < 32; ++i)
  293. {
  294. output << std::setw(2) << std::setfill('0') << std::hex << (int)PublicKeyBest[i];
  295. }
  296. output << std::endl;
  297. output << "EncryptionPrivateKey: ";
  298. for(int i = 0; i < 32; ++i)
  299. {
  300. output << std::setw(2) << std::setfill('0') << std::hex << (int)PrivateKeyBest[i];
  301. }
  302. output << std::endl;
  303. output.close();
  304. }
  305. ++totalcountfortune;
  306. newline = true;
  307. mtx.unlock();
  308. }
  309. getConsoleLog();
  310. } // while(true)
  311. }
  312. void nameminer()
  313. {
  314. unsigned char HashValue[SHA512_DIGEST_LENGTH];
  315. uint8_t PublicKeyBest[KEYSIZE];
  316. uint8_t PrivateKeyBest[KEYSIZE];
  317. while(true)
  318. {
  319. BoxKeys myKeys = getKeyPair();
  320. SHA512(myKeys.PublicKey, KEYSIZE, HashValue);
  321. std::string tempstr = getAddress(HashValue);
  322. if(tempstr.find(conf_search.c_str()) != std::string::npos) // сохранение найденных ключей
  323. {
  324. for(int i = 0; i < KEYSIZE; ++i)
  325. {
  326. PublicKeyBest[i] = myKeys.PublicKey[i];
  327. PrivateKeyBest[i] = myKeys.PrivateKey[i];
  328. }
  329. mtx.lock();
  330. std::cout << "\n Address: " << tempstr << std::endl;
  331. std::cout << " PublicKey: ";
  332. for(int i = 0; i < 32; ++i)
  333. {
  334. std::cout << std::setw(2) << std::setfill('0') << std::hex << (int)PublicKeyBest[i];
  335. }
  336. std::cout << std::endl;
  337. std::cout << " PrivateKey: ";
  338. for(int i = 0; i < 32; ++i)
  339. {
  340. std::cout << std::setw(2) << std::setfill('0') << std::hex << (int)PrivateKeyBest[i];
  341. }
  342. std::cout << std::endl;
  343. if(conf_log == 1) // запись в файл
  344. {
  345. std::ofstream output(log_file, std::ios::app);
  346. output << "\nAddress: " << tempstr << std::endl;
  347. output << "EncryptionPublicKey: ";
  348. for(int i = 0; i < 32; ++i)
  349. {
  350. output << std::setw(2) << std::setfill('0') << std::hex << (int)PublicKeyBest[i];
  351. }
  352. output << std::endl;
  353. output << "EncryptionPrivateKey: ";
  354. for(int i = 0; i < 32; ++i)
  355. {
  356. output << std::setw(2) << std::setfill('0') << std::hex << (int)PrivateKeyBest[i];
  357. }
  358. output << std::endl;
  359. output.close();
  360. }
  361. ++totalcountfortune;
  362. newline = true;
  363. mtx.unlock();
  364. }
  365. getConsoleLog();
  366. }
  367. }
  368. // ------------------------------------------------------
  369. int main()
  370. {
  371. intro();
  372. int configcheck = config();
  373. if(configcheck < 0) // функция получения конфигурации
  374. {
  375. std::cerr << "Error code: " << configcheck << std::endl;
  376. system("PAUSE");
  377. return configcheck;
  378. }
  379. testoutput();
  380. if(conf_mode == 1) // запуск соответствующего режима майнинга
  381. {
  382. std::thread * threads[conf_proc];
  383. for(int i = 0; i < conf_proc; ++i)
  384. threads[i] = new std::thread(highminer);
  385. for(int i = 0; i < conf_proc - 1; ++i)
  386. threads[i]->detach();
  387. threads[conf_proc-1]->join(); // "ждем" последний трэд, бесконечное ожидание
  388. }
  389. else
  390. {
  391. std::thread * threads[conf_proc];
  392. for(int i = 0; i < conf_proc; ++i)
  393. threads[i] = new std::thread(nameminer);
  394. for(int i = 0; i < conf_proc - 1; ++i)
  395. threads[i]->detach();
  396. threads[conf_proc-1]->join();
  397. }
  398. std::cerr << "SYG has stopped working unexpectedly! Please, report about this." << std::endl;
  399. system("PAUSE");
  400. return -420;
  401. }