Generating random passwords according to patterns with genpw

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.

Basic functionality

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):

% genpw

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.

Some examples:

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'

Configuration file

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.



  1. Nelson · May 2, 2018

    I used genpw for quite a few years. Today, for my longer pass phrases I’ve been using Diceware and Keepass2 for generic 20+ randomish web passwords. I agree with your overall push though. Genpw is awesome! HMB while I check out genpw-wordlist…


    • perlancar · May 2, 2018

      Thanks for the compliment. In the first sentence I’m guessing you probably meant some other program? I’ve also used these other scripts from CPAN: genpass (from App::Genpass by Sawyer X) and (from String::MkPasswd by Chris Grau). Both work fine.


  2. John Wiersba · May 3, 2018

    You might be interested in some ideas from the random password generator I wrote for myself. In particular, -c disallows characters which can be visually confused with each other, and -m (and -M) selects punctuation characters from the set that mintty allows when selecting a “word” via a double click (so that I can easily cut/paste the generated passwords). The default -P generates a random 15 character string like: ZKeC5U~nepV%jsv. It can generate about 46K passwords/second on my desktop, although I’ve never used it like that. I’ve never felt the need to use anything better than rand().

    usage: rand [-AclLmMnNpPRsSuUW] [LENGTH (default: 15)]
    -c do not allow confusing characters (0OolI1)
    -l allow lowercase letters
    -m allow mintty-based punctuation characters: ~#%_-+
    -n allow numeric characters
    -s allow special characters: ~`!@#0^&*()_-+={}[]|:;”‘,.?/
    -u allow uppercase letters

    -A must contain a letter (“Alphabetic”)
    -L must contain a lowercase letter
    -M must contain mintty-based punctuation, but not 1st/last char
    -N must contain a numeric character
    -R must not contain 3 identical adjacent characters
    -S must contain a special character
    -U must contain an uppercase letter
    -W must start with a letter (“Word”)

    -p same as -R -clnu -LNUW 10 (“Short password, without symbols”)
    -P same as -R -clnu -LNUW -mM 15 (“Password”, default)


    • perlancar · May 5, 2018

      Your rand program is cool, you should publish it on CPAN if you haven’t (and if it is written in Perl). The -c functionality is present in my genpw in the form of %B (base56 characters). I think your rand program is flexible enough for many needs, except for more extreme requirements like: must contain between M and N special characters, must not contain N consecutive identical characters, ordering of character groups (must start with a letter, must end with a special character), and so on. Some of which my template approach also currently cannot handle, for that matter.


  3. Pingback: Favoritos #012 | Perspicaz

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s