#  texstegi-02.pl  April 12, 2011
my $version=02;
# use spaces again
# some letters e tao inshr have 5 4 and 3 codes each for frequency masking
use strict;
use warnings;
# additives are lines at the end of key file beginning with ```
my $additives = 2;
# Indentation Steganography
# Not copyrighted by Alan Folmsbee or anyone else.
# report unused key codes 4/7/11
# check unused key values, added key final 2 lines: pad and extension 
# additives:
# ```40`pad
# ```99`ext
# when extension code is read, two more codes follow from 00 to 99
# those four extended code numerals can be allocated to any operation

# Use two paired carrier lines for each secret character
# characters numbered 00 to 99, so max addition is 9, min 0
# first digit in first of pair, second digit in second line of pair
# count spaces for carrier to meet key goal to encode secret
# Added checking for key duplicate entries 4/4/11

# five files are used, first, this Perl program 
# in C:/export/PopCryMag/perl
# second x.txt the draft carrier paragraph
# third secret-15.txt a short secret sentence, about 20 characters
# fourth key-15.txt 
# fifth result01_x.txt
# see http://popcryspri11.blogspot.com/p/indentation-steganography.html
# Perl for Popular Cryptography Magazine, Connecticut Office

my $padding3 = 1;
my $extension = 1;

# open 3 input files and 1 output file
my $path = "C:/export/PopCryMag/perl/";
print "What file in $path has the draft carrier text file?\n";
print "Enter the filename, like texst-15\n";

my $carrier=<STDIN>;
chomp $carrier;
if (ord($carrier) == ord(""))
   { 
   $carrier = "texst-15";
   }
my $carrier_in = "$path"."$carrier".".txt";
open(CARRIER, "$carrier_in") or die "Can't open $carrier_in : $!";
my $secret_in = "$path"."secret-15.txt";
open(SECRET, "$secret_in") or die "Can't open $secret_in : $!";

print "What filenumber in $path has the key, like 10 or 25?\n";
print "Enter the filenumber, like 15\n";
my $key_number=<STDIN>;
chomp $key_number;


if (ord($key_number) == ord(""))
   { 
   $key_number = "15";
   }

my $key_in = "$path"."key-"."$key_number".".txt";
open(KEY, "$key_in") or die "Can't open $key_in : $!";

my $result = "$path"."result"."$version"."_$carrier".".txt";
open(OUT, ">$result") or die "Can't open $result : $!";


