Генерация случайного пароля; почему это не портативный?

21

Я хочу создать случайный пароль, и я делаю это так:

</dev/urandom tr -dc [:print:] | head -c 64

На моем ноутбуке, на котором работает Ubuntu, он производит только печатные символы, как и предполагалось. Но когда я захожу на сервер моей школы, на котором работает Red Hat Enterprise Linux, и запускаю его там, я получаю вывод 3!ri�b�GrӴ��1�H�<�oM����&�nMC[�Pb�|L%MP�����9��fL2q���IFmsd|l�K, который не будет работать вообще. Что может быть не так?

Taymon
источник

Ответы:

34

Это ваша локаль и TR проблема.

В настоящее время GNU tr полностью поддерживает только однобайтовые символы. Так что в локалях, использующих многобайтовые кодировки, вывод может быть странным:

$ </dev/urandom LC_ALL=vi_VN.tcvn tr -dc '[:print:]' | head -c 64
`�pv���Z����c�ox"�O���%�YR��F�>��췔��ovȪ������^,<H ���>

Оболочка будет правильно печатать многобайтовые символы, но GNU trудалит байты, которые она считает не пригодными для печати.

Если вы хотите, чтобы он был стабильным, вы должны установить локаль:

$ </dev/urandom LC_ALL=C tr -dc '[:print:]' | head -c 64
RSmuiFH+537z+iY4ySz`{Pv6mJg::RB;/-2^{QnKkImpGuMSq92D(6N8QF?Y9Co@
cuonglm
источник
14
+1, потому что это заставило меня осознать (используя оболочки в Unix / Linux только около 30 лет), что перенаправление stdin / stdout / stderr не должно располагаться после команды, к которой он применяется.
Антон
Просто комментарий, если установлена ​​какая-то странная локаль, разве оболочка не сможет правильно печатать символы, даже если они не ascii? По крайней мере, грамотная оболочка (исключая, конечно, xterm)?
Орион
2
@orion: оболочка будет правильно печатать символы. В этом случае это проблема. Он удалил байты, которые он считает не для печати, что делает результат странным.
Cuonglm
@orion Равномерно случайный поток байтов, как правило, не будет равномерно случайным потоком правильно сформированных кодировок UTF-8 .
Звол
Кроме того, если вы не используете пробелы в своем пароле, вы должны использовать :graph:вместо :print::</dev/urandom LC_ALL=C tr -dc '[:graph:]' | head -c 64
edan
11

Рассмотрим вместо

$ dd if=/dev/urandom bs=48 count=1 status=none | base64
imW/X60Sk9TQzl+mdS5PL7sfMy9k/qFBWWkzZjbYJttREsYpzIguWr/uRIhyisR7

Это имеет два преимущества:

  • Вы читаете только 48 байтов со случайного устройства, а не ~ 8 КБ; если другие процессы на том же хосте нуждаются в случайных числах, 8 КБ, истощенных сразу, могут стать серьезной проблемой. (Да, возможно , никто не должен быть с помощью блокировки случайного устройства, но люди делают .)

  • Вывод base64практически не содержит символов со специальными значениями. (Ибо никто вообще, клейкости | tr +/ -_на конце, и (как в приведенном примере) убедитесь , что число байтов ввода , чтобы base64это кратно 3.)

Пароль, сгенерированный таким образом, имеет ровно 384 бита энтропии, что несколько меньше, чем вы делали (журнал 2 96 64 ≈ 421,4), но более чем достаточно для большинства целей (256 бит энтропии безопасны, «все еще догадываясь, когда Солнце выжигает "территорию за исключением ключей RSA, AFAIK).

zwol
источник
3

Другие люди уже указывали, что локаль определяет, что [:print:]значит. Однако не все печатные символы подходят для паролей (даже в ascii). Вы действительно не хотите пробелов, табуляции и # $% ^? в вашем пароле - это не просто сложно запомнить, это также потенциально опасно для базовой системы аутентификации, может быть невозможно ввести в поле ввода и т. д. В этом случае вам просто нужно вручную выбрать «нормальные» символы:

LC_ALL=C </dev/urandom tr -dc '[:alnum:]_' | head -c 64

или просто

</dev/urandom tr -dc 'A-Za-z0-9_' | head -c 64

Или даже лучше, используйте base64как предложено в других ответах.

Орион
источник
Этот пароль никогда не будет введен людьми (если бы я использовал Diceware вместо этого), и я совершенно уверен, что базовая система может обрабатывать специальные символы без проблем. Спасибо, в любом случае.
Таймон
4
То, что вы говорите, совершенно неправильно. Принудительное использование пользователями букв ascii, цифр и подчеркиваний значительно уменьшает размер алфавита, что значительно упрощает взлом паролей для злоумышленников. Система аутентификации, которая даже не может справиться ?или ^слишком плоха, чтобы воспринимать ее всерьез.
Бакуриу
2
Если ваша система аутентификации или поля ввода задыхаются от обычных символов ASCII ... тогда вы делаете что-то не так и вам не следует доверять мою личную информацию. Нет абсолютно никаких причин не принимать любые символы (включая пробелы) в ваших паролях.
nzifnab
2
Похоже, что это не тот случай, но когда речь идет о человеческом вводе, гораздо проще запомнить длинный буквенно-цифровой пароль, который имеет уникальный смысл для владельца, чем короткий набор символов. Существует также проблема ввода этих символов на различных клавиатурах (не у всех есть ^ на первом уровне, и большинство людей даже не знают, где и что такое обратный удар), поля ввода почти наверняка не могут обработать символ табуляции, и Удивительное количество веб-форм все еще подвержено ошибкам валидации, внедрению SQL-кода или даже неопределенной чувствительности к регистру.
Орион
1
Просто примечание: в языковой [:print:]класс C не входят вкладки. Это только [:alnum:]+ [:punct:]+ пробел (один пробел, а не [:space:] ).
Джимми
2

Как насчет

tr -dc [:print:] < /dev/urandom | head -c 64 | strings

строки должны печатать выходные данные urandom в печатном формате

Blindstealer
источник
Это дает-bash: /dev/urandom: Permission denied
Anthon
извините забыл ведущую кошку
Blindstealer
2

Я не знаю, есть ли причина, по которой вы используете /dev/randomпароль, но я бы порекомендовал вам использовать pwgen, чтобы облегчить вашу боль.

$ pwgen -s 10 1

Где 10 - длина пароля.

http://man.cx/pwgen

Даниил
источник
1
#Chars allowed in password (I don't like l,o,O, etc):
P="0123456789ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz"

#Or such:
#P="a-zA-Z0-9"

head -c 8 < /dev/urandom | tr '\000-\377' "$P$P$P$P$P"
echo

Этот метод IMHO умнее, когда он использует данные из / dev / urandom. Строка, вставленная как $ P $ P $ P ..., должна иметь длину не менее 256 символов.

Александр Кельнер
источник