#!/usr/bin/perl -w

## vigenere decrypt tool
# (c) 2012 F00L.DE 
# by Rup0rt <roport at f00l dot de>

## check for arguments
# 1 - CIPHERTEXT
# 2 - KNOWN PLAINTEXT
# 3 - POSSIBLE KEY
# 4 - KEY LENGTH
if (!defined $ARGV[1]) {
  print "Usage: $0 <ciphertext> <plaintext> [possible_key] [key_length]\n";
  print "When supplying [possible_key] you must supply [key_length] too!\n";
  exit(1);
}

if ((defined $ARGV[2]) && (!defined($ARGV[3]))) {
  print "Usage: $0 <ciphertext> <plaintext> [possible_key] [key_length]\n";
  print "When supplying [possible_key] you must supply [key_length] too!\n";
  exit(1);
}

$ciphertext = $ARGV[0];
$plaintext = $ARGV[1];
$posskey = $ARGV[2];
$keylen = $ARGV[3];

$key = "";
$maxlen = length($ciphertext);
if (length($plaintext) < $maxlen) { $maxlen = length($plaintext); }

for ($pos=0;$pos<$maxlen;$pos++) {

  $cipherchar = lc substr($ciphertext, $pos, 1);
  if ((ord($cipherchar) >= 97) && (ord($cipherchar) <= 122)) {
    $plainchar = lc substr($plaintext, $pos, 1);

    $key = $key . chr(((ord($cipherchar)-ord($plainchar)) % 26) + 97);
  }

}

# ALIGN KEY USING POSSBILE KEY
if ($posskey) {
  $possindex = 0;
  $posspos = 0;

  if (length($posskey) < $keylen) { $posskey = $posskey . "?"x($keylen-length($posskey)); }
  if (length($posskey) > $keylen) { $posskey = substr($posskey, 0, $keylen); }
  if (length($key) > $keylen) { $key = substr($key, 0, $keylen); }
  $posskey = "$posskey$posskey";

  for ($pos=0; $pos < $keylen; $pos++) {
    $index = 0;
    for ($i=0; $i < length($key); $i++) {
      $posschar = substr($posskey, $pos+$i, 1);
      $char = substr($key, $i, 1);
      if ($posschar eq $char) { $index++; }
    }
    if ($index > $possindex) {
      $possindex = $index;
      $posspos = $pos;
    }
  }

  substr($posskey, $posspos, length($key)) = "$key";
  substr($posskey, $posspos+$keylen, length($key)) = "$key";

  $key = substr($posskey, $keylen, $posspos) . substr($posskey, $posspos, $keylen-$posspos);
}

print "$key\n";
