Playfair Verschlüsselung

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
Erichmo
User
Beiträge: 13
Registriert: Donnerstag 1. August 2019, 16:28

Hallo zusammen,

ich bin immernoch dabei eine playfair Verschlüsselung zu programmieren.
Mein Problem ist, dass ich keine Möglichkeit finde alle 3 möglichen Fälle für die Verschlüssselung nacheinander zu durchlaufen und erst dann die Variablen zu erhöhen. (siehe Unterprogramm)

Bitte nehmt keine Rücksicht auf die Textformatierung, diese läuft noch nicht einwandfrei, was aber nicht mein Hauptproblem ist

Schonmal vielen vielen Dank,
Erichmo



Code: Alles auswählen

from string import ascii_uppercase as asc

#input("Ihr Schlüsselwort: ") #Schlüsselwort Eingabe

#text = input("Ihr Text: ") #Text Eingabe

#############################################################

text = "hacd kommtt der Klaartext!"

key = "Hallo"

text2 = text.replace(" ","") #Leerzeichen entfernen

text3 = text2.upper() #Text groß schreiben

"""for i in text3: #Alle Sonderzeichen filtern
    if i in text3 not in asc:
       text4 = text3.replace(i,"")"""
       
       
if len(text3) % 2:
    text5 = text3 + "X"
else:
    text5 = text3


t = ()

key_ABC = []

key1 = lambda x: x.upper().replace("J","I")

#Doppelbuchstaben durch X ersetzen -- Fehlerhaft (ersetzt beide Buchstaben durch X)


f=0
g=1

while True:
    
    if text5[f] == text5[g]:
        text6 = text5[:g] + "X" + text5[g+1:]
        text5 = text6
        f = 0
        g = 1
    else:
        f = f + 1
        g = g + 1
        if g == len(text5):
            break
        
#Kontrollliste erstellen und ausgeben
x = len(text5)
h = 2
e = 2
b = 0
Liste = list()

while h < x + 1 :
    
    if h < x + 1:
        text7 = (text6[b:e])
        Liste.append(text7)
        h =  h + 2
        e = e + 2
        b = b + 2

print (Liste)
#Buchstabenfolge für Matrix generieren

for i in key1(key + asc):
    if i not in key_ABC and i in asc:
        
        key_ABC.append(i)
        

#Matrix erzeugen        
        
Matrix = [key_ABC[i:i+5] for i in range(0, len(key_ABC),5)] 


print("\n___________\n",*Matrix[0],"\n",*Matrix[1],"\n",*Matrix[2],"\n",*Matrix[3],#Matrix formatiert asugeben
      "\n",*Matrix[4],"\n___________")

#Veschlüsseln wenn beide Buchstaben in einer Zeile liegen

T_Matrix = []
for i in zip(*Matrix):
    T_Matrix.append((list(i)))

final = list()
e = 1
d = 0
def Verschlüsseln():
    a = 0
    r = 0
    t = 0
    z = 0
    o = 0
    end = 0
    d = 0
    e = 1
    final = list()
    while True: 
    #beide Buchstaben in einer Zeile    
        if text5[d] in Matrix[a] and text5[e] in Matrix[a] and e <= len(text5):
            b = Matrix[a].index(text5[d])+1
            c = Matrix[a].index(text5[e])+1
            if c == 5:
                c = 0
            if b == 5:
                b = 0    
            if b != c and text5[d] in Matrix[a] and text5[e] in Matrix[a]:
                print (text5[d],text5[e],"-->",Matrix[a][b],Matrix[a][c])
                final.append(Matrix[a][b])
                final.append(Matrix[a][c])
                d = d + 2
                e = e + 2
                a = 0
                end = end + 2
            if c == b:
               a = a + 1
               if a > 4:
                   a= 0
        else:
           a = a + 1
           if a > 4:
               a = 0
               if text5[d] in T_Matrix[a] and text5[e] in T_Matrix[a] and e <= len(text5):
                    b = T_Matrix[a].index(text5[d])+1
                    c = T_Matrix[a].index(text5[e])+1
                    if c == 5:
                        c = 0
                    if b == 5:
                        b = 0    
                    if b != c and text5[d] in T_Matrix[a] and text5[e] in T_Matrix[a]:
                        print (text5[d],text5[e],"-->",T_Matrix[a][b],T_Matrix[a][c])
                        final.append(T_Matrix[a][b])
                        final.append(T_Matrix[a][c])
                        d = d + 2
                        e = e + 2
                        a = 0
                        end = end + 2
                        
                    if c == b:
                       a = a + 1
                       if a > 4:
                           a= 0
               else:
                   a = a + 1
                   if a > 4:
                       if text5[d] in Matrix[r][t]:
                            if text5[e] in Matrix[z][o] and o != t and r != z:
                                if t < o:
                                    enc1 = o
                                    enc2 = t
                                    print(text5[d],text5[e],"-->",Matrix[r][enc1],Matrix[z][enc2])
                                    final.append(Matrix[r][enc1] + Matrix[z][enc2])
                                    end = end + 2
                                    d = d + 2
                                    e = e + 2
                                    if e > len(text5) - 1:
                                        break
                                if t > o:
                                    enc1 = o
                                    enc2 = t
                                    print(text5[d],text5[e],"-->",Matrix[r][enc1],Matrix[z][enc2])
                                    final.append(Matrix[r][enc1] + Matrix[z][enc2])
                                    end = end + 2
                                    d = d + 2
                                    e = e + 2
                                    if e > len(text5) - 1:
                                        break
                            else:
                                o = o + 1
                                if o > 4:
                                    o = 0
                                    z = z + 1
                                    if z > 4:
                                        o = 0
                                        z = 0
                   else:
                            t = t + 1
                            if t > 4:
                                t = 0
                                r = r + 1
                                if r > 4:
                                    t = 0
                                    r = 0
                                    
                        
        if end == len(text5) - 1 or e > len(text5) - 1:
            break

Verschlüsseln()
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Erichmo: Programmieren ist in der Regel ein Problem in kleinere Teilprobleme zu zerlegen, und die dann wieder in kleinere Teilprobleme, solange bis die einzelnen Teilprobleme so klein sind, das man sie mit einer Funktion mit ein paar Zeilen Code lösen kann. So eine Teillösung testet man dann, und wenn sie funktioniert, macht man sich an die nächste Funktion die ein Teilproblem löst. Solange bis man eine Gesamtlösung hat.

Ein Teilproblem ist beispielsweise das vorbereiten des Eingabetextes und zerlegen in Buchstabenpaare, inklusive einfügen von Xen. Ein weiteres ist das erstellen des Quadrats. Dann wäre ein Teilproblem *ein* Buchstabenpaar zu verschlüsseln. Wenn man das gelöst hat, ist es trivial alle zu verschlüsseln, denn dafür braucht man die Funktion zum Verschlüsseln *eines* Buchstabenpaars nur noch in einer Schleife aufrufen (oder mit `map()` auf die Paare anwenden).

Eine Unterfunktion könnte auch sein die Koordinaten zu einem Buchstaben zu finden.

Edit: Und was das Testen der ganzen Funktionen angeht, schreibt man sich am besten Code der das macht, so dass man die Tests immer wiederholen kann, um auch bei Änderungen am Programm automatisch testen zu können, ob alles was mal funktioniert hat, immer noch funktioniert. `pytest` ist dafür IMHO recht empfehlenswert.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Erichmo
User
Beiträge: 13
Registriert: Donnerstag 1. August 2019, 16:28

__blackjack__ hat geschrieben: Dienstag 6. August 2019, 17:02 @Erichmo: Programmieren ist in der Regel ein Problem in kleinere Teilprobleme zu zerlegen, und die dann wieder in kleinere Teilprobleme, solange bis die einzelnen Teilprobleme so klein sind, das man sie mit einer Funktion mit ein paar Zeilen Code lösen kann. So eine Teillösung testet man dann, und wenn sie funktioniert, macht man sich an die nächste Funktion die ein Teilproblem löst. Solange bis man eine Gesamtlösung hat.

Ein Teilproblem ist beispielsweise das vorbereiten des Eingabetextes und zerlegen in Buchstabenpaare, inklusive einfügen von Xen. Ein weiteres ist das erstellen des Quadrats. Dann wäre ein Teilproblem *ein* Buchstabenpaar zu verschlüsseln. Wenn man das gelöst hat, ist es trivial alle zu verschlüsseln, denn dafür braucht man die Funktion zum Verschlüsseln *eines* Buchstabenpaars nur noch in einer Schleife aufrufen (oder mit `map()` auf die Paare anwenden).

Eine Unterfunktion könnte auch sein die Koordinaten zu einem Buchstaben zu finden.

Edit: Und was das Testen der ganzen Funktionen angeht, schreibt man sich am besten Code der das macht, so dass man die Tests immer wiederholen kann, um auch bei Änderungen am Programm automatisch testen zu können, ob alles was mal funktioniert hat, immer noch funktioniert. `pytest` ist dafür IMHO recht empfehlenswert.

Vielen Dank für deine Antwort.

Ich habe schon mehrfach noch einer Funktion gesucht welche mir die Koordinaten eines Punktes liefert und leider bis jetzt nichts gefunden. Gibt es eine einfache Funktion welche mir diese Werte ausgeben kann ?
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Erichmo: Da ist nichts zu finden, das muss man sich programmieren. Und wie das konkret aussieht, hängt davon ab wie man das Quadrat mit den Buchstaben speichert. Man könnte eine Zeichenkette nehmen die alle 25 Zeichen enthält, den Index des Buchstabens suchen und den dann in Zeile/Spalte umrechnen. Oder man kann das Quadrat als Liste von Zeilen des Quadrats speichern und die durchgehen bis man den Index des gesuchten Buchstabens gefunden hat, dabei die Zeilen mitzählen. Oder man erstellt beim erstellen der Zeichenkette für das gesamte Quadrat oder der Liste der Zeilen auch gleich ein Wörterbuch das Buchstaben auf Koordinaten abbildet. Und vielleicht auch gleich die Umkehrung.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich hab' da mal was in QBasic geschrieben…

Code: Alles auswählen

DECLARE FUNCTION MakeKeyTable$ (k AS STRING)
DECLARE SUB PrintKeyTable (keytable AS STRING)
DECLARE FUNCTION PreparePlaintext$ (text AS STRING)
DECLARE FUNCTION FilterLetters$ (s AS STRING)
DECLARE SUB PrintPairs (text AS STRING)
DECLARE SUB GetCoordinate (keytable AS STRING, letter AS STRING, coord AS ANY)
DECLARE FUNCTION GetLetterAt$ (keytable AS STRING, coord AS ANY)
DECLARE FUNCTION Add% (a AS INTEGER, b AS INTEGER)
DECLARE FUNCTION Recode$ (keytable AS STRING, pairs AS STRING, direction AS INTEGER)

' =================
'  Playfair Cipher
' =================
'
' QBasic implementation by Marc 'BlackJack' Rintsch.
'
' Encoding and decoding shown with the variant and example from Wikipedia.
' That is replacing J by I and breaking up same letter pairs and padding
' with X.
'
' The Wikipedia article leaves the case of encoding a pair of same letters
' undefined.  This can happen even with breaking up same letters when the
' message contains a pair of the letter used to break up pairs or ends up
' whith that letter and needs padding at the end.  Examples:
'
' Plaintext: In Zaxxon you better watch your six.
'  Prepared: IN ZA XX XX ON YO UB ET TE RW AT CH YO UR SI XX
'                  ^^ ^^                                  ^^
' (Zaxxon is a 1982 isometric shooter arcade game by Sega, ported to many
'  home computer systems.)
'
' The case of encoding a pair of same letters is handled like them being
' in the same column in the key table.  Which of course they are, but they
' are also in the same row.  Some variants handle it that way, some don't
' change those pairs, some move down *and* right in the key table, ...

CONST ENCODE = 1, DECODE = -1

TYPE Coordinate
  x AS INTEGER
  y AS INTEGER
END TYPE

DIM keytable AS STRING, text AS STRING, prepared AS STRING
DIM encoded AS STRING, decoded AS STRING

keytable = MakeKeyTable("death")
PrintKeyTable keytable

text = "Laboulaye lady will lead to Cibola temples of gold."
PRINT "Plaintext: "; text
prepared = PreparePlaintext(text)
PRINT " Prepared: "; : PrintPairs prepared
encoded = Recode(keytable, prepared, ENCODE)
PRINT "  Encoded: "; : PrintPairs encoded
decoded = Recode(keytable, encoded, DECODE)
PRINT "  Decoded: "; : PrintPairs decoded

PRINT : SYSTEM

' Add a and b and restrict the result to 0 to 5.
FUNCTION Add% (a AS INTEGER, b AS INTEGER)
  DIM result AS INTEGER

  result = (a + b) MOD 5
  IF result < 0 THEN result = result + 5
  Add = result
END FUNCTION

' Return just the letters from given string. Uppercased and J replaced by I.
FUNCTION FilterLetters$ (s AS STRING)
  DIM result AS STRING, i AS INTEGER, j AS INTEGER, c AS STRING * 1

  result = SPACE$(LEN(s))
  j = 0
  FOR i = 1 TO LEN(s)
    c = UCASE$(MID$(s, i, 1))
    IF c >= "A" AND c <= "Z" THEN
      IF c = "J" THEN c = "I"
      j = j + 1
      MID$(result, j, 1) = c
    END IF
  NEXT
  FilterLetters = LEFT$(result, j)
