#!/usr/pkg/bin/perl -w
#
# Enc(rypt)Passwd Prototype 15
# Simple MD5 password encrypter
#
# Copyright Dirk Diggler & Som One 1981-2002. All rides reserved.
# Coded by Pierrot Lunaire
# Redistribution and use, with or without modification,
# is permitted in the sense of GDWYWL
# (GeneralDoWhateverYouWantLicense).
# -z3r0-

use strict;

BEGIN {
  eval "use Term::ReadKey";
  if ($@) {
  print "EncPasswd: Cannot find Term::ReadKey perl module.\n\n".
        "You need to have this module installed in order to run EncPasswd.\n".
        "See README for more info on how to install the module.\n\n";
  die "\n";
  }
  eval "use Digest::MD5";
  if ($@) {
  print "EncPasswd: Cannot find Digest::MD5 perl module.\n\n".
        "You need to have this module installed in order to run EncPasswd.\n".
        "See README for more info on how to install the module.\n\n";
  die "\n";
  }
}

print "Do you plan to use the FastCheck feature ([y]/n)? ";
my $temp7 = ReadLine 0;

chomp($temp7);

my $Fchck;

if ($temp7 !~ /^[nN]$/) {
	eval "use MIME::Base64";
	if ($@) {
	print "EncPasswd: Cannot find MIME::Base64 perl module.\n\n".
              "You need to have this module installed in order to run EncPasswd.\n".
              "See README for more info on how to install the module.\n\n";
	die "\n";
	}
	$Fchck = 1;
}


my $temp1;
my $temp2;

print "\n";

# Turn off terminal output
ReadMode 'noecho';

do {
  if ($temp1) {print "\nERROR: The strings didn\'t match. Please retry...\n\n"}

  print "Please enter your YahooMail password: ";
  $temp1 = ReadLine 0;
  chomp($temp1);

  print "\nPlease re-enter your YahooMail password: ";
  $temp2 = ReadLine 0;
  chomp($temp2);

  print "\n";
} until $temp1 eq $temp2;

# Turn back on terminal output
ReadMode 'normal';

my $passwd = $temp1;

my $ctx = Digest::MD5->new;
$ctx->add($passwd);
my $hash0 = $ctx->hexdigest;

my $hash1;
my $hash2;

if ($Fchck) {
  $ctx = Digest::MD5->new;
  $ctx->add(badcrypt($passwd, "\$1\$_2S43d5f\$"));
  my $tmp = $ctx->digest;
  $hash1 = encode_mac64($tmp);
  undef ($tmp);

  $ctx = Digest::MD5->new;
  $ctx->add($passwd);
  $tmp = $ctx->digest;
  $hash2 = encode_mac64($tmp);
  undef ($tmp);
}

print "\nYour PASSWD is: ".$hash0."\n";
print "--------------------------------------------------\n";
if ($Fchck) {
  print "Your FASTPASS1 is: ".$hash1."\n";
  print "Your FASTPASS2 is: ".$hash2."\n";
  print "--------------------------------------------------\n";
  print "Please copy all these values to your .conf file.\n";
  print "Do not fogret to include also the trailing '--' with FASTPASS\!).\n";
}
else {
  print "Please copy this value to your .conf file.\n";
}
print "\n";


################
# BADCRYPT
#############

sub badcrypt {
my $pw = shift;
my $salt = shift;
my $magic = '\$1\$';
my $magic2 = "\$1\$";

my $sp = $salt;

# print "Salt: ".$salt."\n";
# print "SP: ".$sp."\n";

$sp =~ s/^$magic//g;

# print "SP: ".$sp."\n";

my @temp = split(//, $sp);
my $ep;
my $count = 0;
foreach (@temp) {
  last if ($_ eq '$' || $count == 8);
  $ep = $ep.$_;
  $count++;
}
# print "EP: ".$ep."\n";

my $ctx = Digest::MD5->new;
$ctx->add($pw);
$ctx->add($magic2);
$ctx->add($ep);

my $ctx1 = Digest::MD5->new;
$ctx1->add($pw);
$ctx1->add($ep);
$ctx1->add($pw);

my $final = $ctx1->digest;
# print length($final)."\n";
$final = $final.chr(224).chr(182)."\n@";

# print "Final1: ".$final."\n";

my $pl = length($pw);

$pl = 16 if ($pl > 16);
$final = substr($final, 0, $pl);
# print "Final: ".$final." : PL: ".$pl."\n";
	
$ctx->add($final);

undef $final;
my $temp3 = (split(//,$pw))[0];

for(my $j = 0, my $i = $pl; $i > 0; $i >>= 1) {
  # print "takco?[".$i."]\n";
  $ctx->add($temp3) if $i != 1;
  $ctx->add(chr(0)) if $i == 1;
}

$final = $ctx->digest;
# print "Final1: ".$final."\n";

my $passwd = $magic2.$ep."\$";
# print "Final Passwd: ".$passwd."\n";

for (my $i = 0; $i < 1000; $i++) {
  my $ctx1 = Digest::MD5->new;
  if ($i & 1) {
	$ctx->add($pw);
  }
  else {
	$ctx->add($final);
  }
  if ($i % 3) {
	$ctx->add($ep);
  }
  if ($i % 7) {
	$ctx->add($pw);
  }
  if ($i & 1) {
	$ctx->add($final);
  }
  else {
	$ctx->add($pw);
  }
  $final = $ctx->digest;
}
# print "Final1000: ".$final."\n";

my @fin = unpack("C*",$final);

my @pass = split(//,$passwd);

my $p = \@pass;

my $l = ($fin[ 0]<<16) | ($fin[ 6]<<8) | $fin[12]; to64($p,$l,4);
$l = ($fin[ 1]<<16) | ($fin[ 7]<<8) | $fin[13]; to64($p,$l,4); 
$l = ($fin[ 2]<<16) | ($fin[ 8]<<8) | $fin[14]; to64($p,$l,4);
$l = ($fin[ 3]<<16) | ($fin[ 9]<<8) | $fin[15]; to64($p,$l,4);
$l = ($fin[ 4]<<16) | ($fin[10]<<8) | $fin[ 5]; to64($p,$l,4);
$l =                    $fin[11]                ; to64($p,$l,2);

undef $passwd;

foreach (@{$p}) {
$passwd = $passwd.$_;
}

return $passwd;
}

################
# ENCODE_MAC64
#############

sub encode_mac64 {
  my $what = shift;

  my $encoded = encode_base64($what);
  $encoded =~ s/\+/./g;
  $encoded =~ s/\//_/g;
  $encoded =~ s/=/-/g;

  chomp($encoded);
  return $encoded;
}

################
# TO64
#############

sub to64 {
  my $s = shift;
  my $v = shift;
  my $n = shift;
  my $str_itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  my @itoa64 = split(//,$str_itoa64);

  while (--$n >= 0) {
        $s->[@{$s}] = $itoa64[$v&0x3f];
        $v >>= 6;
  }
}

exit;
