lehrkraefte:blc:informatik:glf22:caesar

This is an old revision of the document!


Cäsar «Verschlüsselung» (Verschleierung)

Idee: Ein Text wird verschleiert, indem jeder Buchstabe $k$ Positionen weiter im Alphabet geschoben wird (wobei nach 'Z' wieder 'A' folgt).

Es gibt also nur 25 mögliche Schlüssel, was die Entschlüsselung auch von Hand trivial macht.

Im Pseudocode verwenden wir Variablen. Diese können im Laufe des Programms Ihre Werte wechseln (was in der Mathematik unüblich ist). Z.B. wird der Buchstabe $b$ u.U. mehrmals geändert, bevor er dem Resultat $r$ hinzugefügt wird (das sich auch in jeder Wiederholung ändert).

  • Input: Text $t$, Schlüssel $k$ (Ganzzahl zwischen $-25$ und $25$).
  • Output: Verschleierter Text
  • $r=$“” (leerer Text)
  • Für jeden Buchstaben $b$ im Text $t$:
    • Wenn $b$ ein Grossbuchstabe ist, sei $b$ der entsprechende Kleinbuchstaben
    • Wenn $b$ ein Kleinbuchstabe ist:
      • Verschiebe $b$ um $k$ Position im Alphabet
    • Hänge $b$ hinten an $r$ an.
  • Das Resultat ist $r$.

Was kommt als Resultat mit dem Input $t=$“Hey You!” und $k=3$ heraus?

Der Text und der Schlüssel werden direkt im Programm festgelegt. Die Ausgabe erfolgt auf der Konsole.

  • Die Funktion ord liefert den ASCII-Code (eine Zahl) für ein gegebenes Symbol (Buchstabe), d.h. die dem Symbol zuordnete Nummer.
    • Z.B. liefert ord('A') die Zahl 65, oder ord(' ') Die Zahl 32 (Code vom Leerschlag).
  • Die Funktion chr liefert das Symbol (als Text) für den gegebenen ASCII-Code (Zahl).
    • Z.B. liefert chr(65) den Text “A”, chr(97) den Text “a”.
  • In Python (und fast allen Programmiersprachen) werden Texte und Zahlen streng unterschieden. So ist 3 und “3” nicht das Gleiche. 3 steht für die Zahl 3 (womit auch gerechnet werden kann) und “3” steht für das Symbol (mit ASCII Code 51).
caesar1.py
text = "Hey You!"
key = 3
 
result = ""
for symbol in text:
    if symbol>='A' and symbol<='Z':
        symbol = chr(ord(symbol)+ord('a')-ord('A'))
    if symbol>='a' and symbol<='z':
        nummer = ord(symbol)+key
        if nummer<ord('a'):
            nummer = nummer+26
        if nummer>ord('z'):
            nummer = nummer-26
        symbol = chr(nummer)
    result = result + symbol
 
print(result)

Es werden direkt im Programmcode zwei Dateien und der Schlüssel festgelegt:

caesar2.py
input_datei = "input.txt"
key = 3
output_datei = "output.txt"
 
# Datei öffnen und einlesen (r für read)
with open(input_datei, "r") as f:
    text = f.read()
 
print(text)
 
result = ""
for symbol in text:
    if symbol>='A' and symbol<='Z':
        symbol = chr(ord(symbol)+ord('a')-ord('A'))
    if symbol>='a' and symbol<='z':
        nummer = ord(symbol)+key
        if nummer<ord('a'):
            nummer = nummer+26
        if nummer>ord('z'):
            nummer = nummer-26
        symbol = chr(nummer)
    result = result + symbol
 
print(result)
 
# Datei überschreiben und ausgeben (w für write)
with open(output_datei,"w") as f:
    f.write(result)

Legen Sie eine Datei input.txt mit einem Text drin an. Verschleiern Sie diese. Kopieren Sie dann wie folgt die Datei output.txt auf die Datei input.txt:

cp input.txt output.txt

Passen Sie dann im Programm den Schlüssel entsprechend an und überprüfen Sie, ob auch der Originaltext wieder erzeugt wird (bis auf Gross-/Kleinschreibung).

