Seite 1 von 1

Dookie's crypt() und decrypt()

Verfasst: Freitag 13. August 2004, 09:43
von genrich
Hallo zusammen...

Hier hat Dookie sein crypt() und decrypt() gepostet:
http://python.sandtner.org/viewtopic.php?p=7127#7127

Ich hatte mir eigentlich eine eigene Variante daraus gestrickt:

Code: Alles auswählen

from random import Random


def encrypt(txt,Pass):
    rnd=Random(Pass).randint(0,127)

    return "".join([chr(ord(a) ^ rnd) for a in txt])


def decrypt(txt,Pass):
    rnd=Random(Pass).randint(0,127)

    return "".join([chr(ord(a) ^ rnd) for a in txt])

Ich wollte es in erster Linie vereinfachen...
Nun ist mir zum Glück etwas Aufgefallen!
Hier mal ein Test:

Code: Alles auswählen

crypted=encrypt("Test1","EinTollesPasswort")
print "crypted:",crypted
decrypted=decrypt(crypted,"EinTollesPasswort")
print "decrypted:",decrypted

print "-"*30

crypted=encrypt("Test2","098f6bcd4621d373cade4e832627b4f6")
print "crypted:",crypted
decrypted=decrypt(crypted,"098f6bcd4621d373cade4e832627b4f6")
print "decrypted:",decrypted
Die Ausgabe:

Code: Alles auswählen

crypted: kZLK[SO]
decrypted: Test1
------------------------------
crypted: Test2
decrypted: Test2
( "[SO]" ist ein Sonderzeichen)


Wie man sieht ist der "Test2" nicht wirklich verschlüßelt... Nun hab ich hin und her überlegt, warum das der Fall ist....

Die Lösung ist, das
Random("098f6bcd4621d373cade4e832627b4f6").randint(0,127)
"zufällig" 0 ergibt!
Wenn damit verschlüsselt wird, dann passiert nix...

Im Original-Skript von Dookie hatte er ja den Random anders gestartet:
sum([ord(a) for a in Pass])

Das hatte ich weg gelassen, weil ich mir dache, wozu so kompliziert...

Jetzt könnte man überlegen, wie man es hinbekommt, das der Random nie mit einer 0 gestartet wird...
Dazu gibt es mehrere Möglichkeiten... Die einfachste ist es nicht .randint(0,127) sondern .randint(1,127) zu verwenden...


Jetzt fällt mir allerdings auf, das durch .randint(0,127) die maximale Variation festgelegt ist! Also egal welches Passwort man benutzt es kann sich nur 128 verschiedene Verschlüsselungen ergeben :!:

Das ist natürlich super einfach mit einem zu knacken:

Code: Alles auswählen

def BruteForce(txt):
    for rnd in range(127):
        decrypted="".join([chr(ord(a) ^ rnd) for a in txt])
        if decrypted=="EinLangerTestText":
            return decrypted

print BruteForce("zVQs^QXZMkZLKkZGK")

Hmmmm.....

Verfasst: Freitag 13. August 2004, 10:14
von genrich
Mir fällt da gerade eine Lösung ein.
Vom Passwort machen wir erstmal einen 32-Zeichen langes MD5 von.
Mit dem MD5-Fingerprint wird bei jedem Zeichen von "txt" ein neuer "Zufallswert" gesetzt. Somit wird jedes Zeichen einzeln "verschlüsselt"...

Damit dürfte man mehr als 128 kombinationen erhalten :)
Genau genommen dürfte es vom MD5 abhängen... Damit sind wohl 2^128 verschiedene Möglichkeiten drin, oder?

Code: Alles auswählen

    def crypten(txt,Pass):
        Seed=md5.new(Pass).hexdigest()

        maxSeedLen=len(Seed)
        crypted=""
        i=0
        for a in txt:
            if i>=maxSeedLen: i=0

            rnd=Random(Seed[i]).randint(0,127)
            crypted+=chr(ord(a) ^ rnd)
            i+=1

        return crypted
Im übrigen ist mir aufgefallen das encrypt() und decrypt() genau gleich sind :)
Somit reicht ja auch eine der beiden zum ver- und entschlüsseln :wink:

Verfasst: Samstag 14. August 2004, 13:39
von genrich
Hab per Zufall eine RSA-Verschlüßelungsverfahren in Python gefunden:
http://ftp.kantisargans.ch/lehrerweb/th ... torium.pdf

Hier die Quellentexte aus dem PDF von Thomas Grischott:

Code: Alles auswählen

# rsaverschluesseln.py
print "RSA-Verschluesselung"
print "--------------------"
alphabet = " abcdefghijklmnopqrstuvwxyz"
klartextbloecke = [i+j for i in alphabet for j in alphabet]
geheimtextbloecke = [i+j+k for i in alphabet for j in alphabet\
                    for k in alphabet]
                    
klartext = raw_input("Klartext eingeben: ")
klartext = klartext.lower()
while len(klartext)%2:
    klartext += " "
modul = input("Modul n eingeben (729 <= n <= 19683): ")
schluessel = input("Schluessel e eingeben: ")

geheimtext = ""
for b in range(len(klartext)/2):
    block = klartext[2*b:2*b+2]
    nummer = klartextbloecke.index(block)
    nummer **= schluessel
    nummer %= modul
    geheimtext += geheimtextbloecke[nummer]

print "Geheimtext:", geheimtext.upper()

Code: Alles auswählen

# rsaentschluesseln.py
print "RSA-Entschluesselung"
print "--------------------"
alphabet = " ABCDEFGHIJKLMNOPQRSTUVWXYZ"
klartextbloecke = [i+j for i in alphabet for j in alphabet]
geheimtextbloecke = [i+j+k for i in alphabet for j in alphabet\
                    for k in alphabet]
                    
geheimtext = raw_input("Geheimtext eingeben: ")
geheimtext = geheimtext.upper()
while len(geheimtext)%3:
    geheimtext += " "
modul = input("Modul n eingeben (729 <= n <= 19683): ")
schluessel = input("Schluessel d eingeben: ")

klartext = ""
for b in range(len(geheimtext)/3):
    block = geheimtext[3*b:3*b+3]
    nummer = geheimtextbloecke.index(block)
    nummer **= schluessel
    nummer %= modul
    klartext += klartextbloecke[nummer]

print "Klartext:", klartext.lower()
Noch Interressante Links:
http://www.amk.ca/python/code/crypto.html
http://www.freenet.org.nz/ezPyCrypto/

Verfasst: Samstag 14. August 2004, 16:16
von Dookie
Hi genrich,

ich hab da noch eine Buchempfehlung zum Thema Verschlüsselung:
Geheime Botschaften von Simon Singh.


Gruß

Dookie

Verfasst: Montag 16. August 2004, 16:54
von genrich
genrich hat geschrieben:Hab per Zufall eine RSA-Verschlüßelungsverfahren in Python gefunden:
Funktioniert leider nicht.
Ich bekomme nur die Fehlermeldung:

Code: Alles auswählen

    nummer **= schluessel
TypeError: unsupported operand type(s) for ** or pow(): 'int' and 'str'
:(

Verfasst: Montag 16. August 2004, 17:49
von Dookie
Du musst als schlüssel eine Zahl eingeben!


Dookie

Verfasst: Montag 16. August 2004, 18:09
von genrich
Dookie hat geschrieben:Du musst als schlüssel eine Zahl eingeben!
Ja, da hast du recht... Aber es ist wohl nur eine ganz, ganz einfache implementation des RSA...

Es werden zu je zwei Buchstaben Blöcke gebildet, die dann durcheinander gewürfelt werden...


Theoretisch könnte man damit schon weiterarbeiten und was draus machen... Allerdings ist der ziemlich rechenaufwendig.
Gerade wenn man das Alphabet vergrößert, dauert es eine weile. Am meisten nimmt wohl die Vorbereitungen in Anspruch:

Code: Alles auswählen

klartextbloecke = [i+j for i in alphabet for j in alphabet]
geheimtextbloecke = [i+j+k for i in alphabet for j in alphabet\
                    for k in alphabet]
Könnte man da was schneller machen???


Da wir aber schonmal dabei sind:
http://rs.box.sk/source/py/rsa.py

Verfasst: Montag 16. August 2004, 18:43
von Dookie
Man könnte die Blöcke einmal berechnen und in einer Datei speichern.


Dookie

Verfasst: Dienstag 17. August 2004, 07:38
von jens
Ich benutze die letzte Version von Genrichs encrypt/decrypt... Doch jetzt ist mir leider Aufgefallen, das Random in v2.3 geändert wurde :(
Changed in version 2.3: Substituted MersenneTwister for Wichmann-Hill.

Leider benutze ich lokal die v2.3 aber auf dem Server ist die alte v2.2.1 :?
Das bedeutet, das ich lokal encryptete Daten, auf den Server nicht decrypten kann :(
Denn:

Code: Alles auswählen

rnd=Random(Seed[i]).randint(0,127)
liefert andere Zufallswerte...