Caesar-Verschlüsselung

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Benutzeravatar
Klapperschlange
User
Beiträge: 6
Registriert: Freitag 4. Januar 2008, 15:55
Kontaktdaten:

Hallo zusammen im Forum (erster Post :D )!

Ich habe mich etwas mit Python beschäftigt und für meine Facharbeit in Mathe auch mein erster kleines "Programm" geschrieben, dass einen Text (auch aus einer Textdatei) verschlüsselt und den Geheimtext wiedergibt.

Kommentare/Anregungen/Kritik/... zum Code, Programmierstil und den Anmerkungen (musste ich für den Lehrer machen) nehme ich gerne entgegen.

Hier der Code:

Code: Alles auswählen

print "Viel Spass mit meinem Programm fuer eine Caesar-Verschluesselung"
print "Bei einer Entschluesselung bitte das negative Vorzeichen beachten!"

#Verschiebung um x Stellen
print
x = int(raw_input('Um wieviele Stellen soll das Alphabet verschoben werden? '))

#Textdatei ausgeben?
a = raw_input('Soll eine Textdatei ausgegeben werden (j/n)? ')
if a == "j":
    a = 1
else:
    a = 0

#Bearbeitung des zu verschluesselnden Textes
#Soll eine Textdatei importiert werden?
b = raw_input('Soll eine Textdatei importiert werden (j/n)? ')
if b == "j":
    b = 1
else:
    b = 0
#Eingabe des zu verschluesselnden Textes
#Aus Textdatei
if b == 1:
    c = raw_input('Bitte Verzeichnis und Dateiname der .txt-Datei angeben: ')
    e = file(c, 'rb')
    t = e.read()
    e.close()
#Als Eingabe
else:
    t = raw_input('Einen Text zum Verschluesseln/Entschluesseln eingeben: ')
#Umwandlung in eine Liste
l = list(t)

#Umwandlungvorschrift der eingegeben Buchstaben (mithilfe eines Dictionaries)
d = {   "a":0 , "b":1 , "c":2 , "d":3 , "e":4 ,
        "f":5 , "g":6 , "h":7 , "i":8 , "j":9 ,
        "k":10, "l":11, "m":12, "n":13, "o":14,
        "p":15, "q":16, "r":17, "s":18, "t":19,
        "u":20, "v":21, "w":22, "x":23, "y":24, "z":25   }

#Umwandlungsvorschrift der Zahlen in Buchstaben
e = {  0 :"a", 1 :"b", 2 :"c", 3 :"d", 4 :"e",
       5 :"f", 6 :"g", 7 :"h", 8 :"i", 9 :"j",
       10:"k", 11:"l", 12:"m", 13:"n", 14:"o",
       15:"p", 16:"q", 17:"r", 18:"s", 19:"t",
       20:"u", 21:"v", 22:"w", 23:"x", 24:"y", 25:"z"   } 

#Verschluesselung
#Leere Hilfsliste definieren
m = []
#Verschluesselung der einzelnen Buchstaben mit 'while'-Schleife
i = 0
while i < len(l):
    m.append(e[(d[l[i]] + x)%26])
    i = i + 1

#Ausgabe
#Hilfsstring definieren
s = ""
#Ausgabe als Textblock
j=0
while j < len(m):
    s = s + m[j]
    j = j + 1
#Ausgabe in Konsole
if a == 0:
    print
    print "Dies ist der Geheimtext: "+s
#Ausgabe als Textdatei
else:
    f = file('C:\crypto.txt', 'w')
    f.write(s)
    f.close()
    print
    print "Die Textdatei befindet sich unter C:\crypto.txt"

#Beenden
print
raw_input('Zum Beenden "Enter" druecken')
Meine Frage dazu noch: Ist es möglich, dass ich das zu einer .exe oder so konvertiere, dass (ohne Python installiert zu haben) sich ein Fenster öffnet und man dass so wie in eine Konsole eingeben kann? Also etwa so wie die Installationsassistenten, die man z.B. mit NSIS erstellen kann?

