There are several modules on CPAN for generating random passwords, but last time I checked, none of them are flexible enough. Different websites or applications have different requirements (sometimes ridiculous ones) for passwords. True, most modules allow setting minimum/maximum length, and some of them allow customizing the number of special characters, or number of digits, but what I want is some sort of template/pattern that the generator would follow. So I created genpw.
genpw is your usual random password generator CLI. When run without any arguments, it returns a single random password (8-20 characters long, comprising letters/digits):
To return several passwords:
% genpw 5
To set exact length or minimum/maximum of length:
% genpw -l 4
% genpw --min-len 12 --max-len 14
In addition to the above basic customization, genpw allows you to specify a pattern (or several patterns to pick randomly, for that matter). A pattern is a string that is similar to a printf pattern where conversion sequences like %d will be replaced with actual random characters. Here are the available conversions:
%l Random Latin letter (A-Z, a-z)
%d Random digit (0-9)
%h Random hexdigit (0-9a-f)
%a Random letter/digit (Alphanum) (A-Z, a-z, 0-9; combination of %l and %d)
%s Random ASCII symbol, e.g. "-" (dash), "_" (underscore), etc.
%x Random letter/digit/ASCII symbol (combination of %a and %s)
%m Base64 character (A-Z, a-z, 0-9, +, /)
%b Base58 character (A-Z, a-z, 0-9 minus IOl0)
%B Base56 character (A-Z, a-z, 0-9 minus IOol01)
%% A literal percent sign
%w Random word
You can specify %NC (where N is a positive integer, and C is the conversion) to mean a sequence of random characters (or a random word) with the exact length of N. Or %N$MC (where N and M are positive integers) to mean random characters (or word) with length between N and M.
Unsupported conversion will be unchanged, like in printf.
Generate random digits between 10 and 12 characters long:
% genpw -p '%10$12d'
Generate a random UUID:
% genpw -p '%8h-%4h-%4h-%4h-%12h'
Like the above, but in uppercase:
% genpw -p '%8h-%4h-%4h-%4h-%12h' -U
The %w conversion in pattern mean to replace with a random word. Words are fetched from STDIN (and will be shuffled before use). For example, the command below will generate password in the form of a random word + 4 random digits:
% genpw -p '%w%4d' < /usr/share/dict/words
Instead of from STDIN, you can also fetch words from the various WordList::* modules available on CPAN (and installed locally). A separate CLI provides this functionality: genpw-wordlist, which is basically just a wrapper to extract the words from the wordlist module(s) then feed it to App::genpw. By default, if you don't specify -w option(s) to select wordlist modules, the CLI will use WordList::EN::Enable:
% genpw-wordlist -p '%w%4d'
Generate 5 passwords comprising 8-character word followed by between four to six random digits:
% genpw-wordlist 5 -p '%8w-%4$6d'
To avoid you from having to type patterns again and again, you can use a configuration file. For example, put this in $HOME/genpw.conf:
patterns = %8h-%4h-%4h-%4h-%12h
case = upper
then you can just say:
% genpw -P uuid
The speed is not great, around 2000 passwords/sec on my laptop, though I believe this should not matter for most use-cases.
genpw is a flexible random password generator where you can specify patterns or templates for the password. I'm still working on a few things, like how to enable secure random source in the most painless way. There are also various CLI variants to generate specific kinds of passwords as straightforward as possible: genpw-base56, genpw-base64, genpw-id, and the aforementioned genpw-wordlist.