Reputation: 340
On ubuntu the program uses
FILE *randomSource = fopen("/dev/urandom", "rb");
int byteCount = fread(buf, sizeof(unsigned char), num, randomSource);
And I would like to replace this with rand() from stdlib because I need to use it in an environment where there is no /dev/urandom. I've tried this way:
buf = malloc (num);
int i;
for (i = 0; i < num; i++)
{
buf[i] = rand ();
}
But apparently it is not equivalent because the program fails. The result should be n random bytes with buf pointing to the first.
I tried it like this too, still fails.
randomBytes(unsigned char *buf, const int num)
{
buf = malloc (num * sizeof *buf);
int i;
for (i = 0; i < num; i++)
{
buf[i] = rand ();
}
return 0;
}
The original function I am trying to replace is:
randomBytes(unsigned char *buf, const int num)
{
FILE *randomSource = fopen("/dev/urandom", "rb");
if (!randomSource)
{
return -1;
}
int byteCount = fread(buf, sizeof(unsigned char), num, randomSource);
if (byteCount < num)
{
return -1;
}
fclose(randomSource);
return 0;
}
The purpose of it is just to test an idea not a cryptographic application.
Upvotes: 0
Views: 625
Reputation: 58695
You don't need to malloc
anything in the function randomBytes()
. The parameter buf
already points to a buffer sufficient to hold num
bytes. All you have to do is fill it.
randomBytes(unsigned char *buf, const int num)
{
int i;
for (i = 0; i < num; i++)
{
buf[i] = rand ();
}
return 0;
}
When you did buf = malloc()
, you overwrote your parameter buf
with a pointer to a new block of memory, and wrote the random bytes in the new block. The original block, which the caller expected to have filled by random bytes, was therefore not touched. Moreover, the new block you allocated is never freed, and after randomBytes
returns, you no longer have any pointers to it, so it is leaked. (Remember that C functions pass arguments by value, so assigning to the parameter buf
itself has no effect on any variables in any other functions - though assigning to buf[i]
is a different story.) So all around, that is not what you want to do.
This could be made a bit more efficient, since rand()
returns a random value between 0 and RAND_MAX
which is usually something like 31 bits of randomness, so you could fill more than one byte per call to rand()
. But it should certainly suffice to get started.
Don't forget to call srand()
somewhere in your program if you don't want to get the same sequence of random bytes on every run.
Finally, keep in mind that on many systems rand()
is a rather low quality random number generator. In particular, it absolutely must not be used for any cryptographic purposes, or for games of chance where there is money at stake.
Upvotes: 2
Reputation: 1
You don't explain how does the program fails. Read more about rand and consider seeding your PRNG. You might be interested by the Mersenne twister: on some platforms it is a much better PRNG that rand
. Without seeding rand
has a reproducible behavior.
Also malloc can fail, and you don't test against that. If malloc
fails, buf
is NULL
, and the first loop of your for
invokes undefined behavior: you dereferences the NULL
pointer (probably a segmentation fault).
Suggested reading: How to debug small programs.
Consider compiling your code on Ubuntu with gcc -Wall -Wextra -g
. You might get useful warnings.
Consider using valgrind on Ubuntu.
I tried this
randomBytes(unsigned char *buf, const int num)
{
buf = malloc (num * sizeof *buf);
int i;
You are overwriting the buf
passed in argument. Better yet not even pass it (and perhaps return such a buffer).
Please read Modern C, then some good C programming site, the documentation of your debugger (on Ubuntu, of GDB), the documentation of your compiler (on Ubuntu, of GCC) then the C11 standard (n1570).
Upvotes: 1