Я хочу використовувати /dev/randomабо /dev/urandomв C. Як я можу це зробити? Я не знаю, як я можу обробляти їх на мові C, якщо хтось знає, будь ласка, скажіть мені, як. Дякую.
Я хочу використовувати /dev/randomабо /dev/urandomв C. Як я можу це зробити? Я не знаю, як я можу обробляти їх на мові C, якщо хтось знає, будь ласка, скажіть мені, як. Дякую.
Відповіді:
Загалом, краще уникати відкриття файлів, щоб отримати випадкові дані, через кількість пунктів відмови в процедурі.
В останніх версіях Linux, то getrandomсистемний виклик може бути використаний для отримання крипто-безпечного випадкових чисел, і це не може не , якщо GRND_RANDOM це НЕ вказано в якості прапора і зчитувального сума в більшості 256 байт.
Станом на жовтень 2017 року, OpenBSD, Darwin та Linux (with -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);
}
/dev/urandomце нормально.
Вище є інші точні відповіді. FILE*Однак мені потрібно було використовувати потік. Ось що я зробив ...
int byte_count = 64;
char data[64];
FILE *fp;
fp = fopen("/dev/urandom", "r");
fread(&data, 1, byte_count, fp);
fclose(fp);
fread((char*)(&myInt),sizeof(myInt),1,fp)
byte_count? Він не використовується.
Просто відкрийте файл для читання, а потім прочитайте дані. У C ++ 11, можливо, ви захочете використовувати std::random_deviceтаку, яка забезпечує крос-платформний доступ до таких пристроїв.
std::random_deviceце не потрапило у стандарт 2011 року. Це дійсно з'являється в проекті N3797 .
std::random_device
std::random_deviceце в C ++, а не в C, і OP запитав, як використовувати /dev/randomчи /dev/urandomні, як використовувати, std::random_deviceхоча це хороший вибір для використання, std::random_deviceі він має переваги, це просто не те, що просив OP
Знеак правильно на 100%. Також дуже часто можна прочитати буфер випадкових чисел, який трохи більший, ніж той, який вам знадобиться під час запуску. Потім ви можете заповнити масив в пам'яті або записати їх у свій власний файл для подальшого повторного використання.
Типова реалізація вищезазначеного:
typedef struct prandom {
struct prandom *prev;
int64_t number;
struct prandom *next;
} prandom_t;
Це стає більш-менш схожим на стрічку, яка просто просувається вперед, яку за необхідності можна чарівним чином поповнити іншою ниткою. Є цілі багато з послуг , які надають великі файлові відвали нічого , крім випадкового чисел, які генеруються з набагато більш сильними генераторами , такими як:
Не використовуйте `` заздалегідь упаковану '' ентропію для криптографічного насіння , на випадок, якщо це само собою зрозуміло. Ці набори чудово підходять для моделювання, а не зовсім для генерування ключів тощо.
Якщо вас не турбує якість, якщо вам потрібно багато цифр для чогось на зразок моделювання Монте-Карло, набагато краще мати їх доступними таким чином, що не призведе до блокування read ().
Однак пам’ятайте, випадковість числа така ж детермінована, як і складність, пов’язана з її генеруванням. /dev/randomі /dev/urandomзручні, але не такі сильні, як використання HRNG (або завантаження великого дампа з HRNG). Також варто зазначити, що /dev/random поповнення за допомогою ентропії , тому воно може блокувати на деякий час, залежно від обставин.
Відповідь zneak охоплює це просто, проте реальність є більш складною, ніж це. Наприклад, вам потрібно розглянути, чи справді / dev / {u} random справді є пристроєм випадкових чисел. Подібний сценарій може трапитися, якщо ваша машина була зламана, а пристрої замінені символьними посиланнями на / dev / zero або розрідженим файлом. Якщо це трапиться, випадковий потік тепер повністю передбачуваний.
Найпростіший спосіб (принаймні на Linux та FreeBSD) - це здійснити виклик ioctl на пристрої, що вдасться лише в тому випадку, якщо пристрій є генератором випадкових випадків:
int data;
int result = ioctl(fd, RNDGETENTCNT, &data);
// Upon success data now contains amount of entropy available in bits
Якщо це виконується перед першим зчитуванням випадкового пристрою, тоді є чесна ставка, що у вас є випадковий пристрій. Тож відповідь @ zneak можна розширити таким чином:
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);
Щоденник божевільного кодування висвітлював це та інші підводні камені не так давно; Настійно рекомендую прочитати всю статтю. Я повинен віддати належне тим, звідки взяли це рішення.
Відредаговано, щоб додати (25.07.2014) ...
До речі, вчора ввечері я прочитав, що в рамках зусиль LibReSSL Linux, схоже, отримує системний виклик GetRandom () . На момент написання статті в загальному випуску ядра немає жодної інформації про те, коли він буде доступний. Однак це найкращий інтерфейс для отримання криптографічно захищених випадкових даних, оскільки він усуває всі підводні камені, які надає доступ через файли. Див. Також можливу реалізацію LibReSSL .
getrandom()була введена в ядрі 3.17. Тож у фондовій Ubuntu 16.04 його немає станом на 17.01.2018. Запустіть uname -aтермінал, щоб перевірити версію ядра.