Should I use a random engine seeded from std::random_device or use std::random_device every time

后端 未结 6 1761
梦如初夏
梦如初夏 2020-12-30 00:16

I have a class that contains two sources of randomness.

std::random_device rd;
std::mt19937 random_engine;

I seed the std::mt19937

相关标签:
6条回答
  • 2020-12-30 00:27

    If you are not using it for encryption it is fine and well to repeatedly use mt19937 which is seeded by random_engine.

    For the rest of this answer, I assume you are using the random numbers for encryption in your networking code. In short, mt19937 is not suitable for that use.

    http://en.wikipedia.org/wiki/Mersenne_twister#Disadvantages

    There is a potential risk that you will leak information (perhaps indirectly) over time so that an attacker could start to predict the random numbers. At least in theory, but this is what it's about. From Wikipedia

    ...since this figure is the size of the state vector from
    which future iterates are produced) allows one to predict all future iterates.

    A simple means of preventing random number generation information to leak to the user is to use one-way hash functions, but there's much more to it. You should use a random number generator designed for that purpose:

    http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator

    Various examples (with code) are found here http://xlinux.nist.gov/dads/HTML/pseudorandomNumberGen.html

    0 讨论(0)
  • 2020-12-30 00:28

    You may want to have a look at http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful that explains why you should use uniform_int_distribution, and the relatives strengths of random_device / mt19937.

    In this video, Stephan T. Lavavej specifically states that on visual C++, random_device can be used for cryptographic purposes.

    0 讨论(0)
  • 2020-12-30 00:31

    If you need randomness for a simulation or a game, then that you're doing is fine. Call the random device just once, and do everything else with a randomly seeded pseudo-RNG. As a bonus, you should store the seed value in a log file so you can later replay the pseudo-random sequence:

    auto const seed = std::random_device()();
    // save "seed" to log file
    std::mt19937 random_engine(seed);
    

    (For multiple threads, use the PRNG in the main thread to generate seeds for further PRNGs in the spawned threads.)

    If you need a lot of true randomness for cryptographic purposes, then a PRNG is never a good idea, though, since a long sequence of output contains a lot less randomness than true randomness, i.e. you can predict all of it from a small subset. If you need true randomness, you should collect it from some unpredictable source (e.g. heat sensors, user keyboard/mouse activity, etc.). Unix's /dev/random may be such a "true randomness" source, but it may not fill up very quickly.

    0 讨论(0)
  • 2020-12-30 00:36

    The answer is platform dependent. I seem to remember that with Visual C++ 2010, std::random_device is just mt19937 seeded in some undocumented way.

    Of course you realize that any ad hoc encryption scheme based on a random number generator is likely to be very weak.

    0 讨论(0)
  • 2020-12-30 00:45

    The standard practice, as far as I am aware, is to seed the random number generator with a number that is not calculated by the computer (but comes from some external, unpredictable source). That should be the case with your rd() function. From then on, you call the pseudo-random number generator(PRNG) for each and every pseudo-random number that you need.

    If you are worried about the numbers not being random enough, then you should pick a different PRNG. Entropy is a scarce and precious resource and should be treated as such. Although, you may not be needing that many random numbers right now, you may in the future; or other applications could need them. You want that entropy to be available whenever an application asks for it.

    It sounds like, for your application, that the mersenne twister will suit your needs just fine. No one who plays your game will ever feel like the teams that are loaded aren't random.

    0 讨论(0)
  • 2020-12-30 00:48

    Assuming this is not for cryptographic purposes, the most important thing to remember about random number generation is to think of how you want the distribution of the random numbers to be and what is the range you are expecting.

    Usually standard random number generators within libraries are designed to give out uniform distribution. So the numbers will range between 0 and some RAND_MAX ( say on 32 bit machine it is 2^31 -1 )

    Now here is the thing to remember with pseudo random number generators. Most of them are designed to generate random numbers and not random bits. The difference is subtle. If you need numbers between 0 and 8 most programmers will say rand()%8 This is bad because the algorithm was for randomizing 32 bits. But you are using only the bottom 3 bits. No good. This will not give you a uniform distribution (assuming that is what you are looking for)

    You should use 8 * (rand() + 1) / (RAND_MAX) which will now give you a uniformly random number between 0 and 8.

    Now with hardware random number generators you may have random bits being produced. If that is indeed the case, then you have each bit independently being generated. Then it is more like a set of identical independent random bits. The modeling here would have to be a bit different. Keep that in mind, especially in simulations the distribution becomes important.

    0 讨论(0)
提交回复
热议问题