#!/usr/bin/perl -w # Failtence by Murty Rompalli # Version 0.1 # Date 1/21/2006 # Each password set consists of: # # 1. Resource ID # 2. Sentence in MD5 hash # 3. Password in MD5 hash # 4. Hint # TO DO: # 1. Use Seeded SHA-2 with 512 bits instead of old fashioned MD5 # 2. Create a LiveCD that boots in Linux containing perl, gpg and this program our $pwd = `pwd` ; chomp $pwd ; die "Bad directory\n" unless $pwd =~ /\/failtence$/ ; chmod 0700,$pwd or die "chmod error\n" ; our $prog = 'failtence.pl' ; our $gpg = "/usr/bin/gpg --homedir $pwd" ; our $user = '' ; our $max = 5 ; our $passfile = 'passwords.txt' ; our $safekeep = '.safekeep' ; $| = 1, select $_ for select STDOUT ; $| = 1, select $_ for select STDERR ; sub getvar { my $var = shift ; while (1) { print $var,': ' ; my $answer = substr ,0,-1 ; unless ($answer =~ /\S/) { print "Bad input. Try again\n" ; next ; } my $a = '' ; while ($a ne 'y' && $a ne 'n') { print $var,': ',$answer," ACCEPT? y/n " ; $a = substr ,0,-1 ; } return $answer if $a eq 'y' ; } } sub encode { my $data = shift ; my $comment = shift ; my $output = `echo "$data" | $gpg -ear "$user" --comment "$comment"` ; return $output ; } sub getsafevar { use Digest::MD5 qw/md5_base64/ ; my $comment = shift ; my $str = shift ; $comment .= ' ' . $str ; while (1) { my ($p1,$p2) ; system 'stty -echo' ; while (!$p1) { print "Enter $str: " ; $p1 = substr ,0,-1 ; } print "\n" ; while (!$p2) { print "Enter $str again: " ; $p2 = substr ,0,-1 ; } system 'stty echo' ; return (md5_base64($p1),encode($p1,$comment)) if $p1 eq $p2 ; print "$str mismatch. Try again\n" ; } } sub gpgcheck { `$gpg --with-colons --list-keys "$user"` ; if ($?) { print "No gpg key for $user\n" ; print "Launching gpg --gen-key\n" ; print "\n",'=========>>>>>> NOTE: Choose email address: ', "$1\n\n" if $user =~ /<(.+)>/ or $user =~ /(.+)/ ; `$gpg --gen-key` ; die if $? ; } } sub createnew { my %set = () ; open PASS,">$passfile" or die ; open SAFE,">$safekeep" or die ; $| = 1, select $_ for select PASS ; $| = 1, select $_ for select SAFE ; print "\nCreating sets\n" ; for (1..$max) { my $tmp = '' ; print "\nSet $_\n\n" ; my $resource = getvar 'Resource ID' ; print PASS $resource,"\n" ; print SAFE $resource,"\n" ; ($set{$resource}{'sentence'},$tmp) = getsafevar($resource,'Sentence') ; print SAFE $tmp,"\n" ; print PASS $set{$resource}{'sentence'},"\n" ; print "\n" ; ($set{$resource}{'password'},$tmp) = getsafevar($resource,'Password') ; print SAFE $tmp,"\n" ; print PASS $set{$resource}{'password'},"\n" ; print "\n" ; $set{$resource}{'hint'} = getvar 'Hint' ; print PASS $set{$resource}{'hint'},"\n" ; print SAFE $set{$resource}{'hint'},"\n" ; print PASS "\n" ; print SAFE "\n" ; } close PASS or die ; close SAFE or die ; } sub practicemode { print "Entering practice mode\n" ; open FILE,"<$passfile" or die "$passfile: read error\n" ; my %set = () ; my @arr = () ; my $p = '' ; while () { if (/^$/) { die "$passfile: corrupt\n" unless $#arr == 3 ; chomp for @arr ; $resource = shift @arr ; $set{$resource}{'sentence'} = shift @arr ; $set{$resource}{'password'} = shift @arr ; $set{$resource}{'hint'} = shift @arr ; next ; } push @arr,$_ ; die "$passfile: corrupt\n" if $#arr > 3 ; } close FILE or die "$passfile: close error\n" ; system 'stty -echo' ; foreach my $r (keys %set) { print "\nResource: $r\n" ; print "Hint: $set{$r}{'hint'}\n" ; my $c = 0 ; while (1) { $p = '' ; while (!$p) { print "Password: " ; $p = substr ,0,-1 ; } if (md5_base64($p) eq $set{$r}{'password'}) { print "Ok\n\n" ; last ; } if ($c > 1) { print "Not ok\n" ; last ; } print "Try again\n" ; $c++ ; } } system 'stty echo' ; } ## Main program print ' (c) failtence by Murty Rompalli ' ; die "$safekeep belongs in a safe, not here!\n" if -f $safekeep ; # For increased security, uncomment the following 4 lines #foreach (<*>) { # $_ eq $prog or $_ eq $passfile or # die "Unauthorized file(s) found in program directory\n" ; #} if (-f $passfile) { practicemode ; exit ; } gpgcheck ; createnew ; `$gpg --fingerprint --fingerprint "$user" >> $safekeep` ; `$gpg --export -ar "$user" --comment failtence-pub >> $safekeep` ; `$gpg --export-secret-key -ar "$user" --comment failtence-key >> $safekeep` ; `$gpg --export-secret-subkey -ar "$user" --comment failtence-ssb>> $safekeep` ; print <