I want to use /dev/random
or /dev/urandom
in C. How can I do it? I don't know how can I handle them in C, if someone knows please tell me how. Thank you.

- 106,488
- 23
- 218
- 262

- 883
- 1
- 7
- 4
-
Check out this very informative article on some common caveats of taking this route to (pseudo-)randomness: http://insanecoding.blogspot.fi/2014/05/a-good-idea-with-bad-usage-devurandom.html – appas Jun 17 '15 at 12:19
5 Answers
In general, it's a better idea to avoid opening files to get random data, because of how many points of failure there are in the procedure.
On recent Linux distributions, the getrandom
system call can be used to get crypto-secure random numbers, and it cannot fail if GRND_RANDOM
is not specified as a flag and the read amount is at most 256 bytes.
As of October 2017, OpenBSD, Darwin and Linux (with -lbsd
) now all have an implementation of arc4random
that is crypto-secure and that cannot fail. That makes it a very attractive option:
char myRandomData[50];
arc4random_buf(myRandomData, sizeof myRandomData); // done!
Otherwise, you can use the random devices as if they were files. You read from them and you get random data. I'm using open
/read
here, but fopen
/fread
would work just as well.
int randomData = open("/dev/urandom", O_RDONLY);
if (randomData < 0)
{
// something went wrong
}
else
{
char myRandomData[50];
ssize_t result = read(randomData, myRandomData, sizeof myRandomData);
if (result < 0)
{
// something went wrong
}
}
You may read many more random bytes before closing the file descriptor. /dev/urandom never blocks and always fills in as many bytes as you've requested, unless the system call is interrupted by a signal. It is considered cryptographically secure and should be your go-to random device.
/dev/random is more finicky. On most platforms, it can return fewer bytes than you've asked for and it can block if not enough bytes are available. This makes the error handling story more complex:
int randomData = open("/dev/random", O_RDONLY);
if (randomData < 0)
{
// something went wrong
}
else
{
char myRandomData[50];
size_t randomDataLen = 0;
while (randomDataLen < sizeof myRandomData)
{
ssize_t result = read(randomData, myRandomData + randomDataLen, (sizeof myRandomData) - randomDataLen);
if (result < 0)
{
// something went wrong
}
randomDataLen += result;
}
close(randomData);
}

