У меня немного ненавистные отношения с паролями. С одной стороны, они необходимы для аутентификации в службах и для расшифровки дисков. С другой стороны, их потеря означает потерю данных или доступа к учетным записям. Выбор более простых паролей или их повторное использование в разных учетных записях упрощает работу с ними, но снижает их безопасность.
В идеале пароли должны быть как можно длиннее.1. Если раньше рекомендовалось использовать политики паролей (например, принудительное использование специальных символов), то в настоящее время лучше избегать этого.2и вместо этого поощрять длинные пароли. В популярном компьютерном комиксе XKCD #936 отмечается, что длинные пароли на основе слов обладают большей надежностью и запоминаемостью, чем пароли на основе специальных символов:
Исходя из этого, я решил создать инструмент, который мог бы помочь в генерации случайных, надежных паролей различной формы. Я хотел, чтобы он был очень гибким, чтобы вы могли легко создавать пароли различной формы (например, 16 буквенно-цифровых символов или 4 английских слова).
Регулярные выражения
Я также очень люблю использовать регулярные выражения. Это язык, который часто используется для фильтрации или поиска текстового содержимого. Например, регулярное выражение [a-z]{8}
будет соответствовать любому вводу, состоящему ровно из восьми строчных латинских символов. Если вы не знакомы с регулярными выражениями, вот таблица, демонстрирующая их синтаксис:
Описание | Regex |
---|---|
Буквальная строка abc |
abc |
Либо a , либо b , либо c |
[abc] |
Любой строчный латинский символ | [a-z] |
16 строчных латинских символов | [a-z]{16} |
Обычно регулярные выражения используются в коде для проверки вводимых данных. Например, вы можете использовать регулярное выражение [a-z0-9.]{3,16}@yourcompany.com
, чтобы проверить, является ли что-то действительным адресом электронной почты компании.
Что, если бы я мог создать инструмент, которому можно дать регулярное выражение, и он будет оценивать его в обратном порядке, выдавая строку, которая соответствует ему, а не определяя, соответствует ли заданная строка?
Из этой идеи родился passgen
. Он начинался как небольшой однофайловый проект на языке Си, а развился в нечто, что я считаю действительно полезным. Он поддерживает небольшое подмножество синтаксиса регулярных выражений и выдает случайную строку, соответствующую им. Например:
# generate a password with eight lower-case latin characters
$ passgen "[a-z]{8}"
nsaaemni
# generate a password with twelve alphanumeric latin characters
$ passgen "[a-zA-Z0-9]{12}"
Lp7FBOldLhJC
Passgen полностью поддерживает юникод, что означает, что вы можете генерировать пароли и для других языков. Вот несколько примеров этого в действии:
# password with german characters
$ passgen "[a-zßäüöA-ZÄÜÖ0-9]{8}"
6Mu6cüYI
# password with sixteen japanese characters
$ passgen "[u{3040}-u{309F}]{16}"
しがぢゐめまゔょぎっきす゚だぃぷ
Списки слов
Одной из причин, по которой я создал Passgen, было желание создавать более запоминающиеся пароли для себя. Использование совершенно случайных букв делает пароли короткими, но не запоминающимися, как отмечалось ранее в XKCD. Поэтому у passgen есть возможность читать списки слов и выбирать из них случайные слова.
Пример | Шаблон |
---|---|
Случайное слово из списка слов | w{english} |
Шесть случайных слов из списка слов, разделенных дефисом | (w{english}-){5}w{english} |
Шесть случайных слов из списка слов, разделенных дефисом, за которым следует случайное число | (w{english}-){5}w{english}[0-9]{1,2} |
Например, если вы работаете на Debian или Ubuntu, и у вас установлен пакет wamerican
, то список слов будет доступен по адресу /usr/share/dict/american-english
. Если вы работаете на другой платформе, скорее всего, вы можете воспользоваться аналогичными предустановленными списками слов. Использование флага командной строки --wordlist
позволит вам загрузить этот список слов и затем ссылаться на него в шаблоне.
# pick 6 random words
$ passgen --wordlist english:/usr/share/dict/words "(w{english}-){5}w{english}"
vichyssoise-outstretching-requisite-weekended-homogenizes-calypsos
# pick 6 random words, and a one or two digit number
$ passgen --wordlist english:/usr/share/dict/words "(w{english}-){5}w{english}[0-9]{1,2}"
Karamazov-tasselling-pianos-shirr-devoutly-bullrings0
Цепочка Маркова
Хотя я считаю, что использование случайных слов из списка слов является хорошей идеей, я экспериментировал со способами придумывания паролей, которые также запоминаются (потому что их можно произнести), но не обязательно прямо из списка слов.
Идея заключается в использовании цепи Маркова для «обучения» тому, какие буквы часто встречаются вместе в словарном файле, и последующей генерации новых случайных слов на их основе. В результате получаются слова, которые можно произносить, но которые имеют идеально большую энтропию, а значит, их труднее взломать.
Чтобы использовать эту функцию, используйте m{wordlist}
, а не w{wordlist}
в шаблоне, все очень просто!
# generate five words from english markov chain
$ passgen --wordlist english:/usr/share/dict/words "(m{english}-){4}m{english}"
dam-bloodling-tempouthed-distnuminest-muchee
# generate four words from english markov chain and a number
$ passgen --wordlist english:/usr/share/dict/words "(m{english}-){3}m{english}[0-9]{1,2}"
lariticitude's-lieu's-gadorayons-flers44
Сложность
Каждый раз, когда passgen предлагает выбор между несколькими вариантами, он знает, сколько вариантов существует, и таким образом может отслеживать, насколько «случайным» является ваш пароль. Это означает, что он может сказать вам, сколько битов случайности содержит ваш пароль, что может рассказать вам о том, насколько сложно злоумышленнику взломать ваш пароль, если он знает шаблон, который вы использовали для его генерации. Например, если ваш пароль имеет 80 бит энтропии, то для его взлома потребуется в среднем
280=1208925819614629174706176 попыток отгадать.
Используйте флаг --complexity
, чтобы указать passgen выводить свою оценку сложности. Вот несколько примеров:
# eight lowercase alphabetic characters
$ passgen --complexity "[a-z]{8}"
entropy: 37.603518 bits
qhziaohr
# twelve alphanumeric characters
$ passgen --complexity "[a-zA-Z0-9]{12}"
entropy: 71.450356 bits
IoSNTUNU3M1Q
# six random dictionary words
$ passgen --complexity --wordlist english:/usr/share/dict/words "(w{english}-){5}w{english}"
entropy: 100.025099 bits
smirked-Ila-ounces-circumstance's-bedpan-process
# six random markov chain words
$ passgen --complexity --wordlist english:/usr/share/dict/words "(m{english}-){5}m{english}"
entropy: 125.801760 bits
confabriquing-mas-Onei-scrite-elaw-inast
Важно помнить, что эта функция не совершенна. Если вы дадите passgen шаблон типа (a|a){5}
, который технически имеет ноль бит энтропии (он всегда выдает aaa
), passgen все равно вычислит ненулевую сложность, потому что passgen делает выбор (между первым a
и вторым a
).
Случайность
Passgen будет предпочтительно использовать безопасный генератор случайных чисел ядра в качестве источника случайности, это getrandom()
в Linux и arc4random_buf()
в macOS. Он возвращается к использованию /dev/urandom
. Однако источник случайных данных настраивается, он также может использовать посевной генератор псевдослучайных чисел, но в настоящее время для этого реализован только небезопасный алгоритм xorshift
.
Мелочи
Passgen использует libseccomp3 на платформах amd64 для «песочницы», ограничивающей его только небольшим количеством разрешенных системных вызовов.
Он также может выводить данные в виде JSON
, передав опцию --json
.
Попробуйте
Если вы хотите попробовать, исходный код доступен здесь, а на странице релизов есть подписанные релизы для множества различных архитектур и платформ. Пожалуйста, будьте так добры, напишите о проблеме, если что-то не работает, так как у меня нет возможности протестировать все сборки.
Если вы работаете на Debian или Ubuntu, релизы .deb
будут вам полезны, потому что они позволят вам легко установить (и удалить) passgen
с APT.
Резюме
На сайте есть обзор синтаксиса, который можно использовать, но вот краткое резюме.
Пример | Паттерн |
---|---|
Сгенерировать литеральную строку abc . |
passgen "abc" |
Выберите символ из a , b , c |
passgen "[abc]" |
Выберите символ из диапазона a-z . |
passgen "[a-z]" |
Повторите a четыре раза |
passgen "a{4}" |
Выберите четыре символа нижнего регистра | passgen "[a-z]{4}" |
Для генерации паролей можно использовать несколько конструкций:
- Дословные символы. Шаблон
abc
генерирует «пароль»abc
. Они просто передаются. - Наборы символов, заключенные в скобки. Вы можете либо перечислить все разрешенные символы, либо использовать диапазоны символов, которые являются инклюзивными. Примеры:
[abc]
,[a-zA-Z0-9]
,[0123456789abcdef]
. - Группы, заключенные в паретес. Группы позволяют перечислить один или несколько возможных шаблонов. Примеры:
(word)
генерирует слово,(this|that)
генерирует this или that,([a-z]|[0-9])
генерирует строчный латинский символ ([a-z]
) или число ([0-9]
). - Повторять. Использование скобок позволяет повторить то, что было раньше. Вы можете указать либо фиксированное число, либо нижнюю и верхнюю границы, разделенные запятой. Примеры:
[abc]{3}
,[a-z]{9,12}
,(this|that){2}
.
Если этот синтаксис слишком сложен для вас, бинарный файл passgen также поставляется с некоторыми предустановками шаблонов, которые вы можете использовать с флагом -p
. Они названы в честь программ, которые генерируют пароли, соответствующие этим шаблонам.
# generated by older versions of safari
$ passgen -p apple1
asG-mIQ-7jz-LAT
# generated by current safari
$ passgen -p apple2
lHODYM-MgdmfG-llo5kD
# generated by firefox
$ passgen -p firefox
iBpDBlTg8bX051H
Разработка
Если вы настоящий ботаник, вы можете захотеть скомпилировать его самостоятельно. Вам понадобятся некоторые зависимости:
- CMake
- компилятор языка Си (gcc или clang)
- Git
С этими зависимостями вы сможете собрать его, клонируя репозиторий, получая подмодули (это необходимо для libutf8proc4).
git clone https://gitlab.com/xfbs/passgen
git submodule update --init
mkdir passgen/build
cd passgen/build
cmake ..
make -j8
Если вы хотите понять, как работают отдельные части, есть также документация, созданная на основе мастер-ветки.
Тесты
В Passgen встроен ряд модульных тестов, которые можно запустить с помощью make test
. Вы также можете запустить эти тесты под valgrind, если он у вас установлен, это позволит вам убедиться в отсутствии утечек памяти.
$ valgrind ./src/test/passgen-test -v
Поддержка
Ваша поддержка высоко ценится. Если вы запустите passgen, и что-то не будет работать, пожалуйста, дайте мне знать. Вы можете написать о проблеме в репозиторий, и я постараюсь ее исправить.
Если вам нравится passgen, и вы нашли ошибки, у вас есть предложения или вы хотите помочь включить его в любой пакетный репозиторий, пожалуйста, не стесняйтесь связаться со мной, я ценю любую помощь. Я надеюсь, что он может быть полезен другим людям.
-
Минимальная длина паролей должна обеспечиваться приложением. Пароли короче 8 символов считаются слабыми. https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html
-
https://www.troyhunt.com/passwords-evolved-authentication-guidance-for-the-modern-era/
-
https://github.com/seccomp/libseccomp
-
utf8proc, библиотека для декодирования UTF-8. https://github.com/JuliaStrings/utf8proc