#include "PrecomputedPuzzles.h" #include "../../Configuration.h" #include "../ConnectedClient.h" #include using namespace std; using namespace ts; using namespace ts::protocol; PuzzleManager::PuzzleManager() {} PuzzleManager::~PuzzleManager() {} size_t PuzzleManager::precomputedPuzzleCount() { return this->cached.size(); } bool PuzzleManager::precomputePuzzles(size_t limit) { while(precomputedPuzzleCount() < limit) generatePuzzle(); return true; } std::shared_ptr PuzzleManager::nextPuzzle() { this->indexLock.lock(); size_t index = this->cacheIndex++ % this->cached.size(); this->indexLock.unlock(); return this->cached[index]; } inline void rndNum(mp_int *result, int byteLength){ uint8_t buffer[byteLength]; for(int index = 0; index < byteLength; index++) { int rnd = rand(); uint8_t urnd = static_cast(rnd & 0xFF); buffer[index] = urnd; //TODO more secure! } mp_zero(result); mp_read_unsigned_bin(result, buffer, byteLength); } inline bool solvePuzzle(Puzzle *puzzle){ mp_int exp{}; mp_init(&exp); mp_2expt(&exp, puzzle->level); if (mp_exptmod(&puzzle->x, &exp, &puzzle->n, &puzzle->result) != CRYPT_OK) { //Sometimes it fails (unknow why :D) mp_clear(&exp); return false; } mp_clear(&exp); return true; } void PuzzleManager::generatePuzzle() { auto puzzle = new Puzzle{}; mp_init_multi(&puzzle->x, &puzzle->n, &puzzle->result, nullptr); generate_new: rndNum(&puzzle->x, 64); rndNum(&puzzle->n, 64); puzzle->level = ts::config::voice::RsaPuzzleLevel; if(!solvePuzzle(puzzle)) { //logFatal("RSA fail at " + to_string(this->cached.size())); goto generate_new; } auto valid_x = mp_unsigned_bin_size(&puzzle->x) <= 64; auto valid_n = mp_unsigned_bin_size(&puzzle->n) <= 64; auto valid_result = mp_unsigned_bin_size(&puzzle->result) <= 64; if(!valid_n || !valid_x || !valid_result) goto generate_new; memset(puzzle->data_x, 0, 64); memset(puzzle->data_n, 0, 64); memset(puzzle->data_result, 0, 64); mp_to_unsigned_bin(&puzzle->x, puzzle->data_x); mp_to_unsigned_bin(&puzzle->n, puzzle->data_n); mp_to_unsigned_bin(&puzzle->result, puzzle->data_result); this->cached.push_back(shared_ptr(puzzle, [](Puzzle* elm){ mp_clear_multi(&elm->n, &elm->x, &elm->result, nullptr); delete elm; })); }