May
28
Getting Started with Crypt::HSXKPasswd
Filed Under Computers & Tech, Software Development, My Projects on May 28, 2015 at 8:28 pm
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~~
NTLM
–0=mAYAN=sCART@
* avoid this one unless you have no choiceSECURITYQ
–Wales outside full month minutes gentle?
WEB16
–:baby.ohio.DEAR:
WEB32
–+93-took-CASE-money-AHEAD-31+
WIFI
–2736_ITSELF_PARTIAL_QUICKLY_SCOTLAND_wild_people_7441!!!!!!!!!!
XKCD
–KING-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:
- German –
Crypt::HSXKPasswd::Dictionary::DE
- Spanish –
Crypt::HSXKPasswd::Dictionary::ES
- French –
Crypt::HSXKPasswd::Dictionary::FR
- Italian –
Crypt::HSXKPasswd::Dictionary::IT
- Dutch/Flemish –
Crypt::HSXKPasswd::Dictionary::NL
- Portuguese –
Crypt::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.
[…] might find this blog post helpful to get you started using the […]
[…] Don’t forget to join the NosillaCastaways in the live chatroom during WWDC at podfeet.com/live (or if you know how to use an IRC chat client, go to irc.borgchat.net and enter room #nosillacast. Macstock Conference and Expo and the Midwest Mac BBQ are only 2 weeks away! I sure hope to see a lot of you there, Steve and I are really excited! I declare time of death for Fitbit (for me), I’ve officially converted to the Apple Watch. Donald Burr announces the new and improved for iOS 8 NosillaCast App that lets you join the live show, chat with the NosillaCastaways, listen to recorded shows, read the blog posts and even watch the videos Steve and I post. There’s even an Apple Watch version to add to your notifications. OWC got back to me with even more awesome geeky detail on the difference between synchronous and asynchronous flash memory inside SSDs. Link to the free AJA speed test they recommended for compressible data transfer. The NosillaCast Headquarters is now unified on 1Password, no more LastPass in the house. In Chit Chat Across the Pond Bart’s back with the second half of the new XKPasswd Perl Module where I actually get to run it: Getting Started with Crypt::HSKPasswd […]