Skip to content
Snippets Groups Projects
Commit 29c83d9c authored by Adrien Béraud's avatar Adrien Béraud
Browse files

rng: improve getSeededRandomEngine

* Make sure to use 32 bit input for std::seed_seq
* Retry using random device every use
* Adjust delays and retry count to keep approx. the same max timeout.
 In practice the actual average timeout should be reduced, because
 the algo doesn't lose existing data and can move forward in case
 of occasional failure/retry.
parent abbc7774
No related branches found
No related tags found
No related merge requests found
...@@ -110,21 +110,47 @@ using random_device = std::random_device; ...@@ -110,21 +110,47 @@ using random_device = std::random_device;
using random_device = std::random_device; using random_device = std::random_device;
#endif #endif
template<class T = std::mt19937, std::size_t N = T::state_size> /**
* Generate a seeded random engine.
*/
template<class T = std::mt19937, std::size_t N = T::state_size+1>
auto getSeededRandomEngine() -> typename std::enable_if<!!N, T>::type { auto getSeededRandomEngine() -> typename std::enable_if<!!N, T>::type {
typename T::result_type random_data[N]; std::array<typename T::result_type, N> random_data;
for (unsigned i=0; i<256; i++) { constexpr auto gen = [](random_device& source) -> typename T::result_type {
for (unsigned j=0; j<64; j++) {
try {
return source();
} catch (...) {
std::this_thread::sleep_for(std::chrono::microseconds(500));
}
}
throw std::runtime_error("Can't generate random number");
};
for (unsigned i=0; i<8; i++) {
try { try {
random_device source; random_device source;
std::generate(std::begin(random_data), std::end(random_data), std::ref(source)); for (auto& r : random_data)
std::seed_seq seeds(std::begin(random_data), std::end(random_data)); r = gen(source);
T seededEngine (seeds); std::seed_seq seed(
return seededEngine; (std::seed_seq::result_type*)random_data.data(),
(std::seed_seq::result_type*)(random_data.data() + random_data.size()));
return T(seed);
} catch (...) { } catch (...) {
std::this_thread::sleep_for(std::chrono::milliseconds(1)); std::this_thread::sleep_for(std::chrono::microseconds(500));
}
} }
throw std::runtime_error("Can't seed random seed");
} }
throw std::runtime_error("Can't seed random engine");
/**
* Generate a random engine from another source.
*/
template<class T = std::mt19937, std::size_t N = T::state_size+1>
auto getDerivedRandomEngine(T& source) -> typename std::enable_if<!!N, T>::type {
std::array<typename T::result_type, N> random_data;
std::generate(random_data.begin(), random_data.end(), std::ref(source));
std::seed_seq seed(random_data.begin(), random_data.end());
return T(seed);
} }
}} // dht::crypto }} // dht::crypto
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment