2
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Follow-up #1: codereview.stackexchange.com/q/180220/104270 \$\endgroup\$ – LinuxSecurityFreak Nov 12 '17 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 Dec 9 '17 at 6:15
3
\$\begingroup\$

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 to int (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 taking T min, T max, which means that unsigned long long will overflow the arguments, which I believe is undefined behavior.

    Return type is unsigned long long, but generates values are of type int, 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 max_val, unsigned long long min_val)
    {
        std::uniform_int_distribution<unsigned long long> distr(max_val, min_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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.