Читання з / dev / random не дає жодних даних


19

Я часто використовую команду

cat /dev/urandom | strings --bytes 1 | tr -d '\n\t ' | head --bytes 32

для генерації псевдовипадкових паролів. Це не працює /dev/random.

Конкретно

  • cat /dev/urandom | strings --bytes 1 | tr -d '\n\t ' виробляє вихід
  • cat /dev/random | strings --bytes 1 виробляє вихід
  • cat /dev/random | strings --bytes 1 | tr -d '\n\t ' не дає виходу

Примітка. Під час використання /dev/randomвам може знадобитися махнути мишею або натиснути клавіші (наприклад, ctrl, shift тощо), щоб створити ентропію.

Чому останній приклад не працює? Чи trє якийсь великий внутрішній буфер, який /dev/urandomшвидко заповнюється, але /dev/randomне працює?

PS Я використовую CentOS 6.5

cat /proc/version
Linux version 2.6.32-431.3.1.el6.x86_64 (mockbuild@c6b10.bsys.dev.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC) ) #1 SMP Fri Jan 3 21:39:27 UTC 2014

яка ваша дистрибуція, ваша версія ядра? на Cygwin обидва повернені значення.
Ківі

@Kiwy Див. Редагувати.
Аарон Дж Ланг,

1
Ви знаєте pwgen, зокрема pwgen -s?
MvG

2
-sПеремикач робить їх менш запам'ятовується, більш істинно випадковими. @Boyd: чи makepasswd широко доступний поза дистрибутивами на базі Debian? Як я це бачу, pwgen доступний для CentOS, а makepasswd - ні .
MvG

1
@BoydStephenSmithJr. Я погоджуюся з @ MvG, який makepasswdнедоступний на моїй платформі, все одно дякую
Aaron J Lang

Відповіді:


27

Це врешті-решт.

В:

cat /dev/random | strings --bytes 1 | tr -d '\n\t '

cat ніколи не буферизується, але все одно це зайве, оскільки тут нічого з’єднати.

< /dev/random strings --bytes 1 | tr -d '\n\t '

stringsоднак, оскільки його вихід більше не є, термінал буферизує свій висновок блоками (приблизно на кшталт 4 або 8 кБ), на відміну від рядків, коли вихід надходить до терміналу.

Таким чином, він почне писати в stdout лише тоді, коли накопичить для виведення символів вартістю 4 КБ, що на час /dev/randomпіде на деякий час.

trвисновок надходить до терміналу (якщо ви запускаєте це у запиті оболонки в терміналі), тому він буде буферизувати свою вихідну лінію. Оскільки ви видаляєте \n, він ніколи не буде мати повний рядок для запису, тому замість цього він запише, як тільки буде накопичений повний блок (наприклад, коли висновок не йде до терміналу).

Тож, trшвидше за все, нічого не напишу, поки stringsне прочитає достатньо /dev/random, щоб записати 8 кБ (2 блоки, можливо, набагато більше) даних (оскільки перший блок, ймовірно, містить деякі символи нового рядка, вкладки чи пробілу).

У цій системі я пробую це, я можу отримати в середньому 3 байти в секунду від /dev/random(на відміну від 12MiB на /dev/urandom), тож у найкращому випадку (перші 4096 байт з /dev/randomусіх друкованих), ми розмовляючи 22 хвилини, перш ніж trщось починає виводити. Але, швидше за все, це пройде години (у швидкому тесті я бачу stringsзапис блоку кожні 1 - 2 блоки читання, а вихідні блоки містять близько 30% символів нового рядка, тому я б очікував, що це буде потрібно прочитати принаймні 3 блоки до цього trмає 4096 символів).

Щоб уникнути цього, ви можете зробити:

< /dev/random stdbuf -o0 strings --bytes 1 | stdbuf -o0 tr -d '\n\t '

stdbuf є командою GNU (також зустрічається на деяких BSD), яка змінює буферизацію stdio команд за допомогою трюку LD_PRELOAD.

Зауважте, що замість цього strings, ви можете використовувати, tr -cd '[:graph:]'які також будуть виключати вкладки, нову лінію та пробіл.

