1. Einleitung
Die Caesar-Verschlüsselung (bzw. Caesar-Chiffre) ist ein ebenso bekanntes wie einfaches Verschlüsselungsverfahren. Kernkonzept ist es, jeden Buchstaben im Alphabet um eine bestimmte Anzahl an Zeichen nach rechts oder links zu verschieben. So würde bei einer Verschiebung um +1 aus einem A ein B werden und entsprechend aus B ein C, aus C ein D usw. (Beim letzten Buchstaben springt man einfach an den Anfang: Aus Z wird demnach A.) Eine Verschiebung um +1 lässt sich durch eine Verschiebung um -1 umkehren. Die Verschlüsselung ist dadurch genauso einfach wie die Entschlüsselung und kann vom selben Algorithmus durchgeführt werden.
Grundsätzlich ist die Caesar-Verschlüsselung sehr leicht zu knacken und sollte daher nicht zum Verschlüsseln von sensiblen Daten verwendet werden.
2. Caesar-Verschlüsselung mittels Schleife
Im nachfolgenden Beispiel wird eine mögliche Funktion zur Umsetzung der Caesar-Verschlüsselung vorgestellt. Diese nimmt einen zu verschlüsselnden String $str, sowie die Verschiebung $moveBy entgegen. Optional kann ein eigenes Alphabet über $letters vorgegeben werden. Standardmäßig werden alle Zeichen von A bis Z, sowohl in Klein- als auch Großschreibung, verschlüsselt. Dabei werden diese zu einem Alphabet zusammengefügt (a-z, dann A-Z), sodass bei einer Verschiebung um +1 etwa „z” auf „A” und „Z” auf „a” abgebildet werden.
Die Funktion wandelt das zu verwendende Alphabet zunächst in zwei ähnliche Arrays um: Eines mit Aufbau „Position im Alphabet => Buchstabe” (int=>String), das andere in der Form „Buchstabe => Position im Alphabet” (String=>int). Anschließend durchläuft es den gesamten zu verschlüsselnden String. Für jedes einzelne Zeichen prüft es über das zweite Array, ob diesem Zeichen eine Position im Alphabet zugeordnet ist. Falls nicht, soll dieses Zeichen auch nicht verschlüsselt werden und wird daher identisch zum Rückgabestring hinzugefügt. Falls es jedoch vorhanden ist, wird die neue Position des (dann verschlüsselten) Zeichens im Alphabet über „($currentPos + $moveBy) % $count” ermittelt, wobei $currentPos der Position des aktuellen (unverschlüsselten) Zeichens im Alphabet entspricht, $moveBy der Verschiebung (z. B. +1) und $count der Anzahl aller Zeichen im gewünschten Alphabet. Über ($currentPos + $moveBy) wird das Zeichen um die Verschiebung $moveBy verschoben, bei +1 würde z. B. aus 0 (für „a”) eine 1 (für „b”). Die Anwendung des Modulo-Operators („% $count”) bewirkt, dass alles was über das Ende des Alphabets hinausgeht, am Anfang wieder anfängt. So würde etwa aus 51 (für Z) bei +1-Verschiebung keine 52, sondern 52 % 52 = 0 (für a) und bei einer +2-Verschiebung entsprechend 53 % 52 = 1 (für b).
<?php function caesar($str, $moveBy, $letters=null) { if ($letters===null) { $letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIHKLMNOPQRSTUVWXYZ'; } $letters = str_split($letters); $lettersFlipped = array_flip($letters); $count = count($letters); $out = ''; for ($x=0, $len=mb_strlen($str); $x<$len; ++$x) { $letter = mb_substr($str, $x, 1); $currentPos = (isset($lettersFlipped[$letter]) ? $lettersFlipped[$letter] : -1); if ($currentPos===-1) { $out[$x] = $letter; } else { $newPos = (($currentPos + $moveBy) % $count); $out[$x] = $letters[$newPos]; } } return implode('', $out); } var_dump(caesar('abcdefg', 1)); // erzeugt: bcdefgh var_dump(caesar('abcdefg', 2)); // erzeugt: cdefghi var_dump(caesar('abcdefg', 3)); // erzeugt: defghij var_dump(caesar('xyz', 3)); // erzeugt: ABC var_dump(caesar('test', 15)); // erzeugt: ItHI // Rückgängig machen einer +1-Verschiebung var_dump(caesar('bcdefg', -1)); // erzeugt: abcdef // erzeugt: PuqE uEF quz quzrmotqD emFL yuF 7 iöDFqDz. // (Zu beachten ist hier, dass alle Zeichen, die nicht Teil des Alphabets sind, // unverschlüsselt bleiben.) var_dump(caesar('Dies ist ein einfacher Satz mit 7 Wörtern.', 12)); // erzeugt: ?>
string(7) "bcdefgh" string(7) "cdefghi" string(7) "defghij" string(3) "ABC" string(4) "ItHI" string(6) "abcdef" string(43) "PuqE uEF quz quzrmotqD emFL yuF 7 iöDFqDz."
3. Caesar-Verschlüsselung mittels strtr()
Eine Alternative zur vorherigen Schleife bietet bei korrekter Anwendung die Funktion strtr($str, $from, $to). Diese nimmt einen String $str entgegen und bildet alle Zeichen aus $from auf $to ab, wobei wiederum das erste Zeichen aus $from auf das erste aus $to, das zweite aus $from auf das zweite auf $to usw. abgebildet werden. Nicht in $from aufgezählte Zeichen werden nicht abgebildet und stattdessen identisch übernommen. Rückgabe der Funktion ist ein String mit allen durchgeführten Ersetzungen. Entsprechend muss an die Funktion für $from das Ausgangsalphabet und für $to das Zielalphabet übergeben werden. Die Bildung von $to klingt kompliziert, ist aber tatsächlich sehr einfach, da das Ausgangsalphabet nur in zwei Abschnitte zerteilt werden und richtig zusammengefügt werden muss. Angenommen die Verschiebung lautet $moveBy, dann entspricht der erste Teil allen Zeichen von 0 bis $moveBy (nicht einschließlich des letzten) und der zweite allen von $moveBy bis zum Ende. Um $to zu erhalten werden beide Abschnitte dann umgekehrt (erst der zweite, dann der erste) und zu einem neuen String verbunden.
<?php function caesarStrtr($str, $moveBy) { static $from = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIHKLMNOPQRSTUVWXYZ'; $count = strlen($from); $moveBy = intval($moveBy) % $count; // hier wird das Zielalphabet erzeugt // wie oben beschrieben, muss das Ausgangsalphabet nur richtig zerteilt und // umgekehrt wieder zusammengefuegt werden $to = substr($from, $moveBy) . substr($from, 0, $moveBy); return strtr($str, $from, $to); } var_dump(caesarStrtr('abcd', 1)); // ergibt: bcde var_dump(caesarStrtr('ABCD', 1)); // ergibt: BCDE var_dump(caesarStrtr('XYZ', 3)); // ergibt: abc var_dump(caesarStrtr('abcd', 4)); // ergibt: efgh var_dump(caesarStrtr('abc', -3)); // ergibt: XYZ ?>
string(4) "bcde" string(4) "BCDE" string(3) "abc" string(4) "efgh" string(3) "XYZ"
4. str_rot13
Soll nur eine Verschiebung um +13 durchgeführt werden, dann kann die fest eingebaute Funktion str_rot13($str) verwendet werden. $str ist der zu verschlüsselnde String. Durch einmalige Anwendung wird er verschlüsselt, durch zweimalige wieder entschlüsselt.
<?php var_dump(str_rot13('abc')); // ergibt: nop var_dump(str_rot13('xyz')); // ergibt: klm var_dump(str_rot13('ABC')); // ergibt: NOP var_dump(str_rot13('$?!')); // ergibt: $?! var_dump(str_rot13(str_rot13('abc'))); // ergibt: abc ?>
string(3) "nop" string(3) "klm" string(3) "NOP" string(3) "$?!" string(3) "abc"