- 134,922
- 42
- 253
- 328
-
okay, nice answer. And what if I want to set it to read multiple numbers ? Would i do while(something) { read(..) } or should i open/close it everytime the loop starts over ? – stojance Apr 03 '10 at 19:34
-
Hi, can you give me some tips how I can read continuously all the bytes from \dev\random. if it blocks, how can I sense it. But again when more bytes are available I will read them. – karim Nov 02 '10 at 10:23
-
@karim It doesn't block on Mac OS (which I use), and I'm not too sure about how to deal with block files for these circumstances. You should ask a new question for it. – zneak Nov 02 '10 at 17:27
-
16@karim: Please never read all the bytes from /dev/random. Just don't. Your program is probably not the *only* user on the system that needs random bytes. – Zan Lynx Feb 25 '11 at 22:40
-
I need only 256 bytes. then I stop. But sometime I do not get 256 bytes. I have to wait for 1/2 seconds. – karim Feb 26 '11 at 16:17
-
The code in this answer is currently wrong. You need to check the return value of read to see how many bytes were actually read, and loop until you've gotten enough. As-is this code could leave myRandomInteger filled with old memory rather than random data. – morrog Oct 25 '13 at 05:38
-
@morrog, I believe my edit will address the issues you've raised. Also don't forget that you can edit anyone's answer if you feel it's inadequate. – zneak Oct 25 '13 at 15:49
-
1@zneak, sorry I forgot that posts could be edited on here. Thanks for letting me know. Your last modification only added a check on read, instead of a loop. I modified it to use a loop, so the code will now block appropriately. – morrog Oct 26 '13 at 02:31
-
2@morrog Overeager reviewers rejected it, so I did the changes manually. Sorry you don't get credited for it. – zneak Oct 26 '13 at 22:01
-
Actually most cryptographers recommend using `/dev/urandom`. If it has been sufficiently seeded *once*, it will output unlimited amounts of pseudo random numbers suitable for use in crypto. The only worry is that the initial seeding might not have been sufficient. The "less random" issue only applies is some rare special cases, like early in the boot process on embedded devices or clones virtual machines. – CodesInChaos Oct 26 '13 at 22:06
-
1@CodesInChaos, I'm [quoting the Linux manpage](http://linux.die.net/man/4/urandom): "If you are unsure about whether you should use /dev/random or /dev/urandom, then probably you want to use the latter. As a general rule, /dev/urandom should be used for everything except long-lived GPG/SSL/SSH keys." – zneak Oct 26 '13 at 22:09
-
2@zneak Emphasis on *long-lived* since for those it doesn't hurt to be extra paranoid. For normal crypto use `/dev/urandom` is fine. – CodesInChaos Oct 26 '13 at 22:51
-
1However you also need to ensure that /dev/random (or /dev/urandom) is actually the random number device and not a sparse file or a symlink to /dev/zero (which may have happened if your machine has been hacked). There's a good article at http://insanecoding.blogspot.co.uk/2014/05/a-good-idea-with-bad-usage-devurandom.html that goes into all the pitfalls of using /dev/{u}random blindly. – Chris J Jul 23 '14 at 12:07
-
-
1@KyleWpppd, this answer initially checked for no error conditions at all for the sake of simplicity, but someone else decided that it was important enough around `read` to include it. I'd say that in general, you should always check for error conditions. Additionally, if your application is security-critical, it might be a good idea to check that the file is a character device. – zneak Jan 02 '15 at 18:19
-
This answer has been sitting here for 5 years, but I believe the code is wrong. You never even used the file descriptor `randomData` aside from closing it. You sure it shouldn't read `read(randomData ...`? Shows the importance of naming. – BoppreH Jul 31 '15 at 21:18
-
@BoppreH, you'll probably be happy to learn that this specific issue has "only" been around for two years ([someone else suggested](http://data.stackexchange.com/stackoverflow/query/342175) a change that I ended up merging myself without being careful enough). Speaking of suggesting edits, you are very welcome to fix any other issue you find. – zneak Jul 31 '15 at 22:39
-
The last paragraph of this answer is making an incorrect assumption, described here: http://www.2uo.de/myths-about-urandom/#structure. In fact, both `/dev/random` and `/dev/urandom` sit behind the same CSPRNG. (Your advice to pick `/dev/urandom` over `/dev/random` still holds.) – Sebastian Mar 23 '17 at 20:23
There are other accurate answers above. I needed to use a FILE*
stream, though. Here's what I did...
int byte_count = 64;
char data[64];
FILE *fp;
fp = fopen("/dev/urandom", "r");
fread(&data, 1, byte_count, fp);
fclose(fp);

- 10,303
- 5
- 36
- 53

- 5,323
- 3
- 36
- 34
-
1An int can be read directly by simply casting the int pointer to a char pointer. `fread((char*)(&myInt),sizeof(myInt),1,fp)` – Azeem Bande-Ali May 25 '13 at 18:50
-
@AzeemBande-Ali:Why don't you use fread((int*)(&myInt),sizeof(myInt),1,fp) instead ? I mean a cast to int* ? – Larry May 30 '14 at 15:20
-
4In neither case should a cast be used in C code, fread() takes a void *, so just do fread(&myInt, ... ); – nos Jan 02 '15 at 21:12
-
-
@CalculatorFeline The byte_count here is a bit confusing, op maybe initially wanted each index to have same byte length, but this could not do ... – LinconFive Mar 19 '20 at 06:51
Just open the file for reading and then read data. In C++11 you may wish to use std::random_device
which provides cross-platform access to such devices.
-
It appears that `std::random_device` didn't make it into the 2011 standard. It does appear in the [N3797 draft](https://isocpp.org/files/papers/N3797.pdf). – Keith Thompson Jan 02 '15 at 19:31
-
2Looks like [`std::random_device`](http://en.cppreference.com/w/cpp/numeric/random/random_device) _did_ make it into C++11 in the end. – legends2k Jun 26 '15 at 14:14
-
1Problem is that ``std::random_device`` is in C++ and not in C, and the OP asked how to use ``/dev/random`` or ``/dev/urandom`` not how to use ``std::random_device`` although it is a good choice to use ``std::random_device`` and it has benefits, it is just not what the OP asked for – Nfagie Yansaneh Aug 08 '17 at 09:20
Zneak is 100% correct. Its also very common to read a buffer of random numbers that is slightly larger than what you'll need on startup. You can then populate an array in memory, or write them to your own file for later re-use.
A typical implementation of the above:
typedef struct prandom {
struct prandom *prev;
int64_t number;
struct prandom *next;
} prandom_t;
This becomes more or less like a tape that just advances which can be magically replenished by another thread as needed. There are a lot of services that provide large file dumps of nothing but random numbers that are generated with much stronger generators such as:
- Radioactive decay
- Optical behavior (photons hitting a semi transparent mirror)
- Atmospheric noise (not as strong as the above)
- Farms of intoxicated monkeys typing on keyboards and moving mice (kidding)
Don't use 'pre-packaged' entropy for cryptographic seeds, in case that doesn't go without saying. Those sets are fine for simulations, not fine at all for generating keys and such.
Not being concerned with quality, if you need a lot of numbers for something like a monte carlo simulation, it's much better to have them available in a way that will not cause read() to block.
However, remember, the randomness of a number is as deterministic as the complexity involved in generating it. /dev/random
and /dev/urandom
are convenient, but not as strong as using a HRNG (or downloading a large dump from a HRNG). Also worth noting that /dev/random
refills via entropy, so it can block for quite a while depending on circumstances.
-
2Downloading "large file dumps of nothing but random numbers" is terrible advice for cryptograhic purposes. It's asking someone else to provide the seed to your functions, and those services seem to transfer that data unencrypted over the internet. Please don't do that. – dequis Jul 09 '14 at 14:07
-
@dequis I clarified. I see no problem with using them to run large simulations, _kinda_ thought it would be common sense to not use them for keygen / etc, but it's worth being oddly specific to the point. The question was endeavor-agnostic, so it really didn't occur to me to be so specific, but good point. – Tim Post Jul 28 '15 at 16:27
zneak's answer covers it simply, however the reality is more complicated than that. For example, you need to consider whether /dev/{u}random really is the random number device in the first place. Such a scenario may occur if your machine has been compromised and the devices replaced with symlinks to /dev/zero or a sparse file. If this happens, the random stream is now completely predictable.
The simplest way (at least on Linux and FreeBSD) is to perform an ioctl call on the device that will only succeed if the device is a random generator:
int data;
int result = ioctl(fd, RNDGETENTCNT, &data);
// Upon success data now contains amount of entropy available in bits
If this is performed before the first read of the random device, then there's a fair bet that you've got the random device. So @zneak's answer can better be extended to be:
int randomData = open("/dev/random", O_RDONLY);
int entropy;
int result = ioctl(randomData, RNDGETENTCNT, &entropy);
if (!result) {
// Error - /dev/random isn't actually a random device
return;
}
if (entropy < sizeof(int) * 8) {
// Error - there's not enough bits of entropy in the random device to fill the buffer
return;
}
int myRandomInteger;
size_t randomDataLen = 0;
while (randomDataLen < sizeof myRandomInteger)
{
ssize_t result = read(randomData, ((char*)&myRandomInteger) + randomDataLen, (sizeof myRandomInteger) - randomDataLen);
if (result < 0)
{
// error, unable to read /dev/random
}
randomDataLen += result;
}
close(randomData);
The Insane Coding blog covered this, and other pitfalls not so long ago; I strongly recommend reading the entire article. I have to give credit to their where this solution was pulled from.
Edited to add (2014-07-25)...
Co-incidentally, I read last night that as part of the LibReSSL effort, Linux appears to be getting a GetRandom() syscall. As at time of writing, there's no word of when it will be available in a kernel general release. However this would be the preferred interface to get cryptographically secure random data as it removes all pitfalls that access via files provides. See also the LibReSSL possible implementation.

- 30,688
- 6
- 69
- 111
-
4An attacker with enough power to replace /dev/random or /dev/urandom with something else typically also has enough power to load a kernel module to screw up every attempt that you make at determining if it's a random device or not. – zneak Jan 02 '15 at 20:39
-
The [man page](http://man7.org/linux/man-pages/man2/getrandom.2.html) says `getrandom()` was introduced in kernel 3.17. So stock Ubuntu 16.04 doesn't have it as of 2018-01-17. Run `uname -a` in a terminal to check your kernel version. – erapert Jan 17 '18 at 18:01