I need many cryptographically secure numbers, so I was thinking about extracting randomness from /dev/urandom
and then "converting" it into (say) unsigned long long int
. I guess it should be very efficient and it seems it is cryptographically secure, but I will investigate this aspect more in the future.
Now the question is: how can I do so?
I found this code:
char * block;
short size = 1;
ifstream urandom("/dev/urandom", ios::in|ios::binary);
urandom.read(block,size);
urandom.close();
Does it make sense? And how do I convert what I get to the type I desire?
EDIT - Using random
interface of C++11
Following a suggestion from the comments, I tried using a uniform distribution over the integers and a random_device
initialized as /dev/urandom
. Here is the code:
std::uniform_int_distribution<unsigned int> dist(0, modulus-1);
std::random_device urandom("/dev/urandom");
for(unsigned int i = start ; i < end ; ++i)
{
vector[i] = dist(urandom);
}
The problem is that this code is approximately 1000 times slower than before (I was using a xorshift128+ generator): 5 milliseconds vs. almost 5 seconds. Is this normal? Honestly, I thought that streaming bytes in from /dev/urandom
and converting them to unsigned int
would have been way faster... Am I missing something?
So first of your example is incorrect and would cause undefined behaviour.
The
char*
block isn't pointing to any allocated data, so theifstream::read
would actually write into unallocated memory.Apart from this the type of
size
issigned short
while it should besize_t
.In order to read a
unsigned long long int
you could use `ifstream' like this:The interesting part would be where this actually reads with
urandom.read(reinterpret_cast<char*>(&random_value), size);
The
size
should be clear. By usingsizeof
we get the actual size in bytes of the data we want to store the random value into. This is useful as this value might be different on different architectures (e.g. 32-bit and 64-bit).Be careful if the data type you pass here is a pointer.
sizeof
will only return the size of the pointer and not the size of the data it is pointing to.random_value
is of typeunsigned long long int
. So&random_value
is the type of the appropriate pointerunsigned long long int*
. But we want to read bytes (char
) and therefore need to change/cast the value fromunsigned long long int*
tochar*
(reinterpret_cast<char*>(&random_value)
).