Diese Variante liest entweder direkt von der Konsole oder von einer Datei, und schreibt ebenfalls direkt auf die Konsole oder in eine Datei.

Der Schlüssel wird ebenfalls auf der Kommandozeile angegeben.

Starten Sie das Programm mit

python caesar3.py -h

um die Hilfe angezeigt zu bekommen.

caesar3.py
import argparse
import sys
import os
 
# Kommandozeilenoptionen festlegen
parser = argparse.ArgumentParser(description='Einfache Caesar-Verschleierung')
parser.add_argument('-k', '--key', nargs=1, type=int, help="Schlüssel, zwischen -25 und 25", required=True)
parser.add_argument('-i', '--infile', type=str, help="Optional: Datei, wovon gelesen werden soll.")
parser.add_argument('-o', '--outfile', type=str, help="Optional: Datei, wohin das Resultat geschrieben werden soll.")
parser.add_argument('-f', '--force', action="store_true", help="Output-Datei wird überschreiben, falls sie schon existiert");
 
# Auswerten
args = parser.parse_args()
 
# Schlüssel bestimmen
key = args.key[0]
if (key<-25 or key>25):
    sys.stderr.write("Der Schlüssel muss zwischen -25 und 25 liegen\n")
    exit(-1)  # Programm mit Fehlerstatus beenden
 
# Text von Datei oder Standardinput lesen
text = ""
# Input Datei gegeben?
if args.infile:
    # Datei öffnen und einlesen (r für read)
    if not os.path.exists(args.infile):
        sys.stderr.write(f"Input Datei {args.infile} nicht gefunden\n")
        exit(-1)
    with open(args.infile, "r") as f:
        text = f.read()
else: # sonst vom Standard-Input lesen
    text = sys.stdin.read()
 
 
# Verschleierung
result = ""
for symbol in text:
    if symbol>='A' and symbol<='Z':
        symbol = chr(ord(symbol)+ord('a')-ord('A'))
    if symbol>='a' and symbol<='z':
        nummer = ord(symbol)+key
        if nummer<ord('a'):
            nummer = nummer+26
        if nummer>ord('z'):
            nummer = nummer-26
        symbol = chr(nummer)
    result = result + symbol
 
# Resultat in Datei oder Standard Output ausgeben
if args.outfile:
    if (os.path.exists(args.outfile)) and (not args.force):
        sys.stderr.write(f"Die Datei {args.outfile} existiert bereits. Benutzen Sie -f um diese zu überschreiben\n")
        exit(-1)
    # Datei überschreiben und ausgeben (w für write)
    with open(args.outfile, "w") as f:
        f.write(result)
else: # Sonst ausgabe auf Standard Ouput
    sys.stdout.write(result)   # Fast das gleiche wie print(result), ausser dass print immer einen Zeilenumbruch hinzufügt.

Probieren Sie das Programm auf alle Varianten aus (mit/ohne Input-Datei, mit/ohne Output-Datei).

Verschleiern Sie einen kleinen Text mit einem «geheimen» Schlüssel. Tauschen Sie die Text-Dateien (kein Word bitte!) mit Ihrem Banknachbar aus. Entschleiern Sie dann den Text. Können Sie den richtigen Schlüssel auf Anhieb erraten?

Anspruchsvolle Aufgabe

Die hier programmierte Verschleierungsmethode ist insofern unschön, dass beim Entschlüsseln nicht unbedingt wieder der Originaltext herauskommt, weil Grossbuchstaben zu Kleinbuchstaben konvertiert werden. Erweitern Sie das Programm so, dass Grossbuchstaben auch in Grossbuchstaben verschleiert werden. Dazu müssen Sie die 2 Fälle gross/klein separat verschleiern. Ersetzen Sie dazu den if-Block, wo Gross- zu Kleinbuchstaben ersetzt werden mit einem entsprechenden Block, der die Verschleierung von Grossbuchstaben vornimmt (analog zur Verschleierung der Kleinbuchstaben).

  • lehrkraefte/blc/informatik/glf22/caesar.1666601320.txt.gz
  • Last modified: 2022/10/24 10:48
  • by Ivo Blöchliger