7

I am trying to generate a good random seed for a psudo-random number generator. I thought I'd get the expert's opinions. let me know if this is a bad way of doing it or if there are much better ways.

#include <iostream>
#include <cstdlib>
#include <fstream>
#include <ctime>

unsigned int good_seed()
{
    unsigned int random_seed, random_seed_a, random_seed_b; 
    std::ifstream file ("/dev/random", std::ios::binary);
    if (file.is_open())
    {
        char * memblock;
        int size = sizeof(int);
        memblock = new char [size];
        file.read (memblock, size);
        file.close();
        random_seed_a = int(memblock);
        delete[] memblock;
    }// end if
    else
    {
        random_seed_a = 0;
    }
    random_seed_b = std::time(0);
    random_seed = random_seed_a xor random_seed_b;
    return random_seed;
} // end good_seed()
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
posop
  • 511
  • 2
  • 7
  • 17

7 Answers7

5

The code that reads from /dev/random seems wrong: you're C-style casting the address of your character buffer into random_seed_a (plug for C++ casts here) and ignoring anything you actually read from /dev/random (try *reinterpret_cast<int*>(memblock).

/dev/random should already be a good entropy source, so if it's available don't possibly taint the value with any other data and just use it as the seed directly. If there isn't enough data in /dev/random I would just fall back on the time and use that by itself rather than xor'ing it with something.

Mark B
  • 95,107
  • 10
  • 109
  • 188
  • 2
    according to my studies a non-deterministic random variable "dev/urandom" xor-ed with a not so random variable time(0) will still be a non-deterministic random variable. – posop Apr 14 '10 at 23:13
5

Good pseudo-random number generators don't need a "good" seed, any seed (that's different from run to run) works equally well.

Using system time directly is fine (and common). Using /dev/random is also fine.

If your pseudo-random number generator isn't good, even picking a "good" seed won't help. Replace it if you can.

Suggestions: Mersenne twister is a pretty well regarded. Here's a precursor which will run on even the most limited of systems.

Jon-Eric
  • 16,977
  • 9
  • 65
  • 97
  • 3
    Depending on the purpose, a pseudo-random number generator may need an unpredictable seed. There was an on-line poker game that fed the time into what may have been a decent PRNG, which meant that it was possible, by observing some cards, to figure out where the PRNG started, and hence to know the whole deck. – David Thornley Apr 14 '10 at 21:07
  • 3
    If it's *at all* important for users to not be able to predict the random number sequence, then you want a cryptographically secure generator, not a pseudorandom generator. (You're crazy if you base real-money gambling on a pseudorandom generator.) – Jon-Eric Apr 14 '10 at 21:15
  • Just FYI, with Mersenne twister, you have to observe 624 consecutive cards (12 decks) before you know all the future cards. – Jon-Eric Apr 14 '10 at 21:30
  • True. To give the poker site due credit, they weren't gambling their own money, although I suspect they lost business once word got around. – David Thornley Apr 14 '10 at 21:31
2

Ok here's the changes I made after considering your input. Thanks for everything by the way!

unsigned int good_seed()
{
    unsigned int random_seed, random_seed_a, random_seed_b; 
    std::ifstream file ("/dev/urandom", std::ios::binary);
    if (file.is_open())
    {
        char * memblock;
        int size = sizeof(int);
        memblock = new char [size];
        file.read (memblock, size);
        file.close();
        random_seed_a = *reinterpret_cast<int*>(memblock);
        delete[] memblock;
    }// end if
    else
    {
        random_seed_a = 0;
    }
    random_seed_b = std::time(0);
    random_seed = random_seed_a xor random_seed_b;
    std::cout << "random_seed_a = " << random_seed_a << std::endl;
    std::cout << "random_seed_b = " << random_seed_b << std::endl;
    std::cout << " random_seed =  " << random_seed << std::endl;
    return random_seed;
} // end good_seed()
posop
  • 511
  • 2
  • 7
  • 17
1

Traditionally, we've used first or second user input to seed our values as the (tics to millisecond range) amount of time it takes them to respond is pretty variable.

Michael Dorgan
  • 12,453
  • 3
  • 31
  • 61
1

Maybe you should prefer /dev/urandom/ over /dev/random. The latter blocks on Linux if there is not enough entropy available, which can easily happen if the program runs on a machine without user interaction. In case you cannot open /dev/urandom, you could throw an exception instead of using a fallback.

Philipp
  • 48,066
  • 12
  • 84
  • 109
1

"Good" generators, "Bad generators" it doesn't mean anything. "Anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin." - John von Neumann. Every such generator is just a deterministic algorithm. It's very important to have initial states ( seed ) that bring enough entropy. Depending on what you need, you should test your generator quality. Monte Carlo method is a very good estimator of a pseudo random number generator.

bartek
  • 505
  • 1
  • 4
  • 19
0

Define good. :-)

Is it important to find a seed quickly, or that the seed be as random as possible no matter how long it takes to put together?

For a balance - definitely not the most random, definitely not the fastest...

  • When it's first called, take the system time, in milliseconds.
  • Run that through a hash function, like SHA-1.
  • Use the result as the seed.

That should give you a mostly-random 160 bits, which is 10^50th or so of variability. The hash will take a split second to run, so this isn't lightning fast, but has been a good balance in the past for me.

Dean J
  • 39,360
  • 16
  • 67
  • 93
  • I'd like to have as random as possible for my application, but I'd be interested in a fast solution too. – posop Apr 14 '10 at 20:22
  • 3
    @DeanJ The hash is superfluous. Just seed with the system time directly. What you're trying to accomplish with the hash is what (a good) pseudo random number generator already *does* (better). – Jon-Eric Apr 14 '10 at 20:34
  • Jon-Eric is 100% correct; on the other hand, I'm used to working with bad random number generators, couldn't tell a good one from a bad one, and tend to stick with (quick) overkill. – Dean J Apr 14 '10 at 20:43