<b>Objektorientes PHP und Entwurfsmuster in Verbindung mit den *Ursprüngen der Kryptographie*</b><br/>
Ver- und Entschluesseln einer Zeichenkette mit Caesar`s Cipher<br/>
(vgl. Erste Aufgabe aus http://www.bundesnachrichtendienst.de/ueber/kryptografie.htm).<P/>

<?php
/* In diesem Beispiel wird die Klassendefinition der Einfacheit halber
* in der gleichen Datei mit der Ausgabeoberflaeche zusammengefasst. */

/** Meine Instanzen sind in der Lage Basisfunktionen (wie Eingabe-/Ausgabespeicherung, Bereitstellung von eines
  * Bezugsalphabets etc.) bereitzustellen, um zu ver- und entschlüsseln.
  * @author Toralf Richter
  */
class CipherBase {

/** Ein Alphabet wird als Verschluesselungsbasis erzeugt,
   * in diesem Fall ein einfaches "deutsches" 29-Buchstaben Alphabet mit den
   * Umlauten ä,ö,ü aber ohne ß und Satzsteuerzeichen etc.  */
var $realAlphaArray = array(
   
"1"=>"A",
   
"2"=>"B",
   
"3"=>"C",
   
"4"=>"D",
   
"5"=>"E",
   
"6"=>"F",
   
"7"=>"G",
   
"8"=>"H",
   
"9"=>"I",
   
"10"=>"J",
   
"11"=>"K",
   
"12"=>"L",
   
"13"=>"M",
   
"14"=>"N",
   
"15"=>"O",
   
"16"=>"P",
   
"17"=>"Q",
   
"18"=>"R",
   
"19"=>"S",
   
"20"=>"T",
   
"21"=>"U",
   
"22"=>"V",
   
"23"=>"W",
   
"24"=>"X",
   
"25"=>"Y",
   
"26"=>"Z",
   
"27"=>"Ä",
   
"28"=>"Ö",
   
"29"=>"Ü"
  
);
/** Ausgangswert einer De-/Enkodierung */
var $inputString = "";
/** Ergebnis einer De-/Enkodierung */
var $outputString = "";
/** Verwendeter Offset-Typ "standard" für Standard Offset von Caesars Cipher (3),
   * "variable" für variablen an der Länge der der Input-Zeichenkette orientierten Offset */
// var $offsetType = "standard";

/** Setter für inputString */
function setInputString( $is ) {
  
$this->inputString = $is;
}

/** Setter für outputString */
function setOutputString( $os ) {
  
$this->outputString = $os;
}

/** Setter offsetType */
/* function setOffsetType( $ot ) {
  $this->offsetType = $ot;
}*/

/** Gibt das verwendete unterliegende Ver-/Entschlüsselungsalphabet zurück.
   * Eine Getter-Methode wird zwar in PHP (zumindest kleiner 5) nicht benötigt,
   * aber Sie soll hier aus Gründen der Portierbarkeit zu Java bereits angelegt werden. */
function getRealAlphaArray() {
  return
$this->realAlphaArray;
}

/** das verwendete Alphabet kann in der Zahl Zeichen variieren, also ermittelt
   * man die Laenge und gibt mit dieser Funktion Ihren Wert zurück */
function getRealAlphaArrayLength() {
  return
count( $this->realAlphaArray );
}

/** Konstruktor */
function CipherBase() {
}
}

/** Meine Instanzen erweitern CipherBase und nutzen die dort enthaltene Basisfunktionalitaet.
  * Zusaetzlich wird in dieser Klasse die benötigte Funktionalitaet zu "Verbesserung" des
  * Schluessels der Caesar's Cipher mit variablem Offset bereitgestellt.
  * Die Klasse wurde ohne eigenen Konstruktor implementiert, damit wird unter PHP 4 der Konstruktor der
  * Parent-Klasse verwendet (nicht so unter PHP 3!)
  * @author Toralf Richter
  */
class CcCipherBase extends CipherBase {

/** Setter offsetType */
function setOffsetType( $ot ) {
  
$this->offsetType = $ot;
}

/** Verwendeter Offset-Typ "standard" für Standard Offset von Caesars Cipher (3),
   * "variable" für variablen an der Länge der der Input-Zeichenkette orientierten Offset */
var $offsetType = "standard";

}

/** Eine simple Factory Klasse, die momentan, da im Beipsiel nur Ceasar's Cipher implementiert ist,
  * auch nur Objektes vom Typ CcCipherBase erzeugen kann. Das es mit dem im Beispiel vorgeschlagenen
  * Muster leicht moeglich sein sollte, weitere Schluessel-Implementierung in Form der verwendeten
  * Kommando-Klassen einzubeziehen, bildet die Factory eine relativ einfache Art variierende
  * Arten von Verschluesselungsbasisobjektes zu erzeugen.
  * @author Toralf Richter
  */
class CipherFactory {

/**
   * @param $cipherType - Name der zu instanziierenden Verschluesselungs-Basisklasse
   * @exception - eine Exception im eigentlichen Sinne ist nicht werfbar.
   *              Wenn fuer den uebergebenen Klassennamen keine Instanz erzeugbar ist (die Klasse im
   *              verfuegbaren Scope (=Script) nicht definiert ist, wird ein exyit des Scripts
   *              mit Fehlermeldung erzwungen
   */
function getCipherBaseObject( $cipherType ) {
  if(
class_exists( $cipherType ) ) {
   return new
$cipherType;
  } else {
   die(
"Error: CipherBase class by name of ".$cipherType." not implemented" );
  }
}
}

/** Abstrakte Vorlage für ableitende Command Klassen. Da es in PHP 4 noch keine Definition von
  * abtrakten Klassen (oder Interfaces ... ) gibt muss in der Entwicklung selbst darauf achten
  * eine per dokumentierter Konvention als abstrakt bezeichnete Klasse auch derart zu verwenden.
  * @author Toralf Richter
  */
class AbstractCommand {

/** Array von Parametern die von der jeweiligen Implementierung der excute() Methode ausgewertet werden sollten */
var $paramsArray;

/* Konstruktor */
function AbstractCommand() {
}

/** Abstrakte Vorlage für die execute() Methode der ableitenden Klassen.
   * In dieser Klasse hier funktionslos
   * @param &$objToExcuteOn
   * @exception - eine Exception im eigentlichen Sinne ist nicht werfbar. Das Script wird mit
   *              Fehlerausgabe terminiert, wenn versucht wird die excute() Methode in dieser
   *              als abstrakt konzipierten Klasse aufzurufen
   */
function execute( &$objToExcuteOn ) {
  
/* Hier wid ein deutlicher Hinweis ausgegeben, dass eine akstrakte Klasse instanziert wurde */
  
die("Error: Call to abstract method. Please, use sub-classing and implement your own execute method!");
}

/** Setter Methode für die Parameter des Command */
function setParams( $paramsArray ) {
  
$this->paramsArray = $paramsArray;
}

}

/** Meine Instanzen versuchen nutzvolle (im Rahmen dieses Beispiels) Verwendung des Command Pattern für
  * das Chiffrieren mit Ceasars Cipher zu machen.
  * Dazu wird die Klasse AbstractCommand erweitert und die execute() Methode zweckgebunden implementiert.
  * Die Klasse wurde ohne eigenen Konstruktor implementiert, damit wird unter PHP 4 der Konstruktor der
  * Parent-Klasse verwendet (nicht so unter PHP 3!)
  * @author Toralf Richter
  */
class CcCipherCommand extends AbstractCommand {

/** Der Methode muss das Basisobjekt ($objToExcuteOn), auf dem das Kommando ausgefuehrt werden soll *by reference* uebergeben werden.
   * Sodann werden die einzelnen Buchstaben der Eingabe im Basisobjekt im unterliegenden Alphabet aufgefunden
   * und anhand des entsprechenden Offset enkodiert.
   * Das Ergebnis wird in das Basisbjekt auf dem das Kommando ausgeführt wird geschrieben ($objToExcuteOn->SetOutputString( String ) )
   * @param &$objToExcuteOn
   */
function execute( &$objToExcuteOn ) {
  
/* CC Standard Offset */
  
$offset = 3;
  
/* "Verbesserung" des Schluessels mit variablem Offset, Einarbeiten der (in diesem Fall
   * aus den aus den Post Vars beziehbaren) Parameter
   */
  
if(isset($this->paramsArray["use_length"])) {
   
$offset = strlen( $objToExcuteOn->inputString ) % $objToExcuteOn->getRealAlphaArrayLength();
   
$objToExcuteOn->setOffsetType( "variable");
  } else {
   
$objToExcuteOn->setOffsetType( "standard");
  }

  
$output_string = "" ;
  
$i=0;
  while(
$i+1<=strlen($objToExcuteOn->inputString)) {
   
/* Feststellen des aktuellen Eingabe-Buchstaben */
   
$input_letter=$objToExcuteOn->inputString[$i];

   
/* Überspringen von Leerzeichen */
   
if($input_letter==" ") {
     
$i++;
     
$output_string .= " ";
     continue;
   }
   
/* Feststellen der Index-Position des Ergebnis-Buchstabens im verwendeten Alphabet */
   
$output_letter_index=array_search(strtoupper($input_letter),$objToExcuteOn->getRealAlphaArray() )+$offset;

   
/* Korrigieren der Index-Position des Ausgabe-Buchstabens für den Fall, dass durch den
    * Offset der Index "um Anfang oder Ende des Alphabets gewickelt wird"
    */
   
if($output_letter_index<=0) {
    
$output_letter_index=$objToExcuteOn->getRealAlphaArrayLength()+$output_letter_index;
   }
   if(
$output_letter_index>$objToExcuteOn->getRealAlphaArrayLength()) {
    
$output_letter_index=-$objToExcuteOn->getRealAlphaArrayLength()+$output_letter_index;
   }

   
/* Anfuegen an das Temporaer-Ergebnis */
   
$output_string.=$objToExcuteOn->realAlphaArray[$output_letter_index];
   
$i++;
  }

  
/* Uebernahme des Ergebnisses in das Basisobjekt */
  
$objToExcuteOn->setOutputString( $output_string );
}
}

/** Meine Instanzen versuchen nutzvolle (im Rahmen dieses Beispiels) Verwendung des Command Pattern für
  * das Dechiffrieren mit Ceasars Cipher zu machen.
  * Dazu wird AbstractCommand erweitert und die execute() Methode zweckgebunden implementiert
  * Die Klasse wurde ohne eigenen Konstruktor implementiert, damit wird unter PHP 4 der Konstruktor der
  * Parent-Klasse verwendet (nicht so unter PHP 3!)
  * @author Toralf Richter
  */
class CcDecipherCommand extends AbstractCommand {

/** Der Methode muss das Basisobjekt ($objToExcuteOn), auf dem das Kommando ausgefuehrt werden soll *by reference* uebergeben werden.
   * Sodann werden die einzelnen Buchstaben der Eingabe im Basisobjekt im unterliegenden Alphabet aufgefunden
   * und anhand des entsprechenden Offset dekodiert.
   * Das Ergebnis wird in das  Bsasisobjekt auf dem das Kommando ausgeführt wird geschrieben ($objToExcuteOn->SetOutputString( String ) )
   * @param &$objToExcuteOn
   */
function execute( &$objToExcuteOn ) {
  
/* CC Standard Offset */
  
$offset = -3;
  
/* "Verbesserung" des Schluessels mit variablem Offset, Einarbeiten der (in diesem Fall
   * urspruenglich aus den aus den Post Vars beziehbaren) Parameter
   */
  
if(isset($this->paramsArray["use_length"])) {
   
$offset= 0-(strlen( $objToExcuteOn->inputString ) % $objToExcuteOn->getRealAlphaArrayLength() );
   
$objToExcuteOn->setOffsetType( "variable");
  } else {
   
$objToExcuteOn->setOffsetType( "standard");
  }

  
$output_string = "" ;
  
$i=0;
  while(
$i+1<=strlen($objToExcuteOn->inputString)) {
   
/* Feststellen des aktuellen Eingabe-Buchstaben */
   
$input_letter=$objToExcuteOn->inputString[$i];

   
/* Ueberspringen von Leerzeichen */
   
if($input_letter==" ") {
     
$i++;
     
$output_string .= " ";
     continue;
   }
   
/* Feststellen der Index-Position des Ergebnis-Buchstabens im verwendeten Alphabet */
   
$output_letter_index=array_search(strtoupper($input_letter),$objToExcuteOn->getRealAlphaArray() )+$offset;

   
/* Korrigieren der Index-Position des Ausgabe-Buchstabens für den fall, dass durch den
    * Offset der Index "um Anfang oder Ende des Alphabets gewickelt wird"
    */
   
if($output_letter_index<=0) {
    
$output_letter_index=$objToExcuteOn->getRealAlphaArrayLength()+$output_letter_index;
   }
   if(
$output_letter_index>$objToExcuteOn->getRealAlphaArrayLength()) {
    
$output_letter_index=-$objToExcuteOn->getRealAlphaArrayLength()+$output_letter_index;
   }

   
/* Anfuegen an das Temporär-Ergebnis */
   
$output_string.=$objToExcuteOn->realAlphaArray[$output_letter_index];
   
$i++;
  }

  
/* Uebernahme des Ergebnisses in das Basisobjekt */
  
$objToExcuteOn->setOutputString( $output_string );
}
}

/* Instanz der der zu verwendeten Basisklasse mittels der factory erzeugen */
$ccb = CipherFactory::getCipherBaseObject( "CcCipherBase" );

if(isset(
$_POST["input"] )) {
  
$ccb->setInputString( $_POST["input"] );
  
/* 1. Fall der Enkodierung */
  
if(isset($_POST["decipher"])) {
   
$cmd = new CcDecipherCommand();
  
/* 2. Fall der Dekodierung */
  
} elseif(isset($_POST["cipher"])) {
   
$cmd = new CcCipherCommand();
  } else {
   
/* hier passiert funktional nichts */
  
}

  
/* Kommando parametrisieren und ausführen */
  
$cmd->setParams( $HTTP_POST_VARS );
  
$cmd->execute( &$ccb );

/* Ergebnis-Ausgabe für die aktuelle Aktion */
echo "Eingabe: " . $ccb->inputString . "<br>";
echo
"Ausgabe: " . $ccb->outputString. "<br>";
echo
"verwendeter Offset-Typ: " . $ccb->offsetType. "<br>";

  }
?>

<FORM ACTION="<?php echo $PHP_SELF ?>" METHOD="POST">
<input type="text" name="input" value="<?php echo $ccb->outputString ?>" STYLE="width: 500px"><BR>
<!-- JDOOLD HVW RPQLV GLYLVD LQ SDUWHV WUHV -->
Variabler Offset: <INPUT TYPE="Checkbox" NAME="use_length" VALUE="1"<?php echo ($ccb->offsetType=="variable")?" checked":"" ?>>
<input type="submit" name="decipher" value="Als Klartext">
<input type="submit" name="cipher" value="Verschluesseln">

</FORM>

<ol style="width: 550px">
  <li> Es stehen Ihnen folgende Moeglichkeiten der Benutzung zur Verfuegung: Entschluesselung oder Verschluesselung (1. Mit Original Caesars
       Cipher Zeichen-Offset oder 2. mit "variablem Offset", der dem Modulus "Anzahl Zeichen in der Botschaft" % "Anzahl Zeichen im verwendeten Alphabet
       entspricht"). <b>Bitte beachten Sie</b>, dass das zugrundeliegende Chiffrierungsalphabet zwar die deutschen Umlaute &Auml;, &Ouml;, &Uuml; kennt, aber
       kein &szlig; oder Satzsteuerzeichen etc. Fuer den Fall, dass das Script auf einem Rechner mit einer nicht-deutschen Locale zum laufen gebracht
       wird, koennen u.U. Darstellungsprobleme auftreten.
  <li> Falls Sie den Algorithmus mit dem "variablen Offset" variieren:
       Das Caesar`s Cipher Verschluesselungsmuster ist hinreichend bekannt. Fuer den Fall, dass man es variieren moechte, koennte man beispielsweise
       als Offet-Wert fuer die zugrundeliegende Zeichenverschiebung innerhalb des Basisalphabets einen Wert waehlen, der dem Modulus "Anzahl Zeichen
       in der Botschaft" % "Anzahl Zeichen im verwendeten Alphabet" entspricht und damit ein gewisses *Zufallsmoment* einfuehren.
       <B>ANMERKUNG:</B> Sollten Sie die variablen Offsets ausprobieren wollen, einfach die Checkbox anklicken, dann bitte zuerst eine Botschaft
       verschluesseln. Der Ergebniswert der Verschluesselung und das Merkmal "variabler Offset" werden automatisch fuer die Entschluesselung, die Sie
       als naechsten Schritt ausfuehren koennen, uebernommen.
  <li> Variante zum variablen Offset (nicht implementiert): Weiterhin waere denkbar, um in die Chiffrierung ein gewisses *Zufallsmoment* einzufuehren und  damit die bei dieser Methode zwangslaeufig
       entstehenden Muster weniger augenfaellig zu machen: Es k&ouml;nnte koennte ein variabler Offset verwendet werden, der sich an der Position des
       momentan verschluesselten Zeichens innerhalb der Botschaft orientiert. Dadurch wird das Prinzip aber nicht mittels Mustererkenung "unknackbar",
       da immer wieder Muster entstehen werden.
</ol>


<?php

echo "<BR>&nbsp;<P><B>Quelltext des Beispiels: </B><P>";

echo
"<pre>";


$filename = $HTTP_SERVER_VARS["SCRIPT_FILENAME"];
$fd = fopen($filename, "r");
$source = fread($fd, filesize ($filename));
fclose($fd);
//$source =
highlight_string( $source );
//echo $source;

echo "</PRE>";

?>