Функция в bash, которая генерирует случайные символы из /dev/random

В моем файле .bashrc я добавил строку psswd() { LC_ALL=C tr -dc 'a-zA-Z0-9-!"@/#$%^&*()_+~' < /dev/urandom | head -c "$1";echo ;}, чтобы при вводе psswd n в терминале возвращалась строка из n случайных символов. Я хотел бы добиться того же, но используя /dev/random вместо /dev/urandom. Однако, когда я заменяю /urandom на /random, вызов psswd ничего не делает (не может даже вывести ни одного случайного символа через 1 час), как будто он завис. Я не знаю, почему это так, и я знаю, что проблема не в недостатке энтропии. Причина в том, что команда od -An -N1 -i /dev/random возвращает случайное число.

Обратите внимание, что эта последняя команда почти мгновенно возвращает случайное число, если я наберу ее, скажем, после новой перезагрузки. Но если я вызвал вызов psswd n с /random, то команда вернет случайное число примерно через 15 секунд. Таким образом, вызов /random, по-видимому, оказывает некоторое влияние на /dev/random, даже несмотря на то, что он не выводит никаких результатов, когда я вызываю функцию psswd.

В целом, я хотел бы знать, как создать функцию, которая использует /dev/random для генерации случайной строки из n символов.


person AccidentalBismuthTransform    schedule 01.08.2015    source источник
comment
Могу я спросить, почему вы хотите использовать /dev/random? (См. также sockpuppet.org/blog/2014/02/ 25/безопасно-генерировать-случайные-числа)   -  person melpomene    schedule 01.08.2015
comment
Могу я спросить, в чем заключалась первоначальная проблема, которую вас просили решить? И почему /dev/random стало так важно для решения исходной проблемы? Вы не указываете, какую проблему вы намеревались решить.   -  person Ryan Vincent    schedule 01.08.2015
comment
@melpomene: В основном для удовольствия. Он делает то, что я уже умею делать с urandom, со random. Райан: Меня не просили решить какую-либо проблему. Все, что я хочу сделать, это создать функцию в bash, которая генерирует строку из n случайных символов, используя /dev/random.   -  person AccidentalBismuthTransform    schedule 01.08.2015
comment
Спасибо за разъяснение: может быть полезно? 10 Способы генерации случайного пароля из командной строки   -  person Ryan Vincent    schedule 01.08.2015
comment
Вот тут-то мне и пришла в голову идея попробовать такую ​​штуку, обратите внимание, что предпоследняя команда очень похожа на ту, которую я пробовал для своего файла .bashrc. Но он использует /dev/urandom, а не /dev/random.   -  person AccidentalBismuthTransform    schedule 01.08.2015
comment
Я ценю помощь PHP, но моя цель не использовать случайные символы. Как я уже сказал, меня интересует только создание функции в bash, которая использует /dev/random для выполнения своей задачи.   -  person AccidentalBismuthTransform    schedule 02.08.2015


Ответы (2)


Это происходит потому, что libc буферизует вывод tr, когда он не является терминалом. В GNU/Linux это 4096 байт. Это означает, что tr должен произвести 4096 байт вывода, прежде чем head увидит первые несколько байтов, даже если он просто запрашивает, например. 8.

Поскольку вы сохраняете только 78 из 256 значений, /dev/random должен произвести в среднем 4096*256/78 = 13443 байта случайного вывода, прежде чем вы получите свой пароль.

/dev/random в моей системе, начиная с пустого пула, потребовалось 26 секунд, чтобы сгенерировать 20 байтов. Это означает, что для создания пароля потребуется 13443*26/20 = 17475 секунд или почти 5 часов.

В этот момент он напечатает пароль, но tr потребуется еще один буфер, чтобы понять, что head больше не хочет, поэтому потребуется еще 5 часов, прежде чем команда завершит работу.

Если вы отключите буферизацию, вам нужно будет сгенерировать только (8+1)*256/78 = 29 байт, что займет всего ~ 38 секунд. В GNU/Linux это можно сделать с помощью stdbuf -o0:

$ time { LC_ALL=C stdbuf -o0 tr -dc 'a-zA-Z0-9-!"@/#$%^&*()_+~' < /dev/random | head -c 8; echo; }
9D^MKbT)

real    0m36.172s
user    0m0.000s
sys     0m0.010s
person that other guy    schedule 02.08.2015

…когда я заменяю /urandom на /random, вызов psswd ничего не делает…

Что происходит. Как объясняет Википедия:

In Unix-like operating systems, /dev/random is a special file that serves as a blocking pseudorandom number generator....

A counterpart to /dev/random is /dev/urandom ("unlimited"/non-blocking random source [Emphasis added]

«Блокировка» означает, что когда он думает, что у него закончилась энтропия, он перестает производить числа. Например, в моей системе первая команда в вашем конвейере выдает следующее:

$ LC_ALL=C tr -dc 'a-zA-Z0-9-!"@/#$%^&*()_+~' < /dev/random  
~Sk(+!h

А затем зависает, по-видимому, в ожидании дополнительной энтропии.

Этот вопрос обсуждается далее здесь, где утверждается, что /dev/urandom является достаточно хорошо.

Ускорение

tr, по-видимому, буферизует свой вывод, что задерживает появление символов. Обходной путь заключается в использовании stdbuf, и для меня это приводит к существенному ускорению:

LC_ALL=C stdbuf -o0 tr -dc 'a-zA-Z0-9-!"@/#$%^&*()_+~' < /dev/random
person John1024    schedule 02.08.2015
comment
Ну, в моем случае он блокируется, не возвращая никакого вывода. Команда LC_ALL=C tr -dc 'a-zA-Z0-9-!@/#$%^&*()_+~' ‹ /dev/random мне ничего не выводит, даже если я подожду 1 час . С другой стороны, использование od возвращает что-то из /dev/random. Таким образом, у него достаточно энтропии (как я сказал в своем первом посте), чтобы вернуть хотя бы строку длины 1. Я не знаю, почему использование tr не дает никакого результата в моем случае. - person AccidentalBismuthTransform; 02.08.2015
comment
/dev/random, возможно, придется создать несколько символов, прежде чем на выходе tr появится хотя бы один. Кроме того, head is waiting for either $1` символов или SIGPIPE, прежде чем он выдаст какой-либо вывод. Таким образом, один символ из /dev/random будет выдаваться только в том случае, если вы запросили 1-символьный пароль и символ, созданный /dev/random, только что совпал со списком в команде tr. - person John1024; 02.08.2015
comment
Я понимаю. Другой вопрос: почему od получает вывод? od -An -N10 -t c /dev/random почти мгновенно возвращает мне числа и специальные символы. - person AccidentalBismuthTransform; 02.08.2015