Створення випадкового пароля; чому це не портативний?


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це зовсім не буде. Що може піти не так?

Відповіді:


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@

14
+1, оскільки це змусило мене зрозуміти (використовуючи оболонки на Unix / Linux лише близько 30 років), що перенаправлення stdin / stdout / stderr не повинно розташовуватися після команди, до якої застосовується.
Антон

Просто коментар, якщо встановлено якийсь дивний локал, чи не може оболонка все-таки вміти правильно друкувати символи, навіть якщо вони не є ascii? Принаймні грамотна оболонка (за винятком xterm звичайно)?
Оріон

2
@orion: оболонка правильно надрукує символи. У цьому випадку це проблема tr. Вилучені байти вважають недрукованими, роблять результат дивним.
cuonglm

@orion Рівномірний випадковий потік байтів взагалі не буде рівномірно випадковим потоком добре сформованих кодувань символів UTF-8 .
zwol

Крім того, якщо у вас не :graph::print:</dev/urandom LC_ALL=C tr -dc '[:graph:]' | head -c 64
залишиться

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 біт ентропії безпечно в "все ще здогадуються, коли Sun не спалює "територію, за винятком ключів RSA, AFAIK).


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 введення або навіть невизначеної чутливості випадку.
orion

1
Лише зауваження: у [:print:]клас локалізації C не включаються вкладки. Це лише [:alnum:]+ [:punct:]+ простір (один простір, ні [:space:] ).
jimmij


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 символів.

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