Як використовувати / dev / random або urandom в C?


76

Я хочу використовувати /dev/randomабо /dev/urandomв C. Як я можу це зробити? Я не знаю, як я можу обробляти їх на мові C, якщо хтось знає, будь ласка, скажіть мені, як. Дякую.


Перевірити це дуже інформативну статтю про деякі загальні застереження приймати цей маршрут (псевдо-) хаотичність: insanecoding.blogspot.fi/2014/05 / ...
appas

Відповіді:


107

Загалом, краще уникати відкриття файлів, щоб отримати випадкові дані, через кількість пунктів відмови в процедурі.

В останніх версіях Linux, то getrandomсистемний виклик може бути використаний для отримання крипто-безпечного випадкових чисел, і це не може не , якщо GRND_RANDOM це НЕ вказано в якості прапора і зчитувального сума в більшості 256 байт.

Станом на жовтень 2017 року, OpenBSD, Darwin та Linux (with -lbsd) тепер мають реалізацію arc4randomкриптобезпеки, яка не може провалитися. Це робить його дуже привабливим варіантом:

В іншому випадку ви можете використовувати випадкові пристрої так, ніби це файли. Ви читаєте з них і отримуєте випадкові дані. Я використовую open/ readтут, але fopen/ freadпрацював би так само добре.

Ви можете прочитати ще багато випадкових байтів перед закриттям дескриптора файлу. / dev / urandom ніколи не блокує і завжди заповнює стільки байтів, скільки ви просили, якщо системний виклик не перерваний сигналом. Він вважається криптографічно безпечним і повинен бути вашим випадковим пристроєм.

/ dev / random є більш вигадливим. На більшості платформ він може повертати менше байтів, ніж ви просили, і може блокувати, якщо недостатньо байтів. Це робить історію обробки помилок більш складною:


14
@karim: Будь ласка, ніколи не читайте всі байти з / dev / random. Тільки не робіть. Ваша програма, мабуть, не єдиний користувач системи, якому потрібні випадкові байти.
Zan Lynx

1
@zneak, вибач, я забув, що тут можна редагувати дописи. Дякую, що повідомив мені. Остання ваша модифікація додала лише перевірку на читання, замість циклу. Я змінив його, використовуючи цикл, тому код тепер буде належним чином блокувати.
morrog

2
Рецензенти @morrog Overeager відхилили це, тому я вніс зміни вручну. Вибачте, за це вас не зараховують.
zneak

1
@CodesInChaos, я цитую ручну сторінку Linux : "Якщо ви не впевнені, чи слід використовувати / dev / random або / dev / urandom, то, мабуть, ви хочете використовувати останні. Як загальне правило, / dev / urandom використовувати для всього, крім довгоживучих ключів GPG / SSL / SSH. "
zneak

2
@zneak Акцент на довгожителі, оскільки для тих, кому не завадить бути зайвим параноїком. Для звичайного використання криптовалют /dev/urandomце нормально.
CodesInChaos

21

Вище є інші точні відповіді. FILE*Однак мені потрібно було використовувати потік. Ось що я зробив ...


1
Int можна прочитати безпосередньо, просто перекинувши покажчик int на покажчик char. fread((char*)(&myInt),sizeof(myInt),1,fp)
Azeem Bande-Ali

@ AzeemBande-Ali: Чому ви не використовуєте замість цього fread ((int *) (& myInt), sizeof (myInt), 1, fp)? Я маю на увазі кидок до int *?
Ларрі,

4
У жодному випадку не слід використовувати закидання в коді C, fread () приймає порожнечу *, тому просто виконайте fread (& myInt, ...);
nos

Навіщо тобі byte_count? Він не використовується.
КалькуляторFeline

@CalculatorFeline Тут кількість байтів трохи заплутана, можливо, спочатку хотілося, щоб кожен індекс мав однакову довжину байта, але це не могло зробити ...
LinconFive,

17

Просто відкрийте файл для читання, а потім прочитайте дані. У C ++ 11, можливо, ви захочете використовувати std::random_deviceтаку, яка забезпечує крос-платформний доступ до таких пристроїв.


Схоже, std::random_deviceце не потрапило у стандарт 2011 року. Це дійсно з'являється в проекті N3797 .
Кіт Томпсон,

2
Дивиться , як зробив це зробити в C ++ 11 , в кінці кінців. std::random_device
legends2k

1
Проблема полягає в тому, що std::random_deviceце в C ++, а не в C, і OP запитав, як використовувати /dev/randomчи /dev/urandomні, як використовувати, std::random_deviceхоча це хороший вибір для використання, std::random_deviceі він має переваги, це просто не те, що просив OP
Nfagie Yansaneh

8

Знеак правильно на 100%. Також дуже часто можна прочитати буфер випадкових чисел, який трохи більший, ніж той, який вам знадобиться під час запуску. Потім ви можете заповнити масив в пам'яті або записати їх у свій власний файл для подальшого повторного використання.

Типова реалізація вищезазначеного:

Це стає більш-менш схожим на стрічку, яка просто просувається вперед, яку за необхідності можна чарівним чином поповнити іншою ниткою. Є цілі багато з послуг , які надають великі файлові відвали нічого , крім випадкового чисел, які генеруються з набагато більш сильними генераторами , такими як:

  • Радіоактивний розпад
  • Оптична поведінка (фотони потрапляють у напівпрозоре дзеркало)
  • Атмосферний шум (не такий сильний, як вище)
  • Ферми сп’янілих мавп друкують на клавіатурах та рухаються мишами (жартують)

Не використовуйте `` заздалегідь упаковану '' ентропію для криптографічного насіння , на випадок, якщо це само собою зрозуміло. Ці набори чудово підходять для моделювання, а не зовсім для генерування ключів тощо.

Якщо вас не турбує якість, якщо вам потрібно багато цифр для чогось на зразок моделювання Монте-Карло, набагато краще мати їх доступними таким чином, що не призведе до блокування read ().

Однак пам’ятайте, випадковість числа така ж детермінована, як і складність, пов’язана з її генеруванням. /dev/randomі /dev/urandomзручні, але не такі сильні, як використання HRNG (або завантаження великого дампа з HRNG). Також варто зазначити, що /dev/random поповнення за допомогою ентропії , тому воно може блокувати на деякий час, залежно від обставин.


2
Завантажувати "великі звалища файлів, крім випадкових чисел", є жахливою порадою для криптографічних цілей. Він просить когось іншого надати насіння вашим функціям, і ці служби, схоже, передають ці дані незашифрованими через Інтернет. Будь ласка, не роби цього.
dequis

@dequis я уточнив. Я не бачу ніяких проблем з використанням їх для запуску великого моделювання, свого роду думав , що це було б здоровий глузд не використовувати їх для серійника / і т.д., але це варто бути дивно специфічні для точки. Питання було агностичним, тому мені справді не спало на думку бути таким конкретним, але вагомим.
Tim Post

6

Відповідь zneak охоплює це просто, проте реальність є більш складною, ніж це. Наприклад, вам потрібно розглянути, чи справді / dev / {u} random справді є пристроєм випадкових чисел. Подібний сценарій може трапитися, якщо ваша машина була зламана, а пристрої замінені символьними посиланнями на / dev / zero або розрідженим файлом. Якщо це трапиться, випадковий потік тепер повністю передбачуваний.

Найпростіший спосіб (принаймні на Linux та FreeBSD) - це здійснити виклик ioctl на пристрої, що вдасться лише в тому випадку, якщо пристрій є генератором випадкових випадків:

Якщо це виконується перед першим зчитуванням випадкового пристрою, тоді є чесна ставка, що у вас є випадковий пристрій. Тож відповідь @ zneak можна розширити таким чином:

Щоденник божевільного кодування висвітлював це та інші підводні камені не так давно; Настійно рекомендую прочитати всю статтю. Я повинен віддати належне тим, звідки взяли це рішення.

Відредаговано, щоб додати (25.07.2014) ...
До речі, вчора ввечері я прочитав, що в рамках зусиль LibReSSL Linux, схоже, отримує системний виклик GetRandom () . На момент написання статті в загальному випуску ядра немає жодної інформації про те, коли він буде доступний. Однак це найкращий інтерфейс для отримання криптографічно захищених випадкових даних, оскільки він усуває всі підводні камені, які надає доступ через файли. Див. Також можливу реалізацію LibReSSL .


2
Зловмисник з достатньою потужністю для заміни / dev / random або / dev / urandom чимось іншим, як правило, також має достатньо потужності для завантаження модуля ядра, щоб зіпсувати кожну вашу спробу, щоб визначити, випадковий пристрій чи ні.
zneak

Сторінка людини говорить getrandom()була введена в ядрі 3.17. Тож у фондовій Ubuntu 16.04 його немає станом на 17.01.2018. Запустіть uname -aтермінал, щоб перевірити версію ядра.
erapert
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.