Vielen Dank für Antworten!

Edit (Leonidas): Code-Highlighting aktiviert.
Edit(Klapperschlange): Danke, habs eben selber nachgeschaut, weil ich mich gewundert hatte, wieso das nicht geklappt hat
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Hallo Klapperschlange, willkommen im Forum,
Klapperschlange hat geschrieben:Meine Frage dazu noch: Ist es möglich, dass ich das zu einer .exe oder so konvertiere, dass (ohne Python installiert zu haben) sich ein Fenster öffnet und man dass so wie in eine Konsole eingeben kann? Also etwa so wie die Installationsassistenten, die man z.B. mit NSIS erstellen kann?
Ja, mit py2exe, PyInstaller, cx_Freeze. Siehe Suchfunktion.

Und das raw_input um die Konsole offen halten nervt. Als Linux-User ganz besonders. Lass es weg. Es funktioniert eh nicht so wie man es sich wünschen würde, bei Exceptions geht nämlich das Fenster ebenso zu und du siehst den Fehler gar nicht.

Ich habe es mir mal erlaubt das Programm in Grunde nachzuprogrammieren, denn diese Dicts sahen sehr seltsam aus. Da habe ich lieber etwas verwendet, was die Indizes automatisch ausrechnet:

Code: Alles auswählen

from string import ascii_lowercase

class Ring(list):
    def __getitem__(self, index):
        real_index = index % len(self)
        return list.__getitem__(self, real_index)

ring = Ring(ascii_lowercase)

move_each = int(raw_input('How many chars to rotate:'))
text = raw_input('Text: ')

encoded_text = list()
for char in text:
    new_index = ring.index(char) + move_each
    new_char = ring[new_index]
    encoded_text.append(new_char)

print ''.join(encoded_text)
Ich weiß nicht in wie weit man solche Hilfe in der Facharbeit verwenden darf (ich habe bisher keinen Bedarf gehabt für meine Facharbeit andere Leute zu befragen), aber wenn du fragen zu meinen Code hast, beantworte ich sie gerne. Der Code demonstriert IMHO auch ganz gut, wie praktisch es ist, von eingebauten Typen zu erben.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Nikolas
User
Beiträge: 102
Registriert: Dienstag 25. Dezember 2007, 22:53
Wohnort: Freiburg im Breisgau

py2exe oder py2app sollte das machen (hab ich mal gelesen).

Such doch mal nach ord und chr. Damit kannst du einfach umrechnen, ohne so eine Tabelle benutzen zu müssen.

Und anstatt a und b solltest du passende Namen benutzen.
z.B. printFile und importFile

dann könntest du so was schreiben:

Code: Alles auswählen

a= raw_input('Soll eine Textdatei importiert werden (j/n)?')
printfile = (a=="j") 
und später dann:

Code: Alles auswählen

if printfile: foobar()
Erwarte das Beste und sei auf das Schlimmste vorbereitet.
rafael
User
Beiträge: 189
Registriert: Mittwoch 26. Juli 2006, 16:13

Hallo,

schau dir mal die Standardfunktionen ``ord()`` und ``chr()`` an.

Außerdem kannst du das Dateilesen, das Ausgeben, etc. in Funktionen packen und die ``raw_input``s dann in eine ``main()``-Funktion packen.

Du musst auch noch ``try-except``-Blöcke um `x = int(raw_input('Um wieviele Stellen soll das Alphabet verschoben werden? '))` setzen. Wenn man nämlich "foo" eingeben würde, schlägt das Programm fehl.
Dann musst du auch in den anderen raw_inputs prüfen, ob die Eingabe "j" oder "n" ist.

Ich denke jedoch es ist für den User übersichtlicher nicht so viele raw_inputs zu durchlaufen, sondern mit Optionen das Programm aufzurufen, wie ein Unixprogramm. Also "python chiffre.py --output-file out.txt --input-file input.txt" oder so ähnlich. Schau dir dafür mal das ``getopt`` oder ``optparse``-Modul an.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Klapperschlange, aller Anfang ist schwer. Ich denke, du kannst dein Programm noch verbessern. Insbesondere besser aufteilen und sprechendere Namen benutzen ist mein Tipp. Boolsche Werte mit 1 und 0 zu repräsentieren finde ich so 70er-Jahre... auch das geht besser.

Deine beiden dict brauchst du nicht, denn du kannst mit Zeichen rechnen. Schau dir die Funktionen "ord" und "str" an. Schließlich kann man "List comprehensions" einsetzen - nicht gerade Stoff für Anfänger gebe ich zu - aber wenn man sie einmal verstanden hat, so viel bequemer...

Mein Vorschlag:

Code: Alles auswählen

# stelle all die Fragen, nutze sprechende Variablennamen
stellen = int(frage("..."))

ausgeben_in_textdatei = frage("...") == "j"

einlesen_in_textdatei = frage("...") == "j"

if einlesen_in_textdatei:
    eingabe = open(frage("...")).read()
else:
    eingabe = frage("...")
    
ausgabe = kodiere(stellen, eingabe)

if ausgeben_in_textdatei:
    datei = open(frage("..."), "w")
    datei.write(ausgabe)
    datei.close()
else:
    print ausgabe


# mache eine eigene Funktion, um leichter von raw_input auf was anderes 
# umstellen zu können, wenn nötig. Außerdem bin ich auf dem Deutschtripp.
def frage(prompt):
    return raw_input(prompt)
    
# mache aus dem eigenlichen Algorithmus auch eine Funktion, um die ganze
# häßliche Ein/Ausgabeverwaltung loszuwerden. So wird's wiederverwendbar
def kodiere(stellen, eingabe):
    alphabet = "abcdefghijklmnopqrstuvwxyz"
    erster_code = ord(alphabet[0])
    def rotiere(zeichen):
        if zeichen in alphabet:
            return chr((ord(zeichen) - erster_code + stellen) % len(alphabet) + erster_code)
        return zeichen
    return "".join(rotiere(zeichen) for zeichen in eingabe.lower())
Stefan
Benutzeravatar
Klapperschlange
User
Beiträge: 6
Registriert: Freitag 4. Januar 2008, 15:55
Kontaktdaten:

Erstmal danke für die zahlreichen Antworten - dass geht ja sehr schnell hier
Leonidas hat geschrieben:Ich weiß nicht in wie weit man solche Hilfe in der Facharbeit verwenden darf (ich habe bisher keinen Bedarf gehabt für meine Facharbeit andere Leute zu befragen), aber wenn du fragen zu meinen Code hast, beantworte ich sie gerne. Der Code demonstriert IMHO auch ganz gut, wie praktisch es ist, von eingebauten Typen zu erben.
Fragen zu meiner Facharbeit bzw. zu der Programmierung für diese habe ich in diesem Sinne, dass ich Hilfe beanspruchen möchte ja nicht. Ich hab jetzt Python kaum eine Woche auf dem PC, weil mein Lehrer ja die Idee hatte ich könnte auch "was Praktisches" (sprich Programmieren) in der Facharbeit machen. Vorher hab ich keine nennenswerten Programmiersprachen gekannt und sonst auch nur HTML und php und deshalb wollt ich mal was Neues machen - zumal ich Python sehr sympathisch fand. Naja und weil ich eben wissen wollte was man da noch so an Möglichkeiten hat hab ich meinen Code mal hier rein gestellt.

Und deswegen freue ich mich auch so über die nützlichen Tipps (vorallem, das als Funktionen zu defninieren und die Hinweise auf die vielen nützlichen Befehle und die ``try-except``-Blöcke) um das noch zu optimieren und für später, wenn ich andere Sachen programmiere.

Weil ich es auch erst so kurz habe verstehe ich Zeile 3-6 in deinem Code nur WAS du da machst, aber nicht so richtig WIESO es klappt. Liegt wahrscheinlich daran, dass ich nicht weiß was die ASCII-Zeichen durchnummeriert sind und was man mit so einer Gruppe alles anstellen kann; was ist denn "self" für ne Variable bzw. "index"? Wo nimmst du das her? Und was haben diese beiden Underscores vor und nach "getitem" zu bedeuten? Ich hab das schon öfters in Codes gesehen aber...

Naja ich werde meinen Code aber nicht so extrem abändern, obwohl das wesentlich besser aussieht, wenn es so kurz und benutzerfreundlich ist. Es soll ja immer noch meine Leistung sein und nicht irgendwo abgeschrieben; die Sache mit dem Dictionaries werd ich deshalb behalten, weils ja der Kern der Ganzen ist - warum sind die denn nicht so sinnvoll (außer, dass man nicht alle ASCII-Zeichen hat ?).
Aber ich denke wegen ein paar Schönheitskorrekturen werde ich ja wohl noch fragen dürfen... es geht ja um das mathematische Prinzip hinter den Verschüsselungen, wie bei Caesar, Vignère, RSA, ... (was ich evtl. auch noch umsetzten will).
Achja; und die boolschen Werte sind mir trotzalledem doch sympathisch :wink:
Vingdoloras
User
Beiträge: 53
Registriert: Sonntag 2. Dezember 2007, 18:25

self ist die Variable für den Selbstgezug, also wenn ich eine Klasse "Hallo" habe, in der
"self.irgendwas"
definiert wird, dann hat die instanz "Instanz" dieser Klasse ein Objekt
"Instanz.irgendwas"

Die Unterstriche beim getitem manipulieren die Klasse so, dass sie auf
"Instanz[index]"
wie gewünscht reagiert.
Es gibt viele Methoden mit Unterstrichen, so kann man zum Beispiel mit
"def __add__(self, other)"
definieren, wie eine Instanz auf Addition reagiert.
rafael
User
Beiträge: 189
Registriert: Mittwoch 26. Juli 2006, 16:13

Schau dir dazu am besten mal die Kapitel zur Objektorientierung in einem Tutorial wie A Byte Of Python oder Wie ein Informatiker denken lernen an.
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

viel interessanter ist doch das entschlüsseln ;)
[url=http://29a.ch/]My Website - 29a.ch[/url]
"If privacy is outlawed, only outlaws will have privacy." - Phil Zimmermann
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Natürlich ist mir klar, dass du hier dein Programm vorstellen wolltest - ich will dir auch gar nichts böses unterstellen, keine Sorge. Den Austausch von Tipps befürworte ich natürlich :)
Klapperschlange hat geschrieben:Weil ich es auch erst so kurz habe verstehe ich Zeile 3-6 in deinem Code nur WAS du da machst, aber nicht so richtig WIESO es klappt. Liegt wahrscheinlich daran, dass ich nicht weiß was die ASCII-Zeichen durchnummeriert sind und was man mit so einer Gruppe alles anstellen kann; was ist denn "self" für ne Variable bzw. "index"? Wo nimmst du das her? Und was haben diese beiden Underscores vor und nach "getitem" zu bedeuten? Ich hab das schon öfters in Codes gesehen aber...
Gut, dann führe ich das mal aus:
Ich erstelle eine Klasse Ring (mangels eines besseren Namens - es ist auf jeden Fall ein Ringspeicher), die von ``list`` erbt. ``list`` ist der eingebaute Listen-Datentyp und ich wollte dass sich mein neuer Datentyp wie eine Liste verhält. Also erbe ich davon und kann nun dort eine Methode überschreiben, namentlich ``__getitem__``.

Was macht nun ``__getitem__``? Das ist eine spezielle Methode, die bei Indexzugriffen aufgerufen wird. Wenn du ein ``r = Ring('abc')`` hast, dann kannst du auf das 'a' mit ``r[0]`` zugreifen. Dabei wird eigentlich ``Ring.__getitem__(r, 0)`` aufgerufen, welches nun hoffentlich den richtigen Wert zurückgibt.

Genau das mache ich mir zu nutze. Ich überschreibe die Methode mit meiner eigenen, die Index Modulo Länge rechnet. Damit kann ich erreichen, dass in dem Beispiel von oben 3 % 3 = 0 und 4 % 3 = 1, also kann ich den gewünschten Index-Wert auf einen in der Liste vorhandenen Index-Wert runterrechnen. Dadurch kann ich auf ``r[3]`` zugreifen und bekomme 'a', etc. Ich habe somit einen Speicher der einen Wraparound hat (in Prozessor-Slang) bzw. einen Speicher der Degeneriert ist (in DNA-Slang). Wie auch immer, ich habe auf jeden Fall einen Speicher, wo ich jedes Element um jeden beliebigen Wert verschieben kann.

Naja, der Rest ist dann einfach, ich hole mir die Bereits definierten Buchstabenfolgen aus dem ``string`` Modul und zähle dann immer den Schlüssel (also 13 oder was auch immer) dazu.

Und irgendwie implementiere ich diese Art von Code jedes Jahr neu, weil ich meine Lösungen vom letzten Jahr irgendwo verliere :)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Nikolas
User
Beiträge: 102
Registriert: Dienstag 25. Dezember 2007, 22:53
Wohnort: Freiburg im Breisgau

@veers: Caesar ist da noch recht langweilig. Interessant ist die Erweiterung von Caesar zu Vegenère und das angepasste Entschlüsselungsverfahren. Wenn da der Schlüssel nicht allzu lang ist im Vergleich zum Text, geht das ganz gut.
Erwarte das Beste und sei auf das Schlimmste vorbereitet.
Redprince
User
Beiträge: 128
Registriert: Freitag 22. Oktober 2004, 09:22
Wohnort: Salzgitter
Kontaktdaten:

Nikolas hat geschrieben:Caesar ist da noch recht langweilig. Interessant ist die Erweiterung von Caesar zu Vegenère und das angepasste Entschlüsselungsverfahren.
Also so spannend sind die klassischen Kryptologieverfahren nun auch nicht ;) Wobei es bei modernen natürlich mit der Kryptoanalyse schwieriger wird..
I am not part of the allesburner. I am the [url=http://allesburner.de]allesburner[/url].
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Redprince hat geschrieben:Wobei es bei modernen natürlich mit der Kryptoanalyse schwieriger wird..
Und, was für die meisten auch wichtig ist: die Implementation ist schwieriger ;)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Klapperschlange
User
Beiträge: 6
Registriert: Freitag 4. Januar 2008, 15:55
Kontaktdaten:

veers hat geschrieben:viel interessanter ist doch das entschlüsseln ;)
Naja bei so einem normalen Caesar reicht Häufigkeitsanalyse (bei einigermaßen langen Nachrichten) aus. Interessanter wirds bei anderen Sachen; die "modernen" Verfahren wie RSA find ich von der Dechiffrierung eher uninteressant...

Aber danke für die Erläuterung der Funktionsweise des "Erbens" - gibts das nur bei Python oder auch in anderen Programmiersprachen? Weil das ist mal eine nützliche Sache.

Und "A Byte Of Python" hab ich auch schon angefangen, aber bin noch nicht so weit gekommen. Ich finde das schon gut gemacht nur meiner Meinung nach könnten da ein paar mehr weiterführende Beispiele sein um die vielen Möglichkeiten der einzelnen Befehle/Funktionen zu zeigen.
Benutzeravatar
Hobbes Hobson
User
Beiträge: 42
Registriert: Sonntag 9. Dezember 2007, 15:24
Wohnort: Bremen

Hast du schon Programmiererfahrung?

Wenn nein, dann hat dich das Erben im Moment noch nicht zu interessieren. Denn nach 1 Woche Python ist das etwas viel verlant.

Arbeite mal das Buch durch und steck das erstmal in definitionen und später dann in eine Klasse.

Und irgendwann bist du dann soweit, dass du das wie Leonidas löst.

Meine Meinung dazu :P
Benutzeravatar
Klapperschlange
User
Beiträge: 6
Registriert: Freitag 4. Januar 2008, 15:55
Kontaktdaten:

Ja für die Facharbeit mach ichs auch auf jeden Fall so wie ich mir das zuerst gedacht habe und wie gut ich das hinbekomme; hab jetzt nur noch die "try...expect"-Blöcke eingebaut und ein bisschen was an den Namen geändert.

Und trotz noch wenig Programmiererfahrung ist doch gut im Hinterkopf zu behalten, dass Python sowas kann - irgendwann brauchts man ja bestimmt :wink:
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Klapperschlange hat geschrieben:Aber danke für die Erläuterung der Funktionsweise des "Erbens" - gibts das nur bei Python oder auch in anderen Programmiersprachen? Weil das ist mal eine nützliche Sache.
Ja, gibt es. Das ist eben Objektorientierte Programmierung, aber - und nun kommt das obligatorische aber - das kann von Programmiersprache zu Programmiersprache ganz unterschiedlich gelöst sein.

In Python kann man erst seit 2.2(.1?) von eingebauten Objekten wie ``file``, ``list``, ``dict`` etc. erben. In anderen Sprachen geht das zum Beispiel gar nicht, in noch anderen Sprachen sind noch tiefschürfendere Dinge erlaubt. OOP ist eigentlich ein Konzept, nicht eine Implementierung. Vielen Leuten wird beigebracht, dass Java das "richtige OOP" ist. Um es kurz zu fassen: Javas OOP ist nur eines der Möglichen Arten von OOP, Python und Ruby sind viel näher am "original OOP" von Smalltalk dran (du darfst gerne einige Begriffe in Wikipedia eintippen, wenn sie dich interessieren). Dass OOP ein Konzept ist und keine Implementierung zeigt wohl CLOS oder Gobject ganz gut, die OOP für Common Lisp bzw. C bieten.

Und natürlich, es ist oft auch wert, einen Blick über den Tellerrand zu riskieren, viele Programmiersprachen bieten interessante Möglichkeiten ein Problem zu lösen. Wobei man aber auch zugeben muss, dass nicht alle Programmiersprachen sich zur Lösung eines Problems auch eignen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Klapperschlange
User
Beiträge: 6
Registriert: Freitag 4. Januar 2008, 15:55
Kontaktdaten:

Du kannst auch Ruby? Davon hab ich auch viel Gutes gehört - soll mit realtiv wenig Befehlen viel machen können. Aber erstmal werd ich mal versuchen in Python einzusteigen.

Ist zwar vielleicht eine doofe Frage in einem python-Forum aber ist python eine Alternative zu C bzw. C++ ? Bzw. auf welchen Gebieten liegen die Vor-/Nachteile?

Wird so langsam Offtopic aber...
Andy
User
Beiträge: 196
Registriert: Sonntag 1. Januar 2006, 20:12
Wohnort: aus dem hohen Norden....

Klapperschlange hat geschrieben:Ist zwar vielleicht eine doofe Frage in einem python-Forum aber ist python eine Alternative zu C bzw. C++ ? Bzw. auf welchen Gebieten liegen die Vor-/Nachteile?

Wird so langsam Offtopic aber...
Nein, ist keine doofe Frage, in einem Programmier-Forum! :wink:

Schau mal hier: www.Programmiersprachen besprechen wir gelegentlich öfter in unserem schönen Python-Forum, man muss nur mal die Suchfunktion benutzen.de
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Klapperschlange hat geschrieben:Du kannst auch Ruby? Davon hab ich auch viel Gutes gehört - soll mit realtiv wenig Befehlen viel machen können. Aber erstmal werd ich mal versuchen in Python einzusteigen.
Was heißt können. Nutzen können, kann ichs, ja. Ist letztendlich von der Syntax her recht ähnlich, nur unübersichtlicher.

Ob ich damit auch richtig gute Programme schreiben kann, die ideomatisches Ruby sind: eher nicht. Den Bedarf habe ich schlicht nicht - ich bevorzuge Python, auch wenn Ruby einige coole (und weniger coole) Features hat.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten