yggm/sources/main.cpp
2025-02-28 12:53:12 +05:00

271 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Address miner for Yggdrsail Network 0.4.x and higher.
*
* developers: Vort, acetone, R4SAS, lialh4, filarius, orignal
* developers team, 2021 (c) GPLv3
*
*/
#include <sodium.h>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <vector>
#include <array>
#include <string.h>
#include <memory.h>
#include <thread>
#include <regex>
#include <arpa/inet.h>
#include <cppcodec/base32_rfc4648.hpp>
int countsize = 0;
uint64_t totalcount = 0;
bool newline = false;
typedef std::array<unsigned char, 32> Key;
typedef std::array<unsigned char, 16> Address;
struct KeysBox {
Key PublicKey;
Key PrivateKey;
};
struct option {
unsigned int proc = 0; // количество потоков
int mode = 1; // режим майнинга
bool log = true; // логгирование
int high = 20; // начальная высота при майнинге: dec(20) == hex(14)
bool letsup = true; // повышение высоты при нахождении
bool mesh = false; // отображение meshname-доменов
bool fullkeys = true; // отображение секретного ключа в консоли в полном формате
std::string str = "aaaa";
std::string outputfile;
int sbt_size = 7; // 64b/8 = 8B, нумерация с нуля
bool sbt_alarm = false; // для симпатичного вывода предупреждения
};
static option conf;
int parameters(option& conf, std::string arg) {
if (arg.find(" ") != std::string::npos) {
const size_t npos = -1;
int position = arg.find(" ");
std::istringstream ss(arg.substr(position + 1)); // Поток нужен для проверки корректности и конвертации
if (arg.find("--threads") != npos || arg.find("-t") != npos) {
ss >> conf.proc;
if (ss.fail()) return 1;
return 0;
}
if (arg.find("--pattern") != npos || arg.find("-p") != npos) {
ss >> conf.str;
if (ss.fail()) return 1;
return 0;
}
if (arg.find("--altitude") != npos || arg.find("-a") != npos) {
ss >> std::hex >> conf.high;
if (ss.fail()) return 1;
return 0;
}
}
else if (arg == "--ip" || arg == "-i") conf.mode = 0;
else if (arg == "--ip-high" || arg == "-ih") conf.mode = 2;
else if (arg == "--regexp" || arg == "-r") conf.mode = 3;
else if (arg == "--regexp-high" || arg == "-rh") conf.mode = 4;
else if (arg == "--mesh" || arg == "-m") conf.mode = 5;
else if (arg == "--mesh-regexp" || arg == "-mr") conf.mode = 6;
else if (arg == "--brute-force" || arg == "-b") conf.mode = 7;
else if (arg == "--increase-none" || arg == "-in") conf.letsup = false;
else if (arg == "--logging-none" || arg == "-ln") conf.log = false;
else if (arg == "--display-mesh" || arg == "-dm") conf.mesh = true;
else if (arg == "--full-pk" || arg == "-fp") conf.fullkeys = true;
else if (arg == "--threads" || arg == "-t") return 777;
else if (arg == "--pattern" || arg == "-p") return 777;
else if (arg == "--altitude" || arg == "-a") return 777;
return 0;
}
void displayConfig() {
unsigned short processor_count = std::thread::hardware_concurrency();
if (conf.proc == 0 || conf.proc > static_cast<unsigned int>(processor_count))
conf.proc = static_cast<unsigned int>(processor_count);
countsize = 80000 * conf.proc;
std::cout << " Threads: " << conf.proc << ", ";
if (conf.mode == 0)
std::cout << "IPv6 pattern (" << conf.str << "), ";
else if (conf.mode == 1) {
std::cout << "high addresses (2" << std::setw(2) << std::setfill('0') <<
std::hex << conf.high << std::dec;
(conf.letsup != 0) ? std::cout << "++), " : std::cout << "+), ";
} else if (conf.mode == 2) {
std::cout << "by pattern (" << conf.str << ") & high (2" <<
std::setw(2) << std::setfill('0') << std::hex << conf.high << std::dec;
(conf.letsup != 0) ? std::cout << "++), " : std::cout << "+), ";
} else if (conf.mode == 3)
std::cout << "IPv6 regexp (" << conf.str << "), ";
else if (conf.mode == 4) {
std::cout << "IPv6 regexp (" << conf.str << ") & high (2" <<
std::setw(2) << std::setfill('0') << std::hex << conf.high << std::dec;
(conf.letsup != 0) ? std::cout << "++), " : std::cout << "+), ";
} else if (conf.mode == 5)
std::cout << "meshname pattern (" << conf.str << "), ";
else if (conf.mode == 6)
std::cout << "meshname regexp (" << conf.str << "), ";
else if (conf.mode == 7)
std::cout << "subnet brute force (" << conf.str << "/" << (conf.sbt_size + 1) * 8 << "), ";
if (conf.log)
std::cout << "logging to text file.";
else
std::cout << "console log only.";
if ((conf.mode == 5 || conf.mode == 6) && conf.mesh == 0)
conf.mesh = 1;
std::cout << std::endl << std::endl;
}
KeysBox getKeyPair() {
KeysBox keys;
unsigned char sk[64];
crypto_sign_ed25519_keypair(keys.PublicKey.data(), sk);
memcpy(keys.PrivateKey.data(), sk, 32);
return keys;
}
std::string getAddress(const Address& rawAddr) {
char ipStrBuf[46];
inet_ntop(AF_INET6, rawAddr.data(), ipStrBuf, 46);
return std::string(ipStrBuf);
}
inline std::string hexArrayToString(const unsigned char* bytes, int length) {
std::string result;
result.reserve(length * 2);
for (int i = 0; i < length; ++i) {
result.push_back("0123456789abcdef"[bytes[i] >> 4]);
result.push_back("0123456789abcdef"[bytes[i] & 0x0F]);
}
return result;
}
inline std::string keyToString(const Key& key) {
return hexArrayToString(key.data(), 32);
}
void getRawAddress(int lErase, Key& InvertedPublicKey, Address& rawAddr) {
lErase++;
const int bitsToShift = lErase % 8;
const int start = lErase / 8;
const int invSize = start + 15;
if (bitsToShift == 0) {
for (int i = start; i < invSize; ++i)
InvertedPublicKey[i] = InvertedPublicKey[i];
} else {
const int complementary = 8 - bitsToShift;
for (int i = start; i < start + 15; ++i) {
InvertedPublicKey[i] = static_cast<unsigned char>((InvertedPublicKey[i] << bitsToShift) | (InvertedPublicKey[i + 1] >> complementary));
}
}
rawAddr[0] = 0x02;
rawAddr[1] = static_cast<unsigned char>(lErase - 1);
memcpy(&rawAddr[2], &InvertedPublicKey[start], 14);
}
inline Key bitwiseInverse(const Key& key) {
Key inverted{};
for (unsigned long i = 0; i < key.size(); i++) inverted[i] = static_cast<unsigned char>(~key[i]);
return inverted;
}
int getOnes(const Key& value) {
int leadOnes = 0;
for (int i = 0; i < 17; ++i) {
if (value[i] == 0xFF) {
leadOnes += 8;
} else {
for (int j = 7; j >= 0; --j) {
if (value[i] & (1 << j))
++leadOnes;
else
return leadOnes;
}
}
}
return leadOnes;
}
void logKeys(const Address& raw, const KeysBox& keys) {
std::cout << std::endl;
std::cout << " Address: " << getAddress(raw) << std::endl;
std::cout << " PublicKey: " << keyToString(keys.PublicKey) << std::endl;
std::cout << " PrivateKey: " << keyToString(keys.PrivateKey);
if (!conf.log || conf.fullkeys) std::cout << keyToString(keys.PublicKey);
std::cout << std::endl << std::endl;
if (conf.log) {
std::ofstream output(conf.outputfile, std::ios::app);
output << std::endl;
output << "Address: " << getAddress(raw) << std::endl;
output << "PublicKey: " << keyToString(keys.PublicKey) << std::endl;
output << "PrivateKey: " << keyToString(keys.PrivateKey) << keyToString(keys.PublicKey) << std::endl;
output.close();
}
}
void process_fortune_key(const KeysBox& keys) {
Key invKey = bitwiseInverse(keys.PublicKey);
Address rawAddr;
getRawAddress(getOnes(invKey), invKey, rawAddr);
logKeys(rawAddr, keys);
}
template <int T>
void miner_thread() {
Address rawAddr;
KeysBox keys;
Key invKey;
while (true) {
keys = getKeyPair();
invKey = bitwiseInverse(keys.PublicKey);
int ones = getOnes(invKey);
getRawAddress(ones, invKey, rawAddr);
bool shouldProcess = false;
if constexpr (T == 0) {
shouldProcess = (getAddress(rawAddr).find(conf.str) != std::string::npos);
} else if constexpr (T == 1) {
if (ones > conf.high) {
if (conf.letsup != 0) {
conf.high = ones;
}
shouldProcess = true;
}
}
if (shouldProcess) {
process_fortune_key(keys);
}
}
}
void startThreads() {
for (unsigned int i = 0; i < conf.proc; ++i) {
std::thread* thread = new std::thread(
conf.mode == 0 ? miner_thread<0> : miner_thread<1>
);
if (i + 1 < conf.proc) thread->detach();
else thread->join();
}
}
void error(int code) {
std::cerr << std::endl << "\
+--------------------------------------------------------------------------+\n\
| Incorrect input, my dear friend. Use --help for usage information. |\n\
+--------------------------------------------------------------------------+\n\
Error code: " << code << std::endl;
}
int main(int argc, char* argv[]) {
if (argc >= 2) {
int res = -1;
for (int i = 1;; ++i) {
if (argv[i] == nullptr) break;
res = parameters(conf, std::string(argv[i]));
if (res == 777) {
++i;
if (argv[i] == nullptr) {
error(776);
std::cerr << " Empty value for parameter \"" << argv[i - 1] << "\"" << std::endl;
return 776;
}
int res2 = parameters(conf, std::string(std::string(argv[i - 1]) + " " + std::string(argv[i])));
if (res2 != 0) {
error(res);
std::cerr << " Wrong value \"" << argv[i] << "\" for parameter \"" << argv[i - 1] << "\"" << std::endl;
return res;
}
}
}
}
displayConfig();
startThreads();
}