# Store the secret sentence and count how many letters and spaces
my $line;
$line = <SECRET>;
chomp $line;
my @sentence;
print "$line...is the secret message\n";
@sentence = split (//,$line);
my $sizeS = @sentence;
print "$sizeS characters in the secret sentence\n";


# Store the carrier paragraph and see how many lines and characters
my $count;
my $sizeof_carrier;
my @carrier_line;
while ($line = <CARRIER>)
{
  chomp $line;
  $count++;
  @carrier_line = split (//,$line);
  $sizeof_carrier = @carrier_line;
  print "$sizeof_carrier characters in carrier paragraph\n";
}
print "$count line in carrier paragraph, $sizeof_carrier characters\n";
close (CARRIER);


# store the key 
$count = 0;
my $j;
my $i;
my $k;
my $m;
my @key_line;
my @key_map;
while ($line = <KEY>)
  {
  chomp $line;
 # print "$line\n";
  $key_line[$count]= $line;
  $count++;
  }
print "$count lines in key\n";
my $key_size = $count;
close (KEY);
close (SECRET);


# list the secret "sentence" as ascii numbers
my $value;
print "The secret is... ";
for ($i=0; $i<$sizeS; $i++)
  {
  $value = ord($sentence[$i]);
  print "$value ";
  }
print " ascii\n";


# make array called @offset of keyed numbers 
# according to each letter in secret sentence
my @offset;
$count=0;
print "offsets are: ";
# loop secret of about 20 characters
# watching for frequent letters 

# e tao inshr dlu cmfwypvbgkqjxz  english frequencies
# 5 444 33333 222 11111111111111

my $flag_match;
my $frequ_e = 5;
my $count_e = 0;
my $frequ_t = 4;
my $count_t = 0;
my $frequ_a = 4;
my $count_a = 0;
my $frequ_o = 4;
my $count_o = 0;
my $frequ_i = 3;
my $count_i = 0;
my $frequ_n = 3;
my $count_n = 0;
my $frequ_s = 3;
my $count_s = 0;
my $frequ_h = 3;
my $count_h = 0;
my $frequ_r = 3;
my $count_r = 0;

for ($i=0; $i<$sizeS; $i++)
    {
    $flag_match = 0;
    for ($j=0; $j<($key_size - $additives); $j++)
        {
         @key_map = split (/`/,$key_line[$j]);
         if ((ord($key_map[0]) == ord($sentence[$i]))&&($flag_match == 0))
            {
             $offset[$i] = $key_map[1];


             if ((ord($key_map[0]) == ord("e")) && ($count_e < $frequ_e))
                {
                $flag_match = 1;
                $j += $count_e;
                $count_e++;
                if ($count_e == $frequ_e)
                   {
                    $count_e = 0;
                   }
                @key_map = split (/`/,$key_line[$j]);
                $offset[$i] = $key_map[1];
                }

             if ((ord($key_map[0]) == ord("t")) && ($count_t < $frequ_t))
                {
                $flag_match = 1;
                $j += $count_t;
                $count_t++;
                if ($count_t == $frequ_t)
                   {
                    $count_t = 0;
                   }
                @key_map = split (/`/,$key_line[$j]);
                $offset[$i] = $key_map[1];
                }

             if ((ord($key_map[0]) == ord("a")) && ($count_a < $frequ_a))
                {
                $flag_match = 1;
                $j += $count_a;
                $count_a++;
                if ($count_a == $frequ_a)
                   {
                    $count_a = 0;
                   }
                @key_map = split (/`/,$key_line[$j]);
                $offset[$i] = $key_map[1];
                }   


             if ((ord($key_map[0]) == ord("o")) && ($count_o < $frequ_o))
                {
                $flag_match = 1;
                $j += $count_o;
                $count_o++;
                if ($count_o == $frequ_o)
                   {
                    $count_o = 0;
                   }
                @key_map = split (/`/,$key_line[$j]);
                $offset[$i] = $key_map[1];
                }

             if ((ord($key_map[0]) == ord("i")) && ($count_i < $frequ_i))
                {
                $flag_match = 1;
                $j += $count_i;
                $count_i++;
                if ($count_i == $frequ_i)
                   {
                    $count_i = 0;
                   }
                @key_map = split (/`/,$key_line[$j]);
                $offset[$i] = $key_map[1];
                }


             if ((ord($key_map[0]) == ord("n")) && ($count_n < $frequ_n))
                {
                $flag_match = 1;
                $j += $count_n;
                $count_n++;
                if ($count_n == $frequ_n)
                   {
                    $count_n = 0;
                   }
                @key_map = split (/`/,$key_line[$j]);
                $offset[$i] = $key_map[1];
                }

             if ((ord($key_map[0]) == ord("s")) && ($count_s < $frequ_s))
                {
                $flag_match = 1;
                $j += $count_s;
                $count_s++;
                if ($count_s == $frequ_s)
                   {
                    $count_s = 0;
                   }
                @key_map = split (/`/,$key_line[$j]);
                $offset[$i] = $key_map[1];
                }

             if ((ord($key_map[0]) == ord("h")) && ($count_h < $frequ_h))
                {
                $flag_match = 1;
                $j += $count_h;
                $count_h++;
                if ($count_h == $frequ_h)
                   {
                    $count_h = 0;
                   }
                @key_map = split (/`/,$key_line[$j]);
                $offset[$i] = $key_map[1];
                }

             if ((ord($key_map[0]) == ord("r")) && ($count_r < $frequ_r))
                {
                $flag_match = 1;
                $j += $count_r;
                $count_r++;
                if ($count_r == $frequ_r)
                   {
                    $count_r = 0;
                   }
                @key_map = split (/`/,$key_line[$j]);
                $offset[$i] = $key_map[1];
                }
            }
         }
     }


