#!/usr/bin/perl -w
# Swordfish is a modified version of the original crypt.pl script 
# for Xchat which was based on monoalphabetic substitution cipher
# The cipher in this version has been replaced with a blowfish
# encryption to hexadecimal output. The script itself is based
# upon the Perl CPAN crypto modules which are needed for the 
# script to compile and run. The original script was tested on
# irc.stratics.com #Goddess where it was thought of as too easy
# to decipher. The only setback with this version is that you
# need to install the cryptomodules for Perl. It would ofcourse 
# be better if we could manage without the modules and make the 
# script standalone. You are welcome to help out with the script
# if you have any suggestions on how to make it better.
# 
# swordfish script by ronrafaelli@vorlonempire.com based on
# cryptolite script by sick_boy@irc.euirc.net based on 
# crypt.pl xchat script written by rodney@irc.xchat.org
# Licensed under GPL v2.0 and following - no warranty of any kind

my $cipher;
my $plaintext;
my $ciphertext;
my $keycode = "This is the Blowfish encryption key";
my $incolor = 05;
my $outcolor = 18;
my $mode = 1;
my $msgLine;
my $msgNick;
my $msgType;
my $logthisLine;

my $key_file ="$ENV{HOME}/.xchat/cryptolite.key";
my $note_file ="$ENV{HOME}/.xchat/note_file.log";

if ( -e "$key_file" ) {
	open (KEYF, "<$key_file");
	$keycode = <KEYF>;
	close (KEYF);
}

if ( -e "$ENV{HOME}/.xchat" ) {
	if ( -e "$ENV{HOME}/.xchat/xchatlogs" ) { }
	else {
        mkdir("$ENV{HOME}/.xchat/xchatlogs", 0755) || die "Cannot mkdir newdir: $!";  
	}
}

IRC::register("Swordfish script","1.1","","");
IRC::print("please do a /crypthelp for the options\n");
IRC::add_message_handler("PRIVMSG","monitor_em");
IRC::add_command_handler("crypthelp","help");
IRC::add_command_handler("setkey","new_key");
IRC::add_command_handler("cr","send_encrypted");
IRC::add_command_handler("7","send_encrypted");
IRC::add_command_handler("getkey","get_key");
IRC::add_command_handler("decrypt","manualdecrypt");
IRC::add_command_handler("encrypt","manualencrypt");
IRC::add_command_handler("note","notefile");
IRC::add_command_handler("incolor","set_incolor");
IRC::add_command_handler("outcolor","set_outcolor");
IRC::add_command_handler("hex","set_mode_hex");
IRC::add_command_handler("base64","set_mode_base64");
IRC::add_command_handler("localtime","get_time");
use Crypt::CBC;
use MIME::Base64;

sub new_key {
  $keycode = shift;
  $cipher = new Crypt::CBC ($keycode, 'Blowfish'); 
  open (KEYF, ">$key_file");
  print KEYF "$keycode";
  close (KEYF);
  return 1;
}

sub set_mode_hex {
   $mode = 0;
}

sub set_mode_base64 {
   $mode = 1;
}

sub set_incolor {
   $incolor = shift; 
}

sub set_outcolor {
   $outcolor = shift;
}

sub notefile {
  $plaintext = shift;
  open (NOTEF, ">>$note_file");
  print NOTEF "$plaintext\n";
  close (NOTEF);
  return 1;
}

sub get_key {
	IRC::print("key is : $keycode");
	return 1;
}

sub get_time {
  use POSIX qw(strftime);
  my $timeis = strftime "localtime: %Y %b %e [%H:%M:%S]", localtime;
  IRC::command("$timeis");
  return 1;
}

sub send_encrypted {
   my $mess = shift;  
   $plaintext = $mess;
   IRC::print("\003$outcolor$mess\n"); 
   $cipher = new Crypt::CBC ($keycode, 'Blowfish');
   if ($mode == 0) {
       $ciphertext = $cipher->encrypt_hex("$mess");
       $ciphertext = "¿$ciphertext";
       IRC::command("$ciphertext");
       &sendprinter;
   }
   else {   
       $ciphertext = $cipher->encrypt("$mess");
       $ciphertext = substr($ciphertext, 8);  # Remove RandomIV  
       $ciphertext = encode_base64($ciphertext);
       $ciphertext =~ s/[\n|\r]//g;
       $ciphertext = "§$ciphertext";
       IRC::command("$ciphertext");
       &sendprinter;
   }    
   return 1;
}

sub manualdecrypt {
   my $demess = shift;
      if($demess =~ m/§/){
	  $demess = substr($demess, 1);
	  $cipher = new Crypt::CBC ($keycode, 'Blowfish');
	  $demess = decode_base64($demess);
	  $demess = "RandomIV$demess";
	  $plaintext = $cipher->decrypt($demess);
	  IRC::print("\00311$plaintext\n");
      }
      elsif ($demess =~ m/¿/){
          $demess = substr($demess, 1);
	  $cipher = new Crypt::CBC ($keycode, 'Blowfish');
	  $plaintext = $cipher->decrypt_hex($demess);
	  IRC::print("\00311$plaintext\n");
      }
   return 1 ;   
}

sub manualencrypt {
   my $mess = shift;
   $cipher = new Crypt::CBC ($keycode, 'Blowfish');
       if ($mode == 0) {
          $ciphertext = $cipher->encrypt_hex("$mess");
          IRC::print("\00311¿$ciphertext");
       }
       else {
	  $ciphertext = $cipher->encrypt("$mess");
          $ciphertext = substr($ciphertext, 8);  # Remove RandomIV  
	  $ciphertext = encode_base64($ciphertext);
	  $ciphertext =~ s/[\n|\r]//g; # chomp / chop didnt work too good.
	  IRC::print("\00311§$ciphertext");
       }
   return 1 ;
}

sub monitor_em {
   #get irc infos
      my $myNick = IRC::get_info(1);
      my $actLine = shift(@_);
      #parse act. msg
      $actLine =~ m/\:(.*?)\!(.*?)\sPRIVMSG\s(.*?)\s\:(.*)?/;
      $msgNick = $1;
      my $hmSender = $2; 
      $msgType = $3;
      $msgLine = $4;
      $logthisLine = $msgLine;
#      chomp $logthisLine; # Or chop
      if($msgLine =~ m/§/){
	    $msgLine = substr($msgLine, 1);
	    $cipher = new Crypt::CBC ($keycode, 'Blowfish');
	    $msgLine = decode_base64($msgLine);
	    $msgLine = "RandomIV$msgLine";
	    $plaintext = $cipher->decrypt($msgLine);
	    &printer;
      }
      elsif ($msgLine =~ m/¿/){
	    $msgLine = substr($msgLine, 1);
	    $cipher = new Crypt::CBC ($keycode, 'Blowfish');
	    $plaintext = $cipher->decrypt_hex($msgLine);
	    &printer;	  
      }
      
  return 0 ;
}

sub sendprinter {
  my $channel = IRC::get_info(2);
  my $msgNick = IRC::get_info(1);
  use POSIX qw(strftime);
  my $timeis = strftime "%H:%M:%S", localtime;
  my $dateis = strftime "%Y%m%e", localtime;
  $channel = lc $channel;
  my $log_file ="$ENV{HOME}/.xchat/xchatlogs/$dateis.$channel.cryptlog";
  open (LOGF, ">>$log_file");
  print LOGF "$timeis  $ciphertext\n";
  print LOGF "  <$msgNick> $plaintext\n";
  close (LOGF);  
}

sub printer {
  use POSIX qw(strftime);
  my $timeis = strftime "%H:%M:%S", localtime;  
  my $dateis = strftime "%Y%m%e", localtime;
  $msgType = lc $msgType;
  my $log_file ="$ENV{HOME}/.xchat/xchatlogs/$dateis.$msgType.cryptlog"; 
  IRC::print("\003$incolor$plaintext\n");
  open (LOGF, ">>$log_file");
  print LOGF "$timeis  $logthisLine\n";
  print LOGF "  <$msgNick> $plaintext\n";
  close (LOGF);
}

sub help {
  IRC::print("SWORDFISH Script:\n");
  IRC::print("/crypthelp --brings up this menu\n");
  IRC::print("/getkey --will display the current key\n");
  IRC::print("/setkey newkey  --will change the key\n");
  IRC::print("/cr text to send  --sends the encrypted text\n");
  IRC::print("/decrypt hexline  --manually decrypts a hexadecimal line\n");
  IRC::print("/encrypt plaintext  --manually encrypts a textmessage\n");
  IRC::print("/note plaintext  --a quick way to note something in the note_file\n");
  IRC::print("/hex --sets encryption to hex output\n");
  IRC::print("/base64 --sets encryption to base64 output\n");
  return 1;
}