END FUNCTION

' Put the coordinate of letter in key table into given coordinate.
' If letter isn't in key table the coordinate is set to (-1, 0).
SUB GetCoordinate (keytable AS STRING, letter AS STRING, coord AS Coordinate)
  DIM i AS INTEGER

  i = INSTR(keytable, letter) - 1
  coord.x = i MOD 5
  coord.y = i \ 5
END SUB

' Get the letter at given coordinate from key table.
FUNCTION GetLetterAt$ (keytable AS STRING, coord AS Coordinate)
  GetLetterAt = MID$(keytable, (coord.x + coord.y * 5) + 1, 1)
END FUNCTION

' Turns given key phrase into a key table.
FUNCTION MakeKeyTable$ (k AS STRING)
  DIM i AS INTEGER, j AS INTEGER, offset AS INTEGER
  DIM result AS STRING * 25, c AS STRING * 1, v AS INTEGER
  DIM seen(25) AS INTEGER

  ' Start by putting the letters from the key phrase into the key table.
  k = FilterLetters(k)
  j = 0
  FOR i = 1 TO LEN(k)
    c = MID$(k, i, 1)
    v = ASC(c) - ASC("A")
    IF NOT seen(v) THEN
      seen(v) = -1
      j = j + 1
      MID$(result, j, 1) = c
    END IF
  NEXT
 
  ' Fill remaining table entries with still unused letters.
  offset = 0
  FOR i = 0 TO 24
    IF i = ASC("J") - ASC("A") THEN offset = 1
    IF NOT seen(i + offset) THEN
      j = j + 1
      MID$(result, j, 1) = CHR$(i + offset + ASC("A"))
    END IF
  NEXT

  MakeKeyTable = result
END FUNCTION

' Prepare the plaintext by filtering and upcasing letters, replacing J by I,
' prevent letter pairs consisting of two equal letters, and padding the text
' to an even length if needed.
FUNCTION PreparePlaintext$ (text AS STRING)
  DIM result AS STRING
  DIM i AS INTEGER, j AS INTEGER
  DIM first AS STRING * 1, second AS STRING * 1

  text = FilterLetters(text)
  ' Worst case length: odd text length & all same letter pairs.
  result = SPACE$(LEN(text) * 2)
  i = 1: j = 0
  DO UNTIL i > LEN(text)
    first = MID$(text, i, 1)
    i = i + 1
    IF i > LEN(text) THEN
      second = "X"
    ELSE
      second = MID$(text, i, 1)
      IF first = second THEN second = "X" ELSE i = i + 1
    END IF
    MID$(result, j + 1, 1) = first
    MID$(result, j + 2, 1) = second
    j = j + 2
  LOOP
  PreparePlaintext = LEFT$(result, j)
END FUNCTION

' Print the key table as 5 rows of 5 letters each.
SUB PrintKeyTable (keytable AS STRING)
  DIM i AS INTEGER
  FOR i = 0 TO 4: PRINT MID$(keytable, i * 5 + 1, 5): NEXT
END SUB

' Print string in pairs of characters, separated by a space.
SUB PrintPairs (text AS STRING)
  DIM i AS INTEGER

  FOR i = 1 TO LEN(text) STEP 2
    PRINT MID$(text, i, 2); " ";
  NEXT
  PRINT
END SUB

' Encode or decode (depending on given direction) the given letter pairs
' with given key table.
FUNCTION Recode$ (keytable AS STRING, pairs AS STRING, direction AS INTEGER)
  DIM result AS STRING, first AS Coordinate, second AS Coordinate
  DIM i AS INTEGER, tmp AS INTEGER

  result = SPACE$(LEN(pairs))
  FOR i = 1 TO LEN(pairs) STEP 2
    GetCoordinate keytable, MID$(pairs, i, 1), first
    GetCoordinate keytable, MID$(pairs, i + 1, 1), second
    IF first.x <> second.x AND first.y <> second.y THEN
      tmp = first.x
      first.x = second.x
      second.x = tmp
    ELSEIF first.x = second.x THEN
      first.y = Add(first.y, direction)
      second.y = Add(second.y, direction)
    ELSEIF first.y = second.y THEN
      first.x = Add(first.x, direction)
      second.x = Add(second.x, direction)
    END IF
    MID$(result, i, 1) = GetLetterAt(keytable, first)
    MID$(result, i + 1, 1) = GetLetterAt(keytable, second)
  NEXT
  Recode = result
END FUNCTION
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten