Kryptographie Sonderzeichenfehler

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
Kamik423
User
Beiträge: 93
Registriert: Donnerstag 28. März 2013, 16:53

Ich versuche ein Kryptographieprogramm zu schreiben

coding.py

Code: Alles auswählen

# -*- coding: cp1252 -*-

letters = [' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~']

def encode(pw,code):
             #pw = passwort
    code2 = []
    for i in code:
        code2.append(letters.index(i))
    code3 = ""
    ap = 0
    apo = 0
    px = 0
    for i in code2:
        ap = i+int(str(pw)[px])+apo
        while ap<0:
            ap += 95
        while ap > 94:
            ap -= 95
        px += 1
        if px == len(str(pw)):
            px = 0
        code3+=str(ap)
        print int(i), apo, int(str(pw)[px]), ap
        apo = i
    print " "
    return code3

def decode(pw,code):
    code2 = []
    for i in range(0, int(len(code)/2)):
        j = 2*i
        code2.append(code[j]+code[j+1])
    ap = 0
    apo = 0
    px = 0
    code3 = ""
    for k in code2:
        ap = int(k)-apo-int(str(pw)[px])
        while ap<0:
            ap += 95
        while ap > 94:
            ap -= 95
        px += 1
        if px == len(str(pw)):
            px = 0
        print ap, apo, int(str(pw)[px]), int(k)
        apo=ap
        code3+=letters[ap]
    return code3
und

start.py

Code: Alles auswählen

import coding
# -*- coding: cp1252 -*-
variable = raw_input()
print coding.decode(123,coding.encode(123,variable))
bei sonderzeichen (Auch leerzeichen) beginnt er zu spinnen und so den gesamten weiteren Text falsch zu übersetzen muss ich die ganzen Sonderzeichen entfernen, denn ich möchte damit größere Texte verschlüsseln, auch mit Leerzeichen :(

(die Printbefehle sind zur übersicht, sie sollten Identisch sein vor und hinter dem Leerzeichen, sind sie aber nur bis zu einer bestimmten Stelle)
0x4c65742773206d616b652073757265207468617420686973746f7279206e6576657220666f726765747320746865206e616d6520656e746572707269736521
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Kamik423 hat geschrieben:Ich versuche ein Kryptographieprogramm zu schreiben
Mir scheint Dein Code schon recht kryptisch zu sein... :wink:
Kamik423 hat geschrieben:... beginnt er zu spinnen ...
Ich denke mal, mit "spinnen" meinst Du den ValueError, der natürlich bei einem Sonderzeichen, das nicht in `letters` enthalten ist, geworfen wird? Allein dieser ValueError sollte Dir zu denken geben...

mutetella

P.S.: Im übrigen sind die Namen in Deinem Code katastrophürchterlich... Das macht es jedem, der das alles verstehen soll, unnütz schwer. Und ich glaube, in ein paar Wochen weißt Du selbst nicht mehr, was mit `ap`, `apo` und dergleichen gemeint ist...
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wenn du eh alle möglichen Zeichen verschlüsseln möchtest, dann ist es sinnlos die Zeichen aufzuzählen. Am einfachsten ist es, wenn du dich für ein Encoding der Strings entscheidest (zum Beispiel UTF-8) und dann auf den Bytes deine Verschlüsselung anwendest.
Das Leben ist wie ein Tennisball.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Um das, was EyDu geschrieben hat, zu konkretisieren:
(Python 2/UTF-8)

Code: Alles auswählen

>>> for byte in 'ä'.decode('utf8'):
...     print ord(byte)
... 
228
>>> for byte in 'a'.decode('utf8'):
...     print ord(byte)
... 
97
(Python 3/UTF-8)

Code: Alles auswählen

>>> for byte in 'ä':
...     print(ord(byte))
... 
228
Damit hast Du ein unicode byte, das Du codierst und nach dem decodieren mit einem entsprechenden encoding wieder in das passende Zeichen übersetzt.

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Ein „unicode byte” ist eine interessante Formulierung. Das würde ich ja eher als Codepoint bezeichnen. Denn auch wenn Byte grundsätzlich keine Bitanzahl impliziert, kann man bei den Rechnern wo Python üblicherweise läuft schon 8 Bit annehmen, und bei Deinem Beispiel können durchaus grössere Zahlen als 255 vorkommen wenn man mal 'Latin 1' verlässt. Zum Verschlüsseln würde man eher den umkehrten Weg nehmen und (Unicode-)Zeichenketten in Bytes umwandeln und die dann ver-/entschlüsseln. Denn wenn man eine Verschlüsselung für Bytes schreibt, kann man alle Arten von Daten verarbeiten und nicht nur Zeichen.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@BlackJack:
Ok, das leuchtet mir ein. Ich war jetzt lediglich auf darstellbare Zeichen fixiert. Und die sind, zumindest da wo ich wohne, bis 255 abgedeckt.
Ausgehend von einem UTF8 codierten 'ä' würdest Du also [195, 164] codieren? Und wie ließen sich denn "alle Arten von Daten" verarbeiten? Ich denke da jetzt z. B. an eine jpeg-Datei. Wie würde ich die in Python einlesen?

mutetella

EDIT:

Code: Alles auswählen

>>> for i in '€'.decode('utf8'):
...     print ord(i)
... 
8364
Ok, das mit 255 war dann wohl auch Quatsch... :oops:
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Die Daten würde man einfach im Binärmodus aus der Datei lesen. Bei Python 2 hätte man (Byte)Strings und bei Python 3 den Typ `bytes`. In beiden Fällen sind die Werte der einzelnen Elemente dann tatsächlich zwischen 0 und 255. Bei Python 2 müsste man noch die `ord()`-Funktion bemühen, bei Python 3 reicht der Indexzugriff beziehungsweise iterieren über die Daten.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

mutetella hat geschrieben:EDIT:

Code: Alles auswählen

>>> for i in '€'.decode('utf8'):
...     print ord(i)
... 
8364
Ok, das mit 255 war dann wohl auch Quatsch... :oops:
Das ist ja auch kein UTF-8 kodierter String was du da rausbekommst sondern ein Unicode-String mit einem Zeichen unter dem Codepoint 0x20ac, namens 'EURO SIGN' (``unicodedata.name(u'\u20ac')``). Der Dezimalwert von 0x20ac ist entsprechend 8364. Womit du jetzt auch rausgefunden hättest was ``ord()`` auf Unicode-Strings macht :)

Was du demonstrieren willst ist die andere Richtung:

Code: Alles auswählen

>>> for byte in u'\u20ac'.encode('utf-8'):
...  print ord(byte)
... 
226
130
172
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

@Kamik423:Dein Code ist gelinde gesagt schwer lesbar. Wieso verwendest du nicht gleich den Modulo Operator für das was du mit dem Passwort(pw, px) veranstaltest?
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

darktrym hat geschrieben:Dein Code ist gelinde gesagt schwer lesbar.
Es handelt sich offensichtlich um »security by obscurity«: ;-)

Code: Alles auswählen

from itertools import cycle
letters = [chr(i) for i in range(32,127)]

def encode(pw,code):  #pw = passwort
    passw = cycle(int(i) for i in str(pw))
    result = ""
    apo = 0
    for ch in code:
        i = letters.index(ch)
        ap = (i+next(passw)+apo) % len(letters)
        result+=letters[ap]
        apo = i
    return result

def decode(pw,code):
    passw = cycle(int(i) for i in str(pw))
    result = ""
    apo = 0
    for ch in code:
        i = letters.index(ch)
        ap = (i-next(passw)-apo) % len(letters)
        result+=letters[ap]
        apo=ap
    return result
Es handelt sich offensichtlich um eine Blockchiffre mit einer Blocklänge von 1 Zeichen.
Für jeden Block werden 3.3Bit des Passworts benutzt, das sich nach n=password_length/3.3 Blöcken wiederholt. Zusätzlich gibt es noch Klartext-Block-Chaining, dass falls der Mitleser Teile verpasst, diese auch wieder rekonstruieren kann.
Kamik423
User
Beiträge: 93
Registriert: Donnerstag 28. März 2013, 16:53

Erstmal danke für die vielen Antworten :D
der Verrechnungsmechanusmus ist mir erstmal egal, und ich weiß, dass mein Code schwer zu lesen ist.

mir ging es erstmal darum, einen String mit sonderzeichen in eine Zahlenfolge umzuwandeln, was ich da mit einer Liste gelöst habe. Ich bin immer iffen für bessere Angebote. Ich habe übrigens die Fehlerquelle gefunden: Ich nehme für jeden Buchstaben beim decodieren 2 Zahlenstellen (00-94) an, aber zahlen unter zehn sind z.b. 5 statt 05 was sich auf das teilen dann ausübt.


nochmal danke, Kamik423
0x4c65742773206d616b652073757265207468617420686973746f7279206e6576657220666f726765747320746865206e616d6520656e746572707269736521
Antworten