#ifndef FORTUNA_FORTUNA_CPP #define FORTUNA_FORTUNA_CPP #include "fortuna.h" #include "util.h" #include #include #include namespace fortuna { static constexpr const unsigned int min_pool_size{64}; auto now{std::chrono::steady_clock::now()}; Fortuna::Fortuna() { try { initialize_prng(); } catch(CryptoPP::Exception& e) { fmt::print(stderr, "{}\n", e.what()); } th_gen = std::thread(generator_service, &R.Gen); th_sfm = std::thread(seed_file_manager_service); } Fortuna::~Fortuna() noexcept { th_gen.join(); th_sfm.join(); } auto Fortuna::random_data(unsigned int n_bytes) -> void { const auto start{std::chrono::system_clock::now()}; fmt::print("random_data starting - {}\n", start); auto elapsed { std::chrono::duration_cast( std::chrono::steady_clock::now().time_since_epoch() - now.time_since_epoch() ) }; fmt::print("last_reseed: {} ago\n", elapsed); now = std::chrono::steady_clock::now(); std::string s; // synchronise reads and writes to the between // {generator,accumulator,fortuna} service threads std::unique_lock uq_lock(mtx); const int pools_to_use{ffsll(static_cast(get_reseed_ctr()))}; if (R.pools[0].get_s_length() >= min_pool_size && elapsed > R.Gen.reseed_interval) { for (int i = 0; i < static_cast(pools_to_use); ++i) { if (R.reseed_ctr % static_cast(pow(2,i)) == 0) { try { s.append(fortuna::Util::do_sha(R.pools[i].get_s())); R.pools[i].clear_pool(); } catch(std::exception& e) { fmt::print("{}\n", e.what()); } } } incr_reseed_ctr(); R.Gen.reseed(s); R.last_reseed = std::chrono::steady_clock::now(); s.clear(); } if (R.reseed_ctr == 0) { fmt::print("reseed ctr is 0, PRNG not seeded!\n"); throw std::runtime_error("illegal state, PRNG not seeded"); } else { std::string n{R.Gen.generate_random_data(n_bytes)}; fmt::print("got you {} proper bytes from generate_random_data -> {}\n", n_bytes, n); n.clear(); } uq_lock.unlock(); const auto end{std::chrono::system_clock::now()}; std::chrono::duration diff = end-start; fmt::print("random_data done - {}\n", end); fmt::print("getting random data took {:.{}f}s\n", diff.count(), 12); } //random_data auto Fortuna::generator_service(fortuna::generator::Generator* Gen) -> void { fmt::print("[i] fortuna: starting generator service\n"); int i{0}; uint sleep_time{1000}; // in ms std::chrono::system_clock::time_point time_point; while(true) { fmt::print("sleeping [{}]\n", i); ++i; time_point = fortuna::Util::current_time(); fmt::print("[*] g: @{}\n", time_point); std::this_thread::sleep_until( time_point + std::chrono::milliseconds(sleep_time) ); } } auto Fortuna::seed_file_manager_service() -> void { // TODO(me): implement proper logic, i.e. include SeedFileManager fmt::print("[i] fortuna: starting seed file manager service\n"); // FIXME: proper interval is 10 minutes uint interval{1}; // in seconds auto now{fortuna::Util::current_time()}; while(true) { now = fortuna::Util::current_time(); fmt::print("[*] sfm: hello now @{}\n", now); std::this_thread::sleep_until(now + std::chrono::seconds(interval)); } } } // namespace fortuna #endif//FORTUNA_FORTUNA_CPP