I spent the weekend majorly re-factoring XKpasswd.pm, my Perl random password generation library. V0.1 was the last thing I wrote before reading Perl Best Practices, and looking back on that code really illustrated the value of that book when used in combination with the perlcritic code analyser.

The new version of the module provides all the functionality the old one did, and more. The refactoring has made the module simpler to use from within scripts, as well as easier to modify and extend. Some new features have also been added, including the ability to use the www.random.org web service as the source of randomness for the library. A full list of bug fixes and new features is included below.

I had hoped to distribute this version as both a ZIP file and a .PKG file, but XCode 4.4 is not being cooperative on the new Mountain Lion, so that will probably have to wait until version 0.3.

Update – 6 August 2012: The link below has been updated to point to version 0.2.1 of the code. Details of the bugs fixed in the release notes.


Installation Instructions

Note: I have only tested the module on OS X and Linux, but provided you have a working Perl environment on Windows it should work there too.

The download file contains three files, copy these to any folder on your system you like. I suggest /usr/local/xkpasswd, and all my examples will assume that location. You may have to chmod 755 example.pl before the sample script works, depending on whether or not your ZIP client preserved the permissions.

That’s it!

Using the Module

The file example.pl included within the zip download is a more full example that’s heavily documented with comments. I’m going to give a much more simplified example here.

Before you can generate a password with the module within a Perl script, you need to do three things, you need to include the library, create a config, and instantiate an XKpasswd object with that config. Then you can call the generate_password() function on that object as often as you like.

To include the module you need to use the use lib directive and point it at the folder you installed the module to before you try to include the module itself with a use directive. Assuming you installed the module in /usr/local/xkpasswd, you would include the following lines at the top of your script:

use lib '/usr/local/xkpasswd';
use XKpasswd;

The config needed to instantiate the object needs to be a hashref, and it MUST include the keys dictionary_file, min_word_length, and max_word_length. You can use as many or as few of the other options are you like (they are all described in example.pl). In this example I’m going to include just a few of the optional keys.

my $xkpasswd_config = {
    dictionary_file => '/usr/local/xkpasswd/sample_dict.txt',
    min_word_length => 4,
    max_word_length => 8,
	num_words => 3,
	custom_separator => '-',
	pad_char => 'RANDOM',

Once the config is assembled, you can use it to instantiate an XKpasswd object:

my $xkpasswd = XKpasswd->new($xkpasswd_config);

The line above can cause a fatal exception to be thrown if the config is in some way incorrect, or if there are file permissions preventing the dictionary file from loading. If you want to ‘catch’ this ‘exception’, you can do it like this:

use Carp;
use English qw( -no_match_vars );

my $xkpasswd;
eval{  # try
    $xkpasswd = XKpasswd->new($xkpasswd_config);
    1; # to force the eval to evaluate to true if there were no problems
} or do{ # catch
     print "Failed to create XKpasswd object with error: $EVAL_ERROR\n";

When you have instantiated an object you can generate as many password with it as you like in the following way:

my $password = $xkpasswd->generate_password();

This call can also generate a fatal error, especially if you are using the optional link to the www.random.org web service as your source of randomness, so you may also want to surround these calls with eval blocks.

Bugs Fixed in V0.2

  1. You can now use the character 0 (zero) as a custom separator or padding character.

New Features In V0.2

  1. By default the module still uses Perl’s built-in random number generator, but, if you wish, you can use the www.random.org web service instead by setting the random_source config key to the value RANDOM_ORG, AND setting the http_command key to the full path to a command line tool for sending the content of a web page to STDOUT. E.g., on OS X the value ‘/usr/bin/curl -f -s‘ works well.
  2. You can now have no separator at all by setting the config key custom_separator to the value NONE.
  3. A new option for the config key case_transform has been added. If you set it to the value ALTERNATE then each alternate word will be all caps then all lowercase.
  4. The padding character can now be randomly chosen by setting the pad_char config key to the value RANDOM.
  5. In V0.1 the code relied on magic return values to indicate failure, V0.2 does not do this, instead, it uses croak() to ‘throw’ a fatal error with a custom message explaining the error. These fatal errors can be programatically ‘caught’ using the eval or do method shown in the examples above.