Немного об автоматической генерации паролей

Зайчатки разума

Записная книжка айтишника

Немного об автоматической генерации паролей

2018-10-19 15:05:32 — Evgeniy Shumilov

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


Генерация пароля

  После нескольких итераций скрипт для генерации паролей принял следующий вид:

#!/bin/sh
# Script for password generation by Evgeniy Shumilov 
# First parameter is password's lenght, second if rows count, third is columns count

[ -z "$1" ] && LENGTH=8 || LENGTH="$1"
[ -z "$2" ] && ROW=10 || ROW="$2"
[ -z "$2" ] && COL=10 || COL="$3"

pwg() {
    [ -z "$1" ] && l="$LENGTH" || l="$1"
    tr -dc A-Za-z0-9 < /dev/urandom | head -c "$l" | xargs
}

for r in `seq 1 $ROW`; do
    ln=''
    for c in `seq 1 $COL`; do
        ln="$(echo "$ln   "`pwg $1`)"
    done
    echo "$ln" | sed 's/^ *//'
done

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

  • без параметров выводит 10 строк по 10 паролей длиной в 8 символов
  • первый параметр - длина пароля
  • второй - количество паролей (строк)
  • третий - количество рядов

  Пример вызова:

$ ./pwg 16 4 5
G34CCXwNYzKCJyZ2   PGedVAM5Eg4aGneG   PxGUfJ0a7Qlewk7t   IcCrmdp6Sbd4yCTe   HgEp6aawjXfqxEBS
9kKAvmX8JQnyALnI   w7IreIyloijVyp27   12TL0gIL0kY8GzaF   Dr00g8jDkvNrse2h   d0Sp3mfEftq2gPAL
hvw3UV2DOJuzJ3Ji   8J6LriztK4yK2IlK   u54mgcToQ1FU0F3u   PnLF16DFxmzcRJi4   N2ue6QkwlUIi3ejn
KWtBvyWxVSlYzi2i   QpZNCoerfCaQufC8   XSJnvJAKSAo5nUdh   j8DwaCb8KHoYxymA   ZGnEPDE3whZDOCaL

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

Получение хэша

  Другая частая задача заключается в том, что нам нужно сгенерировать пользовательский пароль, хеш которого будет записан в /etc/shadow, он в свою очередь должен иметь определённый формат: $TYPE$SALT$HASH, где TYPE - это тип шифрования, SALT - дополнительная случайно сгенерированная последовательность, а HASH - собственно, сама зашифрованная часть. Тип шифрования может принимать несколько значений:

  • 1: md5
  • 5: sha256
  • 6: sha512
От типа шифрования зависит длина получаемого хэша и его надёжность. Самый простой вариант генерации пароля и одновременно наименее надёжный - с помощью openssl. Простой - потому что openssl скорее всего в системе уже установлен:

openssl passwd -1 -salt $salt "$passwd"

  Вышеприведённый способ я оставлю на случай, если пароли нужно генерировать например, на роутере, где нет возможности по какой-то причине использовать другой способ, а openssl уже имеется. Конечно, лучше использовать sha256 или sha512. Для этого есть несколько вариантов. Первый - использовать языки высокого уровня (php, perl, python) с соответствующими библиотеками, второй - использовать doveadm, если внезапно на вашей машине стоит dovecot. Третий: использовать утилиту mkpasswd, входящую в пакет whois. Содержимое скрипта для python будет выглядеть следующим образом:

python -c 'import crypt,getpass; print(crypt.crypt("passwordhere",crypt.mksalt(crypt.METHOD_SHA512)))'

  Вариант для perl:

perl -e 'print crypt("passwordhere","\$6\$saltsalt\$") . "\n"'

  Для doveadm:

echo 'passwordhere' | doveadm pw -s SHA512-CRYPT | cut -c 15-

  Следующий вариант, - наименее затратный способ, а заодно и самый простой, на случай, если python или perl не установлены. Ставить python со всеми его зависимостями ради генерацции пароля - это всё-равно что ездить в булочную за углом на карьерном самосвале. Для начала нужно, чтобы на нашей машине стоял пакет whois (по крайней мере в debian-based системах он называется так). Что замечательно, его размер немногим больше 350кб после установки. sudo apt-get -y install whois вам в помощь. И пример использования:

echo 'passwordhere' | mkpasswd -m sha-512 -s

Добавление пользователей.

  Теперь собственно, объединив генераццию с шифрованием попробуем написать пару функций для автоматического добавления пользователей в систему с выводом паролей на экран.

#!/bin/sh
# Проверяем, что скрипт запущен с полными правами, иначе запускаем через sudo 
# c тем же набором параметров ($*), а затем выходим c тем же кодом ($?),
# чтобы не пытаться выполнять содержимое второй раз
[ `whoami` != "root" ] && sudo $0 $* && exit $?

pwg() {
        [ -z "$1" ] && len="8" || len="$1"
        tr -dc A-Za-z0-9 < /dev/urandom | head -c "$len" | xargs
}

addusers() {
    for u in $1; do
        # Заменяем все символы, которые не являются буквами и цифрами на символ "-"
        uname="$(echo "$u" | sed 's/[^a-zA-Z0-9]/-/g')"
        # Берём пароль длиной в 16 символов
        passwd=`pwg 16`
        # Генерируем ещё одну случайную последовательность для соли
        salt=`pwg 8`
        # Получаем хэш пароля
        phash=`echo "$passwd" | mkpasswd -s -m sha-512 -S "$salt"`
        # Пытаемся создать пользователя и выводим информацию об имени и пароле
        if useradd -M -p "$phash" "$uname"; then
            echo "User $uname is added, password: $passwd"
            # Создаём пользовательскую директорию и выдаём ему права:
            mkdir -p "/home/$uname"
            chown "$uname:$uname" "/home/$uname"
        else
            echo "Fail to add user $uname"
        fi
    done
}

# Передаём нашей функции все параметры запуска
addusers "$*"
Пример запуска и вывода:
$ sudo ./usersadd user1 user2 user3
User user1 is added, password: b73c4054uoxt2nFT
User user2 is added, password: MJ7ru2qGW3C5T6NM
User user3 is added, password: F8uDTXpP8RnAAC90

$ ls -lah /home/ | grep user
drwxr-xr-x  2 user1 user1 4.0K Oct 19 14:34 user1
drwxr-xr-x  2 user2 user2 4.0K Oct 19 14:34 user2
drwxr-xr-x  2 user3 user3 4.0K Oct 19 14:34 user3

$ sudo tail -n 3 /etc/shadow
user1:$6$EUKsNJxa$krQnFygpv1vu7yMeouqapIvyhb5wZyn.cb1rp5Ag1xhC8vug3Wh8aJR3p3FqNi8gL8I06WorSaUqzrVHaY3nA1:17823:0:99999:7:::
user2:$6$habVCSsr$.zPMsmcjPv9tTpyuICZiOdg7FQNIZBse3lQs7XbpYFwWmAhBhlXcgXPt.ATPw.Fro2ndUAjk5hLxRfyw9XwvD.:17823:0:99999:7:::
user3:$6$0CpbD19Q$np1W57a9tHTJDt5lf03oN2LqScYNQWCXpvnmkDULNMqE00LnvoTiMtW6Rn/bu2XOSBSkKA/8spIUINemnnhHG/:17823:0:99999:7:::

$ ssh user1@localhost
The authenticity of host 'localhost (::1)' can't be established.
ECDSA key fingerprint is c3:a8:ce:1e:d4:be:6a:8b:e9:ff:a4:96:37:cc:c6:4c.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'localhost' (ECDSA) to the list of known hosts.
user1@localhost's password: 

$ whoami
user1

Теги: shell, automatization, админское

comments powered by Disqus