This is a quick-start guide to using the free and open source Crypt::HSXKPasswd Perl module for generating secure but memorable passwords.

As I write this post the module is not on CPAN yet, and still in beta form. The module can be downloaded from the project’s GitHub page.

This article assumes you have the module installed – you’ll find installation instructions here.

Before we get stuck into some sample code, let’s first summarise the module’s philosophy.

The module is built around the idea of using common words as a kind of lattice around which to build passwords that are long, have a wide coverage of characters, and yet are still memorable. An ideal HSXKPasswd password will contain a mix of upper and lower case letters, some digits, and some symbols.

The module starts building a password by randomly closing a given number of words from a given dictionary. There can then be an optional number of digits added as pseudo words to the front and/or the back of the initial list of words. Next, a symbol can be used to separate the words, and finally a symbol can be used to pad the front and/or back of the password.

Think of it like this:

correct HORSE BATTERY staple
23 correct HORSE BATTERY staple 45
23*correct*HORSE*BATTERY*staple*45
--23*correct*HORSE*BATTERY*staple*45--

The details of this process are controlled through a set of configuration options described in the module’s documentation which you can access from the terminal using the command below, or at this link.

perldoc Crypt::HSXKPasswd

The configuration options allow you to control the length of the words used, the number of words used, how accented characters within the word should be treated, and how the case of the words should be altered (or not). The configuration options also let you control the number of digits before and after the set of words, the separator character (if any), and the amount of padding and the character to pad with (if any).

To make life a little easier, the module includes a number of pre-defined presets. Below is a sample password generated with each defined preset:

  • APPLEID@60:london:TAUGHT:forget:70@
  • DEFAULT~~12:settle:SUCCEED:summer:48~~
  • NTLM0=mAYAN=sCART@ * avoid this one unless you have no choice
  • SECURITYQWales outside full month minutes gentle?
  • WEB16:baby.ohio.DEAR:
  • WEB32+93-took-CASE-money-AHEAD-31+
  • WIFI2736_ITSELF_PARTIAL_QUICKLY_SCOTLAND_wild_people_7441!!!!!!!!!!
  • XKCDKING-madrid-exercise-BELGIUM

Functional or OO?

This module can be used in two different ways, an old-fashioned functional interface, and a modern Object Oriented (OO) interface.

The functional interface is actually just a shortcut to the OO interface, the following are identical:

print hsxkpasswd(preset => 'XKCD')."\n";
print Crypt::HSXKPasswd->new(preset => 'XKCD')->password()."\n";

So, when should you use which?

My advice is very simple, if you need just a single password per execution of the script, you should use the first form, since it’s shorter to write and easier to read. But, if you need more than one password per execution of the script, definitely use the OO interface, your script will execute significantly faster!

For the remainder of this tutorial I’m going to use the OO interface, mainly because I like to generate a few passwords each time I need one, and then pick my favourite.

A Simple Sample Script

#!/usr/bin/perl

# standard 'best practice' imports
use strict;
use warnings;

# set things up for using UTF-8
use 5.016; # min Perl for good UTF-8 support
use utf8;
binmode STDOUT, ':encoding(UTF-8)';

# import the module
use Crypt::HSXKPasswd;

# create an HSXKPasswd object with default settings
my $hsxkpasswd = Crypt::HSXKPasswd->new();

# generate 5 passwords
my @passwords = $hsxkpasswd->passwords(5);

# print the 5 passwords
say join "\n", @passwords;

To generate your passwords, save the above as a plain text file with a name ending in .pl, open a Terminal window and cd to the folder where you saved the file. You then need to change the permissions to allow execution, and then you can run it. For the sample commands below, I have named my file genpwd.pl:

chmod 755 genpwd.pl
./genpwd.pl 

Customising the Config

Our script now generates five passwords using the default configuration, but what if we want to generate passwords differently? Let’s say we want a traditional XKCD-like passwords?

We can get most of the way there by using the named argument preset to tell the constructor that we want to use the XKCD preset. To do this, replace line 16 in the sample above with the following:

