#! /usr/bin/perl use strict; &pwgen; # pwgen generates a cryptographically random password by choosing four words from a list of over 32,768 # such passwords should have about 60 bits of entropy, perhaps somewhat less as a lot of lusers will # probably repeatedly reject passwords until they find something they like. Nonetheless, the generated # passwords will likely have far more real entropy than any "memorable password consisting of upper- and # lowercase alphabetic letters with at least one numeric digit and one symbol." And will likely be # much more memorable and easier to type. # # Inspired by http://xkcd.com/936/ # # Copyright (c) 2012 Ron Risley my $wordcount; sub random_integer { # return a cryptographically-random 16 bit number open RAND, '/dev/urandom' || die "No random device"; read RAND, my $bytes, 2 || die "Defective random device"; close RAND; $bytes = (unpack 'S',$bytes) ; return $bytes; } sub random_word { # return a random word from our list my $word; my $rand = &random_integer; # throw away out-of-range randoms -- DO NOT attempt to map the random integers # into the word space unless you really understand the cryptographic implications while ( $rand > $wordcount ) { $rand = &random_integer; } open WORDS, "); } chomp($word); return $word; } sub pwgen { print "Content-Type: text/html\n\n"; # compute the global wordcount (it's expensive to recompute it each pass) if (!$wordcount) { open WORDS, ") { $wordcount++; } close WORDS; } my $password=ucfirst(&random_word).ucfirst(&random_word).ucfirst(&random_word).ucfirst(&random_word); # display the template my $dollarsign = '$'; # to display a literal $ in the html template open TEMPLATE,") { s/(\$\w+)/$1/eeg; print; } close TEMPLATE; }