Как сгенерировать случайную строку?

Вопрос или проблема

Я хотел бы сгенерировать случайную строку (например, пароли, имена пользователей и т. д.). Должна быть возможность задать необходимую длину (например, 13 символов).

Какие инструменты я могу использовать?

(По соображениям безопасности и конфиденциальности предпочтительно, чтобы строки генерировались офлайн, а не онлайн на сайте.)

Мой любимый способ сделать это – использовать /dev/urandom вместе с tr, чтобы удалить ненужные символы. Например, чтобы получить только цифры и буквы:

tr -dc A-Za-z0-9 </dev/urandom | head -c 13; echo

В качестве альтернативы, чтобы включить больше символов из списка специальных символов пароля OWASP:

tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~' </dev/urandom | head -c 13; echo

Если у вас есть проблемы с tr, который жалуется на входные данные, попробуйте добавить LC_ALL=C вот так:

LC_ALL=C tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~' </dev/urandom | head -c 13; echo

tr также имеет класс символов для графических символов, который немного более читаем. Ограничив его до C локали, вы должны получить такой же тип вывода, что и в вышеприведенном явном списке символов:

LC_ALL=C tr -dc '[:graph:]' </dev/urandom | head -c 13; echo

Я использую команду openssl, швейцарский армейский нож криптографии.

openssl rand -base64 12

или

openssl rand -hex 12

Чтобы сгенерировать случайный пароль, вы можете использовать pwgen:

pwgen генерирует случайные, бессмысленные, но произносимые пароли. Эти пароли содержат либо только строчные буквы, либо смешанные строчные и заглавные буквы, либо цифры. Заглавные буквы и цифры размещаются так, чтобы облегчить запоминание их положения при запоминании только слова.

Сгенерируйте 7 паролей длиной 13:

geek@liv-inspiron:~$ pwgen 13 7
Eu7Teadiphaec giepahl3Oyaiy iecoo9Aetaib4 phaiChae6Eivi athoo3igee8Co
Iphu4ufeDeelo aesoYi2lie9he 

Как упоминалось в комментариях, вы можете избежать снижения энтропии, используя аргумент -s (то есть генерировать более безопасные, совершенно случайные, но трудные для запоминания пароли):

geek@liv-inspiron:~$ pwgen -s 13 7
eAfycrPlM4cYv 4MRXmZmyIVNBp D8y71iqjG7Zq7 FQRHcserl4R8O yRCUtPtV3dsqV
0vJpp2h0OrgF1 QTp7MKtJyTrjz 

Для пользователей brew смотрите здесь.


Чтобы сгенерировать случайные имена пользователей, вы можете использовать gpw:

Этот пакет генерирует произносимые пароли. Он использует статистику трехбуквенных комбинаций (триграмм), взятых из любых словарей, которые вы ему предоставляете.

Сгенерируйте 7 паролей (имен пользователей) длиной 13:

geek@liv-inspiron:~$ gpw 7 13
sreepoidahsas
risadiestinge
ntodynesssine
deodstestress
natinglumperm
riasigentspir
enderiferback

Вдохновленный Пабло Репетто, я пришел к этому легкому для запоминания решению:

shuf -er -n20  {A..Z} {a..z} {0..9} | tr -d '\n'

-e выводит результат

-r позволяет любому символу появляться несколько раз

-n20 запрашивает случайную строку длиной 20 символов

{A..Z} {a..z} {0..9} определяет допустимые классы символов

shuf является частью coreutils и широко доступен или по крайней мере был портирован.

Вот как я это делаю. Это генерирует 10 случайных символов. Вы можете оптимизировать это, заменив “fold” на другие инструменты обработки строк.

cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 10 | head -n 1

Чтобы создать пароль с максимальной энтропией, которую возможно достичь с помощью стандартных инструментов Linux, которые встроены в каждую дистрибуцию, я использую:

< /dev/urandom tr -cd "[:print:]" | head -c 32; echo

Это выводит все печатаемые символы ASCII – от 32 (пробел) до 126 ( тилда, ~). Длину пароля можно контролировать с помощью флага -c у head. Существуют также другие возможные наборы символов в tr (чтобы не включать пробел, используйте только символы с 33 по 126, введите [:graph:]).

Используйте команду xxd для задания длины (через -l), которая работает как в Linux, так и в macOS. 
Смотрите справочную страницу xxd(1)
или Учебник по команде Linux xxd для начинающих (с примерами).

xxd -l16 -ps /dev/urandom

В зависимости от уровня случайности, который вы хотите, вы можете просто использовать встроенную переменную $RANDOM в bash (также zsh и ksh, возможно, и другие):

$ echo $RANDOM | tr '[0-9]' '[a-z]'
bfeci
$ echo $RANDOM | tr '[0-9]' '[a-z]'
cijjj

Методы, считывающие данные непосредственно из /dev/urandom, значительно проще, но для завершенности вы также можете использовать $RANDOM:

echo $(for((i=1;i<=13;i++)); do printf '%s' "${RANDOM:0:1}"; done) | tr '[0-9]' '[a-z]'

Важно: это решение будет лишь создавать случайные строки, используя первые 10 букв алфавита. Достаточно ли этого для вас, зависит от того, для чего вам это нужно.

Я использую:

base64 < /dev/urandom | tr -d 'O0Il1+/' | head -c 44; printf '\n'

Это дает мне 57 возможных символов. Строку можно копировать и вставлять (удалив + и /) или распечатать и перепечатать, так как трудные для различения символы (I1lO0) были удалены.

  • 44 символов дают мне: log2(5744) > 256.64 бит энтропии
  • 22 символов дают мне: log2(5722) > 128.32 бит энтропии

Мне это нравится, потому что:

  • команда проста для ввода и запоминается
  • использует стандартные системные инструменты – без дополнительных бинарников
  • не “тратит” много случайности (использует 89% случайных битов, которые получает по сравнению с ~24% для решений, которые напрямую передают в tr)
  • 22 и 44 символа довольно хорошо сочетаются (чуть выше обычных степеней двойки)
  • вывод можно легко выбрать, вставить или распечатать и перепечатать с минимальным человеческим уровнем ошибок
  • короче, чем закодированные в шестнадцатеричном формате (32 и 64 вместо 22 и 44) решения, такие как md5sum/sha1sum и т. д.

Кредиты https://unix.stackexchange.com/a/230676/9583 и особенно комментариев для моего первоначального вдохновения.

APG включен по умолчанию в некоторых дистрибуциях Linux.

Для генерации паролей размером от 5 до 10 в подмножествах Специальный, Цифровой, Заглавный и Низкий, команда:

apg -MSNCL -m 5 -x 10

И возвращает

@OpVeyhym9
3:Glul
3DroomIc?
hed&Os0
NefIj%Ob3
35Quok}

Как говорится @landroni в комментарии.

@Brandin объяснил в комментарии к другому ответу, как получить не более 100 байт из /dev/urandom с использованием head -c 100. Другой способ сделать это – с помощью dd:

tr -dc A-Za-z0-9 < /dev/urandom | dd bs=100 count=1 2>/dev/null

Команда 2>/dev/null в конце команды dd используется для подавления вывода “… записей в / … записей вывода”.

Я не знаю никаких существенных преимуществ/недостатков между этими двумя методами.

У меня была проблема с обеими методами tr, которые жаловались на входные данные. Я подумал, что это потому, что ему не нравится получать двоичные входные данные, и, следовательно, предложил сначала отфильтровать /dev/random с iconv -c -t US. Однако Жиль предложил другую диагностику и решение, которое для меня сработало:

LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | dd bs=100 count=1 2>/dev/null

Вы можете использовать один из инструментов md5, который имеет именно такую цель. В случае создания совершенно случайного пароля вы можете использовать md5pass. Это очень простой инструмент для использования и очень полезный, поскольку вы можете использовать “нормальный текст” вместе с “солью”, чтобы получать одну и ту же битовую конструкцию пароля, которую вы можете восстановить позже, или, альтернативно, вы можете захотеть каждый раз получать совершенно случайный пароль. Общий способ использования:

md5pass [пароль] [соль]

где пароль – это выбранное слово, которое будет использоваться для создания случайной строки, а соль – это прыжок в байтах, который будет использоваться. Так:

md5pass слово

$1$.MUittVW$j.XDTF1QRnxqFdXRUiSLs0

Это создаст для вас “случайный последовательность” пароля. Если вы не используете соль, то вы можете не иметь возможности восстановить ту же строку позже.

Тем не менее, если вы используете соль вроде этого:

md5pass слово 512

$1$512$.0jcLPQ83jgszaPT8xzds0

вы можете создать последовательность, которую сможете восстановить, если используете слово вместе с той же солью (или прыжком), если это было первоначально определено.

Эти две команды генерируют случайные пароли и фразы, соответственно.

shuf --random-source=/dev/urandom --repeat --head-count=20 file_with_characters | tr --delete '\n'

shuf --random-source=/dev/urandom --repeat --head-count=7 file_with_words | tr '\n' ' '

Генератор паролей требует файл_with_characters, содержащий все символы, которые вы хотите использовать для пароля, по одному символу в строке, и ровно один раз каждый. Файл не должен содержать пустых строк, а строки должны заканчиваться знаком новой строки.

Генератор фраз требует файл_with_words, содержащий все слова, которые вы хотите использовать в фразе, по одному слову в строке и ровно один раз каждое. Файл не должен содержать пустых строк, а строки должны заканчиваться знаком новой строки.

Опция –head-count указывает длину пароля – в символах – или фразы – в словах.

Я обнаружил, что передача /dev/urandom в tr на macOS не сработала. Вот другой способ:

set="abcdefghijklmonpqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
n=6
rand=""
for i in `seq 1 $n`; do
    char=${set:$RANDOM % ${#set}:1}
    rand+=$char
done
echo $rand
</div><div class="s-prose js-post-body" itemprop="text">

Я хотел бы предложить свою обычную команду для генерации пароля

$ cat /dev/urandom | base64 | head -n 1 |tr -dc '[:alnum:]' |cut -c -13
b0R55751vWW9V

Чтобы настроить длину пароля, измените число в команде cut на требуемую длину, например, 24 символа

$ cat /dev/urandom | base64 | head -n 1 |tr -dc '[:alnum:]' |cut -c -24
WFBhVHuKbrnRhd5kdWXPzmZG

Не хотите путать 0 или O, 1 или l? Отфильтруйте их с помощью другого tr

$ cat /dev/urandom | base64 | head -n 1 |tr -dc '[:alnum:]' | tr -d '0O1l'|cut -c -24
JuCphwvhrhppD9wVqfpP2beG

Я personalmente никогда не предпочитаю специальные символы в пароле, поэтому я выбираю только [:alnum:] для своего генератора паролей

</div><div class="s-prose js-post-body" itemprop="text">

pwgen, как и все другие, для паролей.

Только строчные буквы, безопасно, минимум 1 цифра, 8 символов, 1 результат

$ pwgen -snA 8 1
d14o5wgh

То же самое, но минимум 1 заглавная буква

$ pwgen -csn 8 1
bMxDxcr4

Кубиковая программа для имен пользователей и паролей, если хотите, для чего-то более удобного для запоминания; я использую pip пакет diceware, что вполне устраивает мои потребности.

3 слова и 2 символа

$ diceware -n3 -s2
DemandingWhimsical*a1iar

Я уверен, что есть как минимум 100 других, из которых 74% написаны на nodejs, потому что, ну… это то, что они делают. Какой бы вариант вы ни выбрали, я бы отдал приоритет встроенным функциям верхнего/нижнего регистра, потому что в какой-то момент у вас будут эти ограничения, и выполнение любого из этих действий занимает раздражающе много времени в оболочке posix.

Удачи

</div><div class="s-prose js-post-body" itemprop="text">

Я использовал grep:

grep -ao '[!-~]' < /dev/urandom | head -32 | tr -d '\n' ; echo ""

Без специальных символов:

grep -ao '[A-Za-z0-9]' < /dev/urandom | head -32 | tr -d '\n' ; echo ""

head определяет длину строки.

</div><div class="s-prose js-post-body" itemprop="text">

Универсальная философия “много маленьких инструментов, которые делают одно дело хорошо” очень вам помогает в данном случае.

  • /dev/urandom – это поток случайных “байтов” (включая непечатаемые символы)
  • base64 кодирует байтовые данные в [A-Za-z0-9/+] (что полностью печатаемо)
  • dd копирует ввод на вывод, применяя модификаторы, заданные в аргументах (которые могут включать размер блока и количество блоков)

OSX

base64     < /dev/urandom | dd bs=1k count=1

Linux

base64 -w0 < /dev/urandom | dd bs=1k count=1

Примечания:

  • Если вам нужно подмножество символов, вы можете вставить модификатор в трубу.
    • Напр., tr -d '[A-Z/+]', чтобы избавиться от заглавных букв и + и /
  • Вы можете задать bs (размер блока) на любую желаемую длину.
  • В Linux base64 по умолчанию переносит текст на 76 колонок, и его нужно сбросить с помощью -w0, если вы не хотите этого.

Я поддерживаю secpwgen в Alpine Linux и держу исходный код на своем Github.

Он может производить случайные строки или фразы diceware:

musl64 [~]$ secpwgen
USAGE: secpwgen <-p[e] | -A[adhsy] | -r | -s[e]> N

PASSPHRASE из N слов из словаря Diceware
  -p    генерировать фразу
  -pe   генерировать улучшенную (с символами) фразу

SKEY PASSWORD из N слов из словаря S/Key
  -s    генерировать фразу
  -se   генерировать улучшенную (с символами) фразу

ASCII RANDOM из N элементов (по крайней мере, один вариант ДОЛЖЕН быть представлен)
  -A    Каждая буква добавляет следующие случайные элементы в вывод:
    a    буквенно-цифровые символы
    d    десятичные цифры
    h    шестнадцатеричные цифры
    s    специальные символы
    y    слоги из 3-4 букв

RAW RANDOM
  -r    вывод кодированной BASE64 строки из N случайных БИТ
  -k    вывод кодировки koremutake из N случайных БИТ

Для генерации случайной строки длиной 13 символов вы будете использовать:

musl64 [~]$ secpwgen -Aas 13
----------------
WK5#*V<]M3<CU ;ENTROPY=67.21 bits
----------------
INFO: уничтожение генератора случайных чисел.
INFO: обнуление памяти.

musl64 [~]$ secpwgen -Aa 13
----------------
GP0FIEBM9Y3BT ;ENTROPY=67.21 bits
----------------
INFO: уничтожение генератора случайных чисел.
INFO: обнуление памяти.

Для запоминания пароля используйте фразы diceware:

musl64 [~]$ secpwgen -p 5
----------------
wq seen list n8 kerr  ;ENTROPY=65.00 bits
----------------
INFO: уничтожение генератора случайных чисел.
INFO: обнуление памяти.

Мне лично нравится:

musl64 [~]$ secpwgen -r 512
----------------
h62lL7G4gwh3/j9c7YteQvVXoqJrQKKPWVR3Lt7az36DcfWZWtUgBT19iwmJBwP4UahNzPe7qYD7OcklUFpCzQ== ;ENTROPY=512.00 bits
----------------
INFO: уничтожение генератора случайных чисел.
INFO: обнуление памяти.

Используя только head и md5sum для генерации шестнадцатеричных паролей длиной 22:

 head -c 2048 /dev/urandom | md5sum | head -c 22 ; echo

Ультрабезопасно? Может быть, нет. Легко? Да.

С помощью короткого скрипта:

len=20
arr=( {33..126} ) arrcount=${#arr[@]}
for ((i=0; i<len; i++)); do
    printf \\$(printf '%03o' ${arr[RANDOM%arrcount]})
done; echo

Если вы предпочитаете без специальных символов, используйте:

arr=( {48..57} {65..90} {97..122} )

Это диапазоны кодов ASCII, смотрите man ascii

Мой способ для очень безопасного пароля (где 16 – это длина пароля):

cat /dev/urandom | tr -cd [:graph:]|head -c 16

Пример результата:

jT@s_Nx]gH<wL~W}

Или, в качестве альтернативы, чтобы сгенерировать несколько паролей:

cat /dev/urandom | tr -cd [:graph:]|fold -w 16|head -6

Пример результата:

7ck%G7'|f&}_8(]s
<?*]E.CG[NB'gK#A
:tF-WPTOa3!i7S(h
2xy(>=%3=Kb1B$`6
*98Lf{d?Jzb}6q1\
E7uCEAN2Hz]]y|5*

Немного менее безопасно (меньший набор символов):

cat /dev/urandom |base64 -w 0|fold -w 16|head -6

Пример результата:

rJqYxYZLOTV+A45w
PUKQ+BoBf6yfZw5m
+LRfpsN9CsLRiN8V
yMS6zDpL6NHmG17s
yTUWPG7Rum97schi
cognvjVwaKaAyPRK

Ни один из ответов до сих пор не является по-настоящему кросс-ОС.

Основные недостатки связаны с определением локали (в случае MacOS) и тем, что tr не может распознать интервалы символов (в случае Solaris).

Вам следует попробовать shlibs. Это свежая и действительно кросс-ОС.
Код для получения случайной строки – это shlibs str005 (./shlibs str005).

Получите случайную строку из 50 символов, включите знаки препинания, исключая цифры:

shlibs str005 50 -p -xd

Для длин от 1 до 32 вы можете использовать uuidgen из libuuid или util-linux, просто замените <LENGTH> ниже:

uuidgen -r | tr -d '-' | head -c <LENGTH>

# или

random=$(uuidgen -r | tr -d '-') && echo "${random:0:<LENGTH>}"

Примечание: 6–7 из 128 бит предопределены и фиксированы.

Этот ответ похож на метод /dev/urandom, но использует openssl rand.

Генерируйте случайные байты достаточного размера, так чтобы после фильтрации до нужных символов у вас все еще оставалось необходимое количество.

Здесь я генерирую 1000 случайных байт для 10 алфавитно-цифровых символов a-zA-Z0-9:

LC_ALL=C tr -dc a-zA-Z0-9 < <(openssl rand 1000) | head -c10

Обратите внимание, что вышеуказанное использует подстановку процесса <(...). Если ваша оболочка этого не поддерживает, вы можете создать временный файл:

openssl rand 1000 > random.tmp
LC_ALL=C tr -dc a-zA-Z0-9 < random.tmp | head -c10

Простая функция Bash, основанная на ответе @Gilles Quénot, которая использует SRANDOM и опцию grep -P для совместимых с Perl регулярных выражений.

Использование

randString;
# 4csibIlydNZxJGhV4cRWaeXvGC2XzVUUm58CJfDO1aUTELpA6c7X2YE2oBiosi99

randString 32;
# C1BIyf8TyxltBDKS207C8SOEjjfZDW1E

randString 48 '[abcd]{2}$';
# jsnVQpNDgfLy9BboryXmQYjxcSOh3YFWk6Xae3yxRdKrh6dc

Исходный код

randString()
(
    declare -r -- __length="${1-64}" __regex="$2";
    shift 2;

    declare -r -- c=(  
        {48..57}   # 0-9
        {65..90}   # A-Z
        {97..122}  # a-z
        # {33..47}   # !"#$%&'()*+,-./
        # {58..64}   # :;<=>?@
        # {91..96}   # [\]^_`
        # {123..126} # {|}~
    );

    declare -r -- cc="${#c[@]}";
    declare r="" i;

    while [[ "$r" == '' ]] || ! printf '%s' "$r" | grep -P -- "$__regex";
    do
        r="";

        for (( i=0; i < __length; i++ ));
        do
            declare h; h="$( printf -- '%x' "${c[RANDOM%cc]}"; )";
            printf -v t -- "\\x${h}";
            r+="$t";
        done
    done
)

Ответ или решение

Создание случайной строки, например, для паролей или имен пользователей, можно выполнить различными способами, используя стандартные инструменты Linux и Unix-подобных систем. В этой статье мы подробно рассмотрим несколько методов генерации случайных строк, включая указание необходимой длины строки, при этом уделяя внимание безопасности, поскольку важно, чтобы данные генерировались оффлайн, а не с использованием онлайн-сервисов.

Способы генерации случайных строк

  1. Использование /dev/urandom и tr

    Один из самых простых способов — это использование файла /dev/urandom, который предоставляет доступ к случайным байтам. С помощью команды tr можно отфильтровать ненужные символы. Например, для генерации строки длиной 13 символов, состоящей только из букв и цифр:

    tr -dc A-Za-z0-9 < /dev/urandom | head -c 13; echo

    Если вы хотите включить специальные символы, вы можете использовать следующий вариант:

    tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<=>?@[\]^_`{|}~' < /dev/urandom | head -c 13; echo

    Также можно указать использование локали для корректной обработки символов:

    LC_ALL=C tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 13; echo
  2. Использование openssl

    Команда openssl предоставляет ещё один мощный способ генерации случайных строк:

    Для случайной строки в формате base64:

    openssl rand -base64 12

    Или в формате hex:

    openssl rand -hex 12
  3. Использование pwgen

    Если вам нужны легко запоминаемые пароли, команда pwgen является отличным вариантом. Например, для генерации 7 паролей длиной 13 символов можно выполнить:

    pwgen 13 7

    Для генерации более безопасных, менее запоминаемых паролей используйте параметр -s:

    pwgen -s 13 7
  4. Использование shuf

    shuf также может быть полезным для создания случайных строк:

    shuf -er -n20 {A..Z} {a..z} {0..9} | tr -d '\n'

    Здесь -n20 указывает длину строки, и -r разрешает повторение символов.

  5. Пользовательские скрипты на Bash

    Вы можете создать пользовательский скрипт на Bash для генерации случайной строки фиксированной длины:

    len=20
    arr=( {33..126} ) arrcount=${#arr[@]}
    for ((i=0; i<len; i++)); do
       printf \\$(printf '%03o' ${arr[RANDOM%arrcount]})
    done; echo

Вывод

Эти методы генерации случайных строк выделяются своей простотой и эффективностью. Выбор конкретного подхода зависит от ваших требований к безопасности и удобству использования. Каждая из предлагаемых команд подходит для оффлайн-генерации и не требует подключения к интернету, что соответствует вашей потребности в безопасности и конфиденциальности.

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

Оцените материал
Добавить комментарий

Капча загружается...