Make a Password

Since my Mac’s hard disk failed I’ve been using a Debian Lenny system, and I’ve missed lots of features, one of which is a widget to generate passwords. The recent Twitter documents hack came from someone using the same password across several services, and it was probably guessable too. A generator coupled with a password manager works a treat to beat this kind of attack. There are plenty of online generators, but after my last girlfriend I have trust issues, so I knocked one up (a script, not an ex-girlfriend) in Perl, as it’s the daddy (not me) of quick scripts.


use warnings;
use strict;
use Digest::SHA::PurePerl qw(sha1_base64);
use constant HASHLENGTH => 27; #hash full length
use constant LENGTH => shift @ARGV || HASHLENGTH;

sub makepass {
  my $len = shift;
  my $pass = shift;
  my $p = sha1_base64(rand());
  $p = substr $p, 0, $len if $len < HASHLENGTH;
  $pass .= $p;
  $len -= length($p);
  return $pass if $len == 0;
  return makepass($len, $pass);
print makepass(LENGTH), "\n";

The script is called via ./makepass.pl 42 and it will give you a random password of 42 characters. Leave off a number and it will return a 27 character password (the default length of SHA1 under base64).

Here’s what it’s doing:

  • the script generates a random number
  • produces the SHA1 hash for that number
  • then concatenates the hashes (or chops them down) until the right length has been reached.

I originally wrote this without recursion, but I’ve been using Haskell a lot over the past year, and there was a for loop bang in the middle of the code, and for-loops just look so nasty compared to folds and maps etc. I would have used a fold but Perl doesn’t have them, and the Language::Functional plugin that would enable them didn’t install for me, so I ended up using tail recursion. It actually made the script more concise, and readable, if you understand recursion.

Now all I need is a cross platform password manager like the OSX Keychain…

Added on:
Last updated:
Info:Originally written 14th of August 2009 - OSX 10.5 - Perl 5.10+