#!/usr/bin/perl -w
################################################################
# porta.pl : Porta-Belaso cipher over the alphabet [A..Z]      #
#    Input from STDIN : plaintext                              #
#    Output to STDOUT : ciphertext                             #
#    Keys from command line :                                  #
#      key[0] determines the base alphabet.                    #
#             Example: key[0] = "SECRET" gives                 #
#                               SECRTABDFGHIJKLMNOPQUVWXYZ     #
#      key[1] determines which shift of the base alphabet to   #
#             use for each single position in the plain text.  #
#--------------------------------------------------------------#
# Special cases:                                               #
#   1. If key[1] is empty, the encryption is monoalphabetic    #
#      with key[0] as key.                                     #
#   2. If key[0] is trivial, for example "A", you get the      #
#      Trithemius cipher with key[1] as Belaso key (often      #
#      but uncorrectly called "Vigenere cipher").              #
#   3. If key[0] is trivial and key[1] is "long" you get the   #
#      running-key cipher that adds the plaintext and the key. #
#--------------------------------------------------------------#
# Transliteration of special characters according to English   #
#   rules                                                      #
# For special characters of other languages use preptext.pl    #
#   first.                                                     #
#--------------------------------------------------------------#
# Klaus Pommerening 1997-Jun-07, 1999-Oct-10                   #
#                                                              #
# This program is freeware. Use it as you like.                #
# Usual disclaimers apply.                                     #
################################################################

require "auxcrypt.pl";

$key[0] = $ARGV[0];                 # Get keys from command line.
$key[1] = $ARGV[1];                 #
$permut = &makeperm($key[0]);       # Make permutation from key.
$_ = &to26eng($key[1]);             # Prepare for using eval with tr
eval "tr/$permut/A-Z/";             # Preprocess key for addtext
$runkey = $_;

$plaintext = &gettext;              # Get plaintext from standard
                                    #   input.
$_ = &addtext($plaintext);          # 1st step: running-key
eval "tr /A-Z/$permut/";            # 2nd step: monoalph. subst.

&puttext($_);                       # Output ciphertext.

################################################################
# Subroutine addtext                                           #
#   Running text cipher                                        #
#     We identify the alphabet A-Z with the integers           #
#     0..25 and add the plaintext with the runkey mod 26       #
#     to get the ciphertext elementwise. If the runkey ist     #
#     exhausted before the plaintext, it is repeated from its  #
#     beginning.                                               #
#   Input:  plaintext as string of uppercase characters        #
#   Output: ciphertext as string of uppercase characters       #
#   Global variable: $runkey                                   #
################################################################
sub addtext {
  local(@inlist) = split(//,$_[0]);# Get input
  local(@key) = split(//,$runkey);# Runkey as list
  local($cipher);                 # Ciphertext for output
  local($i);                      # Loop counter
  local($j) = 0;                  # Auxiliary counter
  local($x);                      # Auxiliary variable
  local($y);                      # Auxiliary variable
  local($z);                      # Auxiliary variable

  for ($i = 0; $i < @inlist; $i++) {
    $x = $sa{$inlist[$i]};        # Interpret letter as number
    $y = $sa{$key[$j]};
    $z = $x + $y;                 # Running text cipher
    if ($z > 25) {$z = $z - 26;}
    $cipher .= $alphabet[$z];     # Append cipher text letter
    $j++;
    if ($j == @key) {$j = 0;}     # Da capo
    }
  return $cipher;
  } #--- addtext -----------------------------------------------