my $hsxkpasswd = Crypt::HSXKPasswd->new(preset => 'XKCD');

If we run the script we see we get passwords that look like this:

INTEREST-WILD-HEAR-size
speak-DIVISION-THANK-slept
indeed-HILL-country-FALL
after-WHEEL-PLEASANT-GRAY
moment-friend-MONEY-BANKER

That’s similar to the famous correct horse battery staple example from the comic, but not exactly the same. It’s not clear from the comic whether the words are separated by spaces, or just joined together. We can achieve either by using the named argument preset_overrides to tweak aspects of the preset. You can replace the call to the constructor on line 16 of the script with either of the sets of lines below. Note that you don’t have to split named arguments over multiple lines, but I choose to do so because I think it makes the code easier to read.

To have no separator, use:

my $hsxkpasswd = Crypt::HSXKPasswd->new(
    preset => 'XKCD',
    preset_overrides => {separator_character => 'NONE'}
);

To separate the words with spaces use:

my $hsxkpasswd = Crypt::HSXKPasswd->new(
    preset => 'XKCD',
    preset_overrides => {separator_character => ' '}
);

Comparing the passwords the script now generates to those in the comic, we can still see one subtle difference – for added security, the preset randomises the case of the letters in each word. In the comic all the words are in all lower case. We can achieve that same result by adding another override, case_transform:

my $hsxkpasswd = Crypt::HSXKPasswd->new(
    preset => 'XKCD',
    preset_overrides => {
        separator_character => ' ',
        case_transform => 'LOWER'
    }
);

Note that again, my choice to separate the overrides onto separate lines is purely a stylistic one – you could put all this one one massive line if you really wanted to.

The script will now generate passwords exactly as in the cartoon, BUT, it will also generate a security warning. Why? Because the entropy for this configuration is too low for an attacker with full knowledge. What does that mean? It means that if the attacker knew that your passwords were generatated with this module, and that you used this exact config, and that you used the default word source, then there would be less entropy than if you had used a truly random 8 character passwords consisted of letters, numbers, and symbols. As a general rule, security by obscurity is a bad idea, so I like to have my passwords remain sufficiently random, even in the unlikely scenario where the attacker knows exactly how I generate them.

Generating Custom Configs

If there happens to be a preset close to what you want, it makes sense to use that preset as a starting point, and then to specify your deviations form that preset using preset overrides. However, if what you want is nothing like any of the presets, then you’re better off building a so-called settings hashref from scratch.

You can find the full details of all the available config variables, and the rules for their values in the Configuration Hashrefs section of the docs.

The most obvious way to specify your own custom configuration is as a native Perl hashref. The example below shows how to assemble a configuration equivalent to the one we created previously by altering the XKCD preset, but built from scratch. Because this involves a lot of changes, I’ve included the full script below:

#!/usr/bin/perl

# standard 'best practice' imports
use strict;
use warnings;

# set things up for using UTF-8
use 5.016; # min Perl for good UTF-8 support
use utf8;
binmode STDOUT, ':encoding(UTF-8)';

# import the module
use Crypt::HSXKPasswd;

# assemble a config hashref
my $config = {
    word_length_min => 4,
    word_length_max => 8,
    num_words => 4,
    separator_character => ' ',
    padding_digits_before => 0,
    padding_digits_after => 0,
    padding_type => 'NONE',
    case_transform => 'LOWER',
    allow_accents => 0,
};

# create an HSXKPasswd object using the above config
my $hsxkpasswd = Crypt::HSXKPasswd->new(config => $config);

# generate 5 passwords
my @passwords = $hsxkpasswd->passwords(5);

# print the 5 passwords
say join "\n", @passwords;

While it’s quite easy to assemble your own config through trial and error using the above technique, wouldn’t it be nice to be able to build the config in a GUI, and then include it in your script somehow? Well, the good news is, you can!

