Copyright (C) 2014 Keith Thompson
UPDATE, Wed 2014-08-06 :
A very minor bug in
gen-password caused a warning message:
defined(@array) is deprecated at /home/kst/bin/gen-password line 151. (Maybe you should just omit the defined()?)
to appear when using recent versions of Perl. (The warning appears with Perl 5.16.3, but not with Perl 5.14.4.) This bug had no effect other than printing the warning message. I've corrected it.
UPDATE, Sat 2014-04-12 :
A bug was recently discovered in the
This bug did not affect the security of the generated passphrases,
but it did cause the command to go into an infinite loop if the
provided dictionary is very long (specifically, if there are more
than 65536 candidate words to choose from).
An update I made a few days ago did not correctly fix this problem. It avoided the infinite loop, but caused the program to ignore all but the first 65536 eligible words. In some cases this could create a bias for words earlier in the alphabet. This shouldn't have caused a problem if you specify the initials of the random words (unless you have a huge dictionary), but it could show up if you instead specify the number of words. It could also cause a generated passphrase to be (slightly) less secure than implied by statistics reported with the "-v" option.
The problem is now corrected, and
gen-passphrase should in principle
handle up to 232 words (though it would probably run out
of memory before that).
My thanks to Jimmy Wales (yes, that Jimmy Wales) for finding and reporting the original bug, and for letting me know that somebody out there is actually using this.
random-passwords is released under GPL version 2 or later. See the
header comments in
gen-password and the file
This is a small collection of utilities, written in Perl, for generating random passwords and passphrases.
gen-password generates a random password of a specified length
(the default is 12 characters) from a specified character set.
gen-passphrase generates a random passphrase consisting of words from
a dictionary (
/usr/share/dict/words by default), in the spirit of
this XKCD cartoon.
Both utilities obtain random data from
default, but can be told to use
/dev/random, which is much
slower. They will not work on systems that do not have these
device files. (I could have had it falling back to Perl's built-in
rand() function, but its
documentation explicitly says that it's not cryptographically secure.)
gen-password -help shows the following message:
Usage: gen-password [options] -help Display this message and exit -length N Length of generated password, default is 12 -charset ... Character set, default is "a-z0-9" The argument is a single word. -decimal Equivalent to "-charset 0-9" -hexadecimal Equivalent to "-charset 0-9a-f" -Hexadecimal Equivalent to "-charset 0-9A-F" -octal Equivalent to "-charset 0-7" -lower Equivalent to "-charset a-z" -upper Equivalent to "-charset A-Z" -alphanumeric Equivalent to "-charset A-Za-z0-9" -printable Equivalent to "-charset !-~" (ASCII non-blank printable characters) -split N Split with a blank every N characters -dev-random Use /dev/random rather than /dev/urandom (slow) -debugging Produce debugging output
The program assumes an ASCII character set. For example, it assumes that
the set of lower case letters is
gen-password -help shows the following message:
Usage: gen-passphrase [options] initials min-len max-len gen-passphrase [options] word-count min-len max-len -help Show this message and exit -verbose Show statistics about the strength of the passphrase -dictionary file Use specified word list Default is /usr/share/dict/words or $PASSPHRASE_DICT -dev-random Use /dev/random rather than /dev/urandom (slow) -debugging Produce debugging output Option names may be abbreviated; for example, "-verbose" may be given as "-v". The passphrase consists of a sequence of words randomly selected from the specified word list file. The first argument is either a string of lowercase letters (specifying the initial letters of the generated passphrase) or a decimal integer specifying the number of words. "min-len" and "max-len" are decimal integers determining the lengths of the chosen words
The passphrase consists of a sequence of words randomly selected from the specified word list file. The three command-line arguments (following any options) are:
- A string of ASCII lowercase letters, specifying the initials of the generated passphrase; or
- A decimal integer specifying the number of words (each of which will be selected randomly from the entire word list);
The minimum length of each word; and
The maximum length of each word.
This was partly inspired by this XKCD cartoon, which suggests using long passphrases consisting of randomly selected English words. The example in the cartoon was "correct horse battery staple" (of course you shouldn't use that specific passphrase).
With the first option, giving a string of lowecase letters as the first argument, you can specify a known word that will remind you of the passphrase; for example, "hello" might yield "hellion erosion leprosy legless outlook".
Words are randomly selected from
/usr/share/dict/words. Only lines
consisting entirely of lowercase letters are considered. You can
specify a different dictionary file by using the
or by setting the
$PASSPHRASE_DICT environment variable. (For
example, Cygwin has no
/usr/share/dict/words, so set
$PASSPHRASE_DICT to point to a copy from my Ubuntu system).
gen-passphrase shows some statistics
about the estimated strength of the generated passphrase, based on the
number of possibilities for each word. The statistics shown will depend
on the size of the dictionary file being used. For example, on Solaris
/usr/dict/words has 20,068 qualifying entries; on Ubuntu 12.04
/usr/share/dict/words has 62,887, and on Centos 5.7 it has 355,543.
Here's an example of
gen-passphrase with options that could
generate "correct horse battery staple", executed on Ubuntu 12.04:
$ gen-passphrase -v chbs 5 7 chasing hearsay bygones smocked 1881 * 843 * 1586 * 2817 7.0844e12 possibilities, equivalent to: 42.69 random bits, 9.08 random lowercase letters, 7.17 random mixed-case alphanumerics, 6.51 random printable ASCII characters
and on CentOS 5.7, with a much larger dictionary:
$ gen-passphrase -v chbs 5 7 cepous halpace bundist subfix 7117 * 2895 * 5952 * 9233 1.1322e15 possibilities, equivalent to: 50.01 random bits 10.64 random lowercase letters 8.40 random mixed-case alphanumerics 7.63 random printable ASCII characters
This indicates that the generated passphrase on Ubuntu is approximately
as secure as
vsxdrnhli (9 random lowercase letters) or
random mixed-case alphanumeric characters). Using a larger dictionary
gives better results, but can result in a passphrase that's more
difficult to remember ("cepous halpace bundist subfix"? Really?).
Note that this shows the number of possibilities given the criteria you chose. With the Ubuntu example above ("chasing hearsay bygones smocked"), a hypothetical attacker has over 7 trillion possibilities to consider if he or she knows that your passphrase consists of 4 words starting with 'c', 'h', 'b', and 's', with 5 to 7 letters in each word. Without that knowledge, the attacker's problem space is much larger.
If you find any bugs in these programs, particularly any security holes, please let me know.
-- Keith Thompson <Keith.S.Thompson@gmail.com>, Sat 2014-04-12