Have a look at this Mersenne Twister random-number generator function that I've written based on what I found on SO.
As I am a beginner and don't understand half of the stuff below, I would very much appreciate if you guided me a little on my journey to improving this random number generator.
I don't need it to be fast, I just want it to be secure.
I want it to be more or less the most secure way of generating numbers.
All that, because I plan on generating random passwords with it later on.
#include <iostream>
#include <random>
unsigned long long int random_integer(unsigned long long int rand_min, unsigned long long int rand_max)
{
// initialize = seed the random device
std::random_device random_device;
// use Mersenne Twister as random-number generator engine
std::mt19937 random_number_generator(random_device());
// number distribution, guaranteed unbiased
std::uniform_int_distribution<int> number_distribution(rand_min, rand_max);
return number_distribution(random_number_generator);
}
int main()
{
for (int i = 1; i <= 10; i++)
{
std::cout << random_integer(1, 1000) << std::endl;
}
return 0;
}
Notes:
I'm on Linux.
Compiler is
g++5
.Standard being C++17.
-
\$\begingroup\$ Follow-up #1: codereview.stackexchange.com/q/180220/104270 \$\endgroup\$Vlastimil Burián– Vlastimil Burián2017年11月12日 10:37:10 +00:00Commented Nov 12, 2017 at 10:37
-
\$\begingroup\$ Mersenne Twister will never be secure. It was not created for cryptographic security. It would be trivial for someone capturing even a little bit of the output to be able to reconstruct the state of the internals and then predict everything else you generate. If you want crypto-level security, you'll need a crypto-level algorithm. MT is fast and has good randomness for simulation but horrible randomness for security. \$\endgroup\$Snowbody– Snowbody2017年12月09日 06:15:42 +00:00Commented Dec 9, 2017 at 6:15
1 Answer 1
Math
Well, I believe usually you could avoid the math, but this is a special case. The main things to cover is random variable, random functions and distributions. It is gonna help a lot. Do note that int distribution is discrete, whereas real distribution is continuous.
Code Review
Incorrect usage of twister
First of all,
std::mt19937
generates only 32 bit random numbers. This means that by truncating it toint
(not always, depends on the platform), the code will discard higher (or lower) 16 bits of the number.The twister has state, which means that when function generates one random number, it will discard the state and start from scratch when called again. Although
std::random_device
might normalize the behavior, the output will not be as intended.Incorrect usage of distribution
std::uniform_distribution
has a constructor takingT min, T max
, which means thatunsigned long long
will overflow the arguments, which I believe is undefined behavior.Return type is
unsigned long long
, but generates values are of typeint
, which means that higher (or lower) bits will be zero or garbage. Both of the cases are wrong.
Different solution
If you want a generator without all of the hoops to jump through, just slam everything into a class. Here is the rough sketch (might not compile):
#include <random>
class uniform_int_generator
{
std::mt19937_64 twister;
public:
uniform_int_generator():
twister(std::random_device{}())
{}
unsigned long long operator()(unsigned long long min_val, unsigned long long max_val)
{
std::uniform_int_distribution<unsigned long long> distr(min_val, max_val);
return distr(twister);
}
};
You might want to add some customization points using templates. Anyway, if you need more, make this one compile and post question with the updated code.
-
\$\begingroup\$ NOTE: this example is passing arguments for
min
andmax
in the wrong order to uniform_int_distribution. It probably would make sense to re-order the function arguments ofoperator()
as well. \$\endgroup\$Chris Uzdavinis– Chris Uzdavinis2021年12月03日 17:13:32 +00:00Commented Dec 3, 2021 at 17:13