В целом, лучше избегать открывать файлы для получения случайных данных из-за того, сколько точек сбоя есть в процедуре.
В последних дистрибутивах Linux системный вызов getrandom
можно использовать для получения крипто-защищенных случайных чисел, и он не может завершиться ошибкой , если GRND_RANDOM
равно , а не указан как флаг, а количество считанных не превышает 256 байт.
По состоянию на октябрь 2017 года, OpenBSD, Darwin и Linux (с -lbsd
) теперь имеют реализацию arc4random
, которая является криптобезопасной и не может дать сбой. Это делает его очень привлекательным вариантом:
char myRandomData[50];
arc4random_buf(myRandomData, sizeof myRandomData); // done!
В противном случае вы можете использовать случайные устройства, как если бы они были файлами. Вы читаете с них и получаете случайные данные. Я использую open
/ read
здесь, но fopen
/ fread
будет работать так же хорошо.
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
}
}
Вы можете прочитать еще много случайных байтов перед закрытием дескриптора файла. / dev / urandom никогда не блокирует и всегда заполняет столько байтов, сколько вы запросили, если только системный вызов не прерывается сигналом. Он считается криптографически безопасным и должен быть вашим случайным устройством.
/ dev / random более привередливый. На большинстве платформ он может вернуть меньше байтов, чем вы просили, и он может заблокировать, если недостаточно байт доступно. Это делает историю обработки ошибок более сложной:
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);
}