If you go to www.xkpasswd.net, you can use the GUI there to assemble your own config. When you have all the settings just the way you like them, expand the Load/Save tab, and click Save Config. This will dump a copy of the config into the text box below the button. This version of the config is in a format known as JSON, and we can use it to create a new object in our code using Perl’s multi-line string feature. In the code below, the config from the site is copied and pasted between the lines my $config = <<'END_CONFIG'; and END_CONFIG. Note that it is vital that END_CONFIG appears on a line by itself with no spaces before or after it.

Here is the full script using the config from the website:

#!/usr/bin/perl

# standard 'best practice' imports
use strict;
use warnings;

# set things up for using UTF-8
use 5.016; # min Perl for good UTF-8 support
use utf8;
binmode STDOUT, ':encoding(UTF-8)';

# import the module
use Crypt::HSXKPasswd;

# assemble a config hashref
my $config = <<'END_CONFIG';
{
 "num_words": 4,
 "word_length_min": 4,
 "word_length_max": 8,
 "case_transform": "LOWER",
 "separator_character": " ",
 "padding_digits_before": 0,
 "padding_digits_after": 0,
 "padding_type": "NONE"
}
END_CONFIG

# create an HSXKPasswd object using the above config
my $hsxkpasswd = Crypt::HSXKPasswd->new(config_json => $config);

# generate 5 passwords
my @passwords = $hsxkpasswd->passwords(5);

# print the 5 passwords
say join "\n", @passwords;

Note that because the web interface is using an older version of the library, it will include the now-obsolete config key random_increment , you should delete that line from the config to avoid getting a warning.

Also note that this feature is only available if the standard Perl JSON module is installed in your system. If it’s not installed you can easily install it with the command:

sudo cpan JSON

Other Languages

So far in our examples we have used the default dictionary the module ships with – a list of common English words I compiled a few years ago.

The module also includes some experimental dictionaries from other languages. Be warned that these dictionaries are in need of some TLC by native speakers of those languages. They are simply too big ATM, containing uncommon words, and really slowing down the module. Please contact me of you’d like to help prune one or more of these dictionaries. At the moment the following foreign-language dictionaries ship with the module:

  • GermanCrypt::HSXKPasswd::Dictionary::DE
  • SpanishCrypt::HSXKPasswd::Dictionary::ES
  • FrenchCrypt::HSXKPasswd::Dictionary::FR
  • ItalianCrypt::HSXKPasswd::Dictionary::IT
  • Dutch/FlemishCrypt::HSXKPasswd::Dictionary::NL
  • PortugueseCrypt::HSXKPasswd::Dictionary::PT

For our example, let’s use French.

Note that French has a lot of words with accents, like Cliché. We need to decide how we want to treat them within our passwords. Because many websites don’t allow accents in passwords, the module’s default behaviour is to strip the accents from the letters, so cliché becomes cliche.

For our example, let’s assume we want to override the default, and let the accents appear in the passwords. Below is a final re-write of the code using the French dictionary, and the WEB32 preset with accents permitted:

#!/usr/bin/perl

# standard 'best practice' imports
use strict;
use warnings;

# set things up for using UTF-8
use 5.016; # min Perl for good UTF-8 support
use utf8;
binmode STDOUT, ':encoding(UTF-8)';

# import the module & French Dictionary
use Crypt::HSXKPasswd;
use Crypt::HSXKPasswd::Dictionary::FR;

# create an HSXKPasswd object using the French words with accents and WEB32
my $hsxkpasswd = Crypt::HSXKPasswd->new(
    preset => 'WEB32',
    preset_overrides => {allow_accents => 1},
    dictionary => Crypt::HSXKPasswd::Dictionary::FR->new() 
);

# generate 5 passwords
my @passwords = $hsxkpasswd->passwords(5);

# print the 5 passwords
say join "\n", @passwords;

Final Thoughts

This post is not intended as the definitive resource on the module, it really is just a guide to help people get started using the module. To understand all the module’s features in detail, please refer to the very detailed documentation available via the perldoc command, and online.