Secure Passwords Made Easy

There are really only a few requirements for passwords:
1) not easily guessed
2) easily remembered (or reproduced given some sort of privileged information)
3) different password for each site

What I’ve done is to make something that uses the username and website, along with a password and/or passfile to generate a random password. This has a few advantages in that,
1) the passwords are very random in the sense that they do not resemble dictionary words, breaking these using a guessing attack would have to use 95^characters guesses. Assuming a 6 character password (and with this tool there is no reason to use anything other than the longest password allowed by the website), and 10^4 guesses per second (which is ridiculously high), it would still take longer than 2 years to guess. At 12 characters it would take 10^12 years, assuming the same rate of guessing, even if we assume one guess per clock cycle (counting hyperthreaded) it would take 400,000 years.
2) it’s super easy to get your password back, you just run the program again, and voila, there it is. Even if someone knew you were using this program, they’d have to guess secret words, and or secret files. Here there’s a slight hole, if they know your username to a given website, and you choose something like password as your key they might try that. If you use a file, a small image would work great. They’d have to essentially know exactly what file you were using.

#!/usr/bin/perl
use strict;
use Digest::SHA;
# some parameters
my $password_length = 8;
my $include_lowers = 1;
my $include_uppers = 1;
my $include_specials = 1;
my $include_digits = 1;

# get conversion strings
my $lowers = "";
my $uppers = "";
my $digits = "";
my $specials = "";
for(my $i = 33; $i < 127; ++$i)
{
if($include_digits && chr($i) =~ m/\d/){$digits .= chr($i);}
elsif($include_uppers && chr($i) =~ m/[A-Z]/){$uppers .= chr($i);}
elsif($include_lowers && chr($i) =~ m/[a-z]/){$lowers .= chr($i);}
elsif($include_specials && chr($i) =~ m/[^A-Za-z\d]/){$specials .= chr($i);}
}
my $all_characters = "${lowers}${uppers}${digits}${specials}";
#print "$all_characters\n";
my @characters_array = split("",$all_characters);

my $secretfile;
# full path to any file you like, could be a picture,
# you cannot edit this file or else it will change your passwords
# This crossed my mind as a good random seed, that would be
# easy to hold on to.

my $secretword;
# a secret "word", can be a number, whatever, I might recommend
# using 10 digits of pi starting at a number you can remember
# address, zipcode, phonenumber... can't be very long, more like a pin
# http://www.angio.net/pi/piquery

# get number of arguments
my $numargs = $#ARGV + 1;
my $username;
my $sitename;
for(my $i = 0; $i < $numargs; ++$i)
{
if($ARGV[$i] =~ m/^-.*/) # if it starts with a dash treat as a flag
{
my $flag = lc($ARGV[$i]);
++$i;
if($ARGV[$i-1] =~ m/.*user.*/){$username = lc($ARGV[$i]);}
elsif($ARGV[$i-1] =~ m/.*help.*/)
{
print "./password_generator [-user username] [-site sitename] [-word secretword] [-file secretfile]\n";
print "secretword or secretfile will be used to seed the randomness.\n";
print "The advantage to this script is that passwords can be regenerated\n";
print "and yet are very difficult to guess.\n";
print "\n";
exit(0);
}
elsif($ARGV[$i-1] =~ m/.*file.*/){$secretfile = $ARGV[$i];}
elsif($ARGV[$i-1] =~ m/.*word.*/){$secretword = $ARGV[$i];}
elsif($ARGV[$i-1] =~ m/.*site.*/){$sitename = lc($ARGV[$i]);}

}
}

# get site name
if(!defined($sitename))
{
print "What is the name of the site for which you need a password?\n";
$sitename = <STDIN>;
chomp($sitename);
$sitename = lc($sitename);
}

if(!defined($username))
{
print "What is the username on the site?\n";
$username = <STDIN>;
chomp($username);
$username = lc($username);
}

if(!defined($secretword) && (!defined($secretfile) || ! -e $secretfile))
{
if(defined($secretfile)){print "Could not find $secretfile"; exit(0);}
else
{
print "You have given neither a secret word nor a seed file (you can use both).\n";
print "Please specify a secret word:\n";
$secretword = <STDIN>;
chomp($secretword);
}
}

my $sha = Digest::SHA->new(512);
print "\n";
print "sitename   = $sitename\n";

if( -e $secretfile )
{
print "secretfile = $secretfile\n";
$sha->addfile($secretfile);
}

if(defined($secretword))
{
print "secretword = $secretword\n";
$sha->add("${secretword}");
}

if(defined($username))
{
print "username   = $username\n";
$sha->add("${username}");
}

print "\n";

$sha->add("${sitename}");
#print substr($sha->clone->hexdigest,0,15)."\n";
my $decdigest = hex(substr($sha->hexdigest,0,15));#cut to 15 to avoid overflows

# random seed using the hash
srand($decdigest);
my $password;
while( ($include_lowers == 1   && &stringcontains($password,$lowers)   == 0) ||
( $include_uppers == 1   && &stringcontains($password,$uppers)   == 0) ||
( $include_digits == 1   && &stringcontains($password,$digits)   == 0) ||
( $include_specials == 1 && &stringcontains($password,$specials) == 0))
{
$password = "";
for(my $iii = 0; $iii < $password_length; $iii++)
{
my $randomnumber = int(rand()*length($all_characters));
$password .= $characters_array[$randomnumber];
}
}

# finally print the password
print "$password\n";
exit(0);

# function to check if string contains at least one of the characters in second string
sub stringcontains
{
my($string, $search_class) = @_;
if($string =~ m/[${search_class}]/){return 1;}
return 0;
}

One Response to “Secure Passwords Made Easy”

  1. bob marley Says:

    you should enter the glorious world of firefox extensions with this! ;)

    so many nefarious types have submitted evil [adware[malware]] extensions to AMO something from you would likely be well received.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: