I would like to do something like this:
boost::random_device rd;
boost::random::mt19937_64 gen(rd());
boost::random::uniform_int_distribution<unsigned long long> dis;
uint64_t value = dis(gen);
But I've read that a mersenne twister is not cryptographically secure. However, I've also read that a random_device could be, if its pulling data from /dev/urandom which is likely on a linux platform (my main platform). So if the random_device is non-deterministically random and its used to seed the mersenne twister (as shown above), doesn't that also make the mersenne twister cryptographically secure (even though by itself, it isn't)?
I'm a bit of a novice in this arena so any advice is appreciated.
So, how can I generate a cryptographically secure 64 bit number that can be stored in a uint64_t?
Thanks,
Ben.
Using the random device just for seeding isn't really cryptographically secure. The problem is then reduced to figuring out the initial seed, which is a greatly reduced problem. Instead, directly use the random device.
For greater security, initialize the random device with
/dev/random
rather than/dev/urandom
./dev/random
will block if there isn't enough "entropy", until some random things have happened. However, it may be much, much slower.BTW, assuming that you have a high-quality C++11 implementation that doesn't return bogus values for the
entropy
function, using C++11 might be a better idea if you are trying to remove dependencies.EDIT: Apparently there is some debate about whether or not /dev/random is any better than /dev/urandom. I refer you to this.
Analyzing your question is harder than it might seem:
You seed the mersenne twister with
rd()
, which returns anunsigned int
, and therefore (on most platforms) contains at most 32 random bits.Everything that the mersenne twister does from this point on is determined by those 32 bits.
This means that the
value
can only take on 2**32 different values, which can be a problem if any attack vector exists that attacks whatever you do with this number by brute force. In fact, the mersenne twister's seeding routine may even reduce the number of possible values for the first result, since it distributes the 32 random bits over its complete state (to ensure that this is not the case you would have to analyse the seed routine boost uses).The primary weakness of the mersenne twister (its state can be derived after seeing 624 numbers) is not even of interest in this case however, since you generate a sequence that is so short (1 value).
Generating 64 cryptographically secure bits
Assuming that
unsigned int
is equivalent touint32_t
on your platform, you can easily generate 64 cryptographically secure random bits by usingboost::random_device
:This is fairly secure, since the implementations for both linux and windows use the operating system's own cryptographically secure randomness sources.
Generating cryptographically secure values with arbitrary distributions
While the previous works well enough, you may wish for a more flexible solution. This is easy to do by realizing that you can actually use the random distributions boost provides with
random_device
as well. A simple example would be to rewrite the previous solution like this:(While this can in theory also provide a more robust solution if the previous one does not actually contain a number in [0, 2**32), this is not a problem in practice.)
Binding distribution to generator
To improve usability you will often find usage of
boost::bind
to bind distribution and generator together. Sinceboost::bind
copies its arguments, and the copy ctor is deleted forboost::random_device
, you need to use a little trick: