Dookie's crypt() und decrypt()

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
genrich
User
Beiträge: 91
Registriert: Sonntag 27. Juni 2004, 17:46

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.....
genrich
User
Beiträge: 91
Registriert: Sonntag 27. Juni 2004, 17:46

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:
genrich
User
Beiträge: 91
Registriert: Sonntag 27. Juni 2004, 17:46

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/
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi genrich,

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


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
genrich
User
Beiträge: 91
Registriert: Sonntag 27. Juni 2004, 17:46

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'
:(
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Du musst als schlüssel eine Zahl eingeben!


Dookie
[code]#!/usr/bin/env python
import this[/code]
genrich
User
Beiträge: 91
Registriert: Sonntag 27. Juni 2004, 17:46

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
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Man könnte die Blöcke einmal berechnen und in einer Datei speichern.


Dookie
[code]#!/usr/bin/env python
import this[/code]
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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...
Antworten