Ви можете також виправити локаль C, щоб уникнути можливих подальших сюрпризів із символами UTF-8.


вау вражаюче пояснення.
Ківі

2
Дивовижний! Прекрасне пояснення та рішення. Я завжди використовував cat"марно", тому що мені ніколи не подобалось перенаправляти stdin в кінці конвеєра, тепер я можу "зберегти процес" і все ще мати читабельні команди. Моє остаточне рішення було< /dev/random stdbuf -o0 tr -Cd '[:graph:]' | stdbuf -o0 head --bytes 32
Aaron J Lang,

@AaronJLang, хороший пункт про [:graph:]. Я про це забув.
Stéphane Chazelas

@AaronJLang, вам не потрібно stdbufдля , head -c32якщо ви не хочете , щоб дозволити йому записати дані , як тільки він отримав його (як і в кількох шматках замість одного 32byte шматка , як тільки він отримав їх)
Stéphane Chazelas

2
На мою думку, / dev / urandom цілком достатньо для використання автором. Якщо хтось цікавився, як, зокрема, працює урандум порівняно зі випадковим, я б запропонував прочитати коментарі у верхній частині драйвера у драйверах / char / random.c дерева дерева ядра. У коментарях згадується аналіз PRNG та його реалізація. Сподіваємось, цей документ відповість на питання "наскільки більш-менш випадковим є випадковий порівняно зі випадковим?" Доступно тут: eprint.iacr.org/2012/251.pdf
etherfish

5

Генерування випадкових чисел для багатьох програм безпеки вимагає достатньої ентропії - ентропія вимірює наскільки непередбачуваною є випадковість. Детермінований процесор не може генерувати ентропію, тому ентропія повинна надходити ззовні - або з апаратного компонента з недетермінованою поведінкою, або з інших факторів, які досить важко відтворити, наприклад, часу виконання дій користувача (саме тут мишіть мишу заходить). Після наявності достатньої ентропії криптографію можна використовувати для створення практично необмеженого потоку випадкових чисел.

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

Якщо оцінка ентропії в пулі занадто низька, /dev/randomблокується до моменту накопичення більшої кількості ентропії. Це може сильно калічити швидкість, з якою /dev/randomможна отримати вихід. Це ви тут спостерігаєте. Це не має нічого спільного tr; але stringsзчитує вихід з буферизацією, тому він повинен зчитувати повний буфер (кілька КБ) /dev/randomпросто для отримання принаймні одного байта вводу.

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

Видалення stringsз завантажувального ланцюга, ймовірно, пришвидшить ваш процес. Нижче trбуде відфільтровано символи без друку:

</dev/random LC_ALL=C tr -dc '!-~'

Але ви можете використовувати /dev/urandomтут , доки ви не будете генерувати паролі в системі, яка не встигла накопичити достатню кількість ентропії. Ви можете перевірити рівень ентропійного пулу Linux /proc/sys/kernel/random/entropy_avail(якщо ви використовуєте /dev/random, цифра в цьому файлі буде консервативною, можливо, дуже).


1

Вам слід використовувати /dev/urandomдля отримання якісних (псевдо) випадкових чисел і /dev/randomлише тоді, коли вам абсолютно потрібні випадкові числа, які справді непередбачувані. Зловмиснику нижче ресурсів НСА буде дуже важко зламати /dev/urandom(і не забудьте про криптографію гумового шланга ). Ядро заповнює буфер "дійсно випадковими" байтами, саме це і /dev/randomдає. До жаль , швидкість , з якою вони даються невисока, тому читання багато з з /dev/random буде стійла чекає випадковості.

Ви можете розглянути можливість використання random.org або його генератора паролів , або одного з багатьох, безлічі генераторів випадкових паролів, що плавають навколо, подивіться, наприклад, на цю сторінку для кількох порад командного рядка (не те, що я б рекомендував їх усіх , але вони повинні дати вам ідеї), або ви можете скористатися чимось подібним mkpasswd(1)(тут, на частині Fedora 19 expect-5.45-8.fc19.x86_64).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.