# look at offsets
for ($i=0; $i<$sizeS; $i++)
    {
     print "$offset[$i] ";
    }

# check for duplicate numbers in key and report unused 2 digit codes
my @check;
my @unused;
for ($k=0; $k<100; $k++)
    {
     $unused[$k] = 1;
    }

print "\nkey duplicate search and report any additives \n";
for ($k=0; $k<$key_size; $k++)
    {
    @key_map = split (/`/,$key_line[$k]);
    if (@key_map < 4)
     {
    $check[$k] = $key_map[1];
    $unused[$check[$k]] = 0;
    for ($m=0; $m<($key_size - $additives); $m++)
        {
        @key_map = split (/`/,$key_line[$m]);
        if ($check[$k] == $key_map[1])
           {
           if ($k != $m)
              {
    print "$check[$k] - $k $m /\n";
              }
           }
        }
      }
     if (@key_map > 3)
      {
        print "$key_line[$k]\n";
        if ($key_line[$k] =~ "pad")
           {
            $padding3 = $key_map[3];
           }
       
        if ($key_line[$k] =~ "ext")
           {
            $extension = $key_map[3];
           }
        
      }
     }
print "\nsecret characters number $i\nkey entries number $j\n";
print "Unused codes available for key changes...\n";
for ($k=0; $k<100; $k++)
    {
     if ($unused[$k] == 1)
        {
         print "$k ";
        }
    }
print "\nPadding can be any value. It does not affect key codes.\n";
print "Extension code must be unused by key, as reported above.\n\n";



# now write the carrier with key-coded newlines positioned at offset
my @pair;
my $count_spaces=0;
my $start = 0;
# $j is the line number for the result
for ($j=0; $j<$sizeS; $j++)
{
$count_spaces=0;
if ($offset[$j]<10)
  {
   $pair[0]=0;
   $pair[1]=$offset[$j];
  }
if ($offset[$j]>=10)
  {
   @pair = split (//,$offset[$j]);
  }
for ($i=$start; $i<($start + $pair[0] + $padding3 + $count_spaces); $i++)
  {
 #do not print leading space
 if (($i == $start)&&(ord($carrier_line[$i]) == 32))
   {
    $count_spaces++;
   }
 #do print other spaces, letters, etc.
  else
   {
   # do include the spaces towards the goal, but count them to ignore them
   if (ord($carrier_line[$i]) == 999)
      {
       print OUT "$carrier_line[$i]";
       print     "$carrier_line[$i]";
       $count_spaces++;
      }
   else
      {
       print OUT "$carrier_line[$i]";
       print     "$carrier_line[$i]"; 
       }
    }
  }
$start = $i;
print OUT "\n";
print     "\n";

$count_spaces = 0;

for ($i=$start; $i<($start + $pair[1] + $padding3 + $count_spaces); $i++)
  {
 #do not print leading space
 if (($i == $start)&&(ord($carrier_line[$i]) == 32))
   {
    $count_spaces++;
   }
 #do print other spaces, letters, etc.
  else
   {
   # do include the spaces towards the goal, but count them to ignore them
   if (ord($carrier_line[$i]) == 999)
      {
       print OUT "$carrier_line[$i]";
       print     "$carrier_line[$i]";
       $count_spaces++;
      }
   else
      {
       print OUT "$carrier_line[$i]";
       print     "$carrier_line[$i]"; 
       }
    }
  }
$start = $i;
print OUT "\n";
print     "\n";
}
print "This many letters: $i, padding was $padding3, extension code was $extension\n";
close (OUT);
exit();  