# Kryptographie - Enigma



## javama (24. Oktober 2019)

Hallo kann mir jemand helfen die Aufgabe zu lösen:

Mit einer Enigma wurde folgendes Chiffrat erzeugt:

 BGLRAOGHKRWRGSKCNSJAXXUUEXNSRXQUDXOSZHNIWLUVKXIPJSNJTM 

Entschlusseln Sie das Chiffrat per Brute-Force-Angriff unter der Annahme, dass ¨ der Klartext mit dem Wort WETTERBERICHT beginnt, kein Steckerbrett verwendet wurde und die Verschlusselung wie folgt abl ¨ auft: ¨ Jeder Buchstabe passiert bei der Verschlusselung zuerst die Walzen 1, 2 und 3, dann ¨ die Umkehrwalze und anschließend die Walzen 3, 2 und 1 jeweils in umgekehrter Richtung. Die untenstehenden Tabellen beschreiben die jeweiligen Transformationen. Dabei steht der transformierte Buchstabe an der alphabetischen Position des hereinkommenden Buchstabens; Walze 1 transformiert also in Grundstellung 
beispielsweise A zu B, B zu D und C zu F. Nach einer Rotation aus der Grundstellung verschlusselt Walze 1 ¨ Z zu A, A zu C , B zu E und so fort; Entsprechendes gilt fur Walze 2. Sie dürfen außerdem als bekannt voraussetzen, dass Walze ¨ 2 in der unten angegebenen Grundstellung zum ersten Mal unmittelbar vor der zweiundzwanzigsten Eingabe rotiert. 
Walze 1:    {’B’,’D’,’F’,’H’,’J’,’L’,’C’,’P’,’R’,’T’,’X’,’V’,’Z’,’N’,’Y’,’E’,’I’,’W’,’G’,’A’,’K’,’M’,’U’,’S’,’Q’,’O’} 
Walze 2:    {’A’,’J’,’D’,’K’,’S’,’I’,’R’,’U’,’X’,’B’,’L’,’H’,’W’,’T’,’M’,’C’,’Q’,’G’,’Z’,’N’,’P’,’Y’,’F’,’V’,’O’,’E’} 
Walze 3:    {’E’,’K’,’M’,’F’,’L’,’G’,’D’,’Q’,’V’,’Z’,’N’,’T’,’O’,’W’,’Y’,’H’,’X’,’U’,’S’,’P’,’A’,’I’,’B’,’R’,’C’,’J’}
 Umkehrwalze:   {’Y’,’R’,’U’,’H’,’Q’,’S’,’L’,’D’,’P’,’X’,’N’,’G’,’O’,’K’,’M’,’I’,’E’,’B’,’F’,’Z’,’C’,’W’,’V’,’J’,’A’,’T’}


----------



## StormChaser (25. Oktober 2019)

Leider verstehe ich die Aufgabe nicht richtig, denn statt des "B" als ersten Buchstaben erhalte ich "R", und zwar durch:
Eingabe: W
nach Walze #1 => U
nach Walze #2 => P
nach Walze #3 => H
nach Walze #4 => D
nach Walze #3 => F
nach Walze #2 => I
nach Walze #1 => R 

Wenn ich LeerEingaben so weit laufen lasse, bis ich das "B" erhalte, klappt es zwar noch bis zum "G", aber dann ist auch Schluss. Wobei ich da auch wieder nicht sicher bin, ob und wie die 2. Walze mit der 22. Eingabe konkret zu behandeln ist und gehe einfach davon aus, dass es eine zusätzliche Rotation ist. Vielleicht liegt ja da schon der erste Fehler bei mir.

Mir ist auch nicht klar, was


> anschließend die Walzen 3, 2 und 1 jeweils in umgekehrter Richtung


 konkret bedeuten soll. "3, 2, 1" ist ja schon die umgekehrte Richtung bezogen auf die Walzennummerierung. Was hat es da mit "_jeweils in umgekehrter Richtung_" auf sich ?


----------



## zerix (25. Oktober 2019)

StormChaser hat gesagt.:


> Leider verstehe ich die Aufgabe nicht richtig, denn statt des "B" als ersten Buchstaben erhalte ich "R", und zwar durch:
> Eingabe: W
> nach Walze #1 => U
> nach Walze #2 => P
> ...



Na es soll doch mittels brute-force gelöst werden. Das einzige was du noch 'brute-force'n kannst ist wann die Ẃalzen gedreht werden. Damit es möglich ist, hast du auch Fixpunkte erhalten, beispielsweise wann die zweite Walze dreht und was das erste Wort ist. Beispielsweise kann Walze 1,3 oder die Umkehrwalze nach einem Durchlauf gedreht werden. 

Das mit "3, 2, 1" und umgekehrt ist wahrscheinlich einfach nur doppelt um es deutlich zu machen.

Viele Grüße
Sascha


----------



## StormChaser (25. Oktober 2019)

Hallo Sascha,
danke für die Hinweise.
Zur Enigma hatte ich nochmal einiges nachgelesen. So, wie ich das mit den Walzen (für die Aufgabe) verstehe, handelt es sich um mehrere nacheinander geschaltete "Kilometerzähler": Nach jeder Eingabe der 1. Walze wird die Walze gedreht. Nach 26 Eingaben ist es eine vollständige Rotation und es wird die 2. Walze gedreht. Laut Aufgabe erfolgt vor der 22. Eingabe bereits eine Rotation der 2. Walze. Nach der 26. Rotation der 2. Walze rotiert die 3. Walze. Die Umkehrwalze (Walze 4) rotiert nicht. (Sie soll eigentlich die Dechiffrierung ermöglichen; wie, weiss ich auch noch nicht.) 

Soweit ist eigentlich alles klar. Bis auf "jeweils in umgekehrter Richtung".


----------



## Technipion (25. Oktober 2019)

Ich finde es schön, dass der Thread hier Fahrt aufnimmt, aber:


javama hat gesagt.:


> Hallo kann mir jemand helfen die Aufgabe zu lösen:


So nicht mein Lieber. Erst mal zeigst du uns, welche Gedanken du dir bis hierher gemacht hast und welchen Lösungsweg (Code?) du bis jetzt erarbeitet hast. Die Aufgabe klingt mir nämlich sehr nach einem Übungsblatt einer Uni, und wir machen hier nicht deine Hausaufgaben für dich!


----------



## javama (29. Oktober 2019)

Technipion hat gesagt.:


> Ich finde es schön, dass der Thread hier Fahrt aufnimmt, aber:
> 
> So nicht mein Lieber. Erst mal zeigst du uns, welche Gedanken du dir bis hierher gemacht hast und welchen Lösungsweg (Code?) du bis jetzt erarbeitet hast. Die Aufgabe klingt mir nämlich sehr nach einem Übungsblatt einer Uni, und wir machen hier nicht deine Hausaufgaben für dich!



ich habe schon einiges versucht, meine farge ist wenn ich "B" eingebe sollte "W" rauskommen, kann mir jemand das erläutern?


----------



## zerix (29. Oktober 2019)

javama hat gesagt.:


> ich habe schon einiges versucht, meine farge ist wenn ich "B" eingebe sollte "W" rauskommen, kann mir jemand das erläutern?


Wann soll das denn passieren? Wenn 'B' als erster Buchstabe eingegeben wird?

Viele Grüße
Sascha


----------



## javama (29. Oktober 2019)

zerix hat gesagt.:


> Wann soll das denn passieren? Wenn 'B' als erster Buchstabe eingegeben wird?
> 
> Viele Grüße
> Sascha




BGLRAOGHKRWRGSKCNSJAXXUUEXNSRXQUDXOSZHNIWLUVKXIPJSNJTM 
WETTERBERICHT

B-->W
G-->E
....


----------



## zerix (29. Oktober 2019)

Ich glaube das hast du falsch verstanden. Gibst du W ein, muss ein B herauskommen.

Viele Grüße
Sascha


----------



## javama (31. Oktober 2019)

zerix hat gesagt.:


> Ich glaube das hast du falsch verstanden. Gibst du W ein, muss ein B herauskommen.
> 
> Viele Grüße
> Sascha


enigma funktioniert so entschlüsselung = verschlüsselung das heisst klartext W ergibt Chiffrat B und umgekehrt


----------



## zerix (1. November 2019)

javama hat gesagt.:


> enigma funktioniert so entschlüsselung = verschlüsselung das heisst klartext W ergibt Chiffrat B und umgekehrt


Stimmt, hatte ich vergessen. In der Theorie müsste man nur die Walzenstellung suchen, die bei der Verschlüsselung war. Das heißt solange rotieren, bis 'B'=='W'.
Habe ich mal so implementiert, funktioniert leider nicht. Es kommt bisher nie das Wort 'WETTERBERICHT' heraus.


----------



## Technipion (1. November 2019)

@zerix: Ich habe nebenbei auch ein kleines Python-Skript zur Entschlüsselung geschrieben, und dem System dabei so viele Freiheitsgrade wie möglich gegeben (beliebige Walzenstellungen 1 bis 4). Außerdem die Rotationsrichtung (im und gegen Uhrzeigersinn) variabel gelassen. Hat alles nicht gepasst.
Dann habe ich sogar noch alle Walzenpermutationen durchprobiert, aber wieder Fehlanzeige. Ich glaube die Aufgabe ist unlösbar. (Ich hatte auch bedacht die Buchstaben nach der Umkehr rückwärts durch die Walzenkanäle zu transformieren)

@javama: Mich würde mal interessieren was in der Auflösung rauskam?


----------



## zerix (1. November 2019)

Technipion hat gesagt.:


> @zerix: Ich habe nebenbei auch ein kleines Python-Skript zur Entschlüsselung geschrieben, und dem System dabei so viele Freiheitsgrade wie möglich gegeben (beliebige Walzenstellungen 1 bis 4). Außerdem die Rotationsrichtung (im und gegen Uhrzeigersinn) variabel gelassen. Hat alles nicht gepasst.
> Dann habe ich sogar noch alle Walzenpermutationen durchprobiert, aber wieder Fehlanzeige. Ich glaube die Aufgabe ist unlösbar. (Ich hatte auch bedacht die Buchstaben nach der Umkehr rückwärts durch die Walzenkanäle zu transformieren)
> 
> @javama: Mich würde mal interessieren was in der Auflösung rauskam?



Ich habe das implementiert was oben gegen war. Wie die Walze rotiert. Das ist für W1 u W2 gegeben. Bei W1 bin ich davon ausgegangen, dass diese nach jeder Eingabe rotiert und W2 nach jeder 21. Eingabe. Über W3 und U wird keine Aussage getroffen, also habe ich diese auch bei jedem 21. mal und gar nicht rotieren lassen.


----------



## StormChaser (9. November 2019)

Purer Zufall: Beim Einsortieren einiger Filme stiess ich auf 
Enigma - Das Geheimnis
Sehr passend zum Themenbereich, wenn auch nicht ganz zur Fragestellung.
Im Film sieht man auch die Turing-Bombe bei der Arbeit, also bei dem, was wir hier ja auch versuchen. Nur haben wir heute dazu sehr leistungsstarke Computer - es hapert lediglich an der Findung des passenden Algorithmus


----------



## Technipion (9. November 2019)

StormChaser hat gesagt.:


> Nur haben wir heute dazu sehr leistungsstarke Computer - es hapert lediglich an der Findung des passenden Algorithmus


Unsere Computer sind sogar so schnell, dass wir die Lösung über Brute-Force finden können (wie in der Aufgabe verlangt). Ist es dir denn gelungen die Nachricht zu entschlüsseln? Weil mein Python-Skript hat zwar alle erdenklichen Kombinationen durchprobiert, jedoch leider kein "WETTERBERICHT" ausfindig machen können...


----------



## StormChaser (9. November 2019)

Leider auch noch nicht.
Ich bin noch dabei, den WETTERBERICHT zu BGLRAOGHKRWRG zu chiffrieren.


----------



## zerix (10. November 2019)

Technipion hat gesagt.:


> Unsere Computer sind sogar so schnell, dass wir die Lösung über Brute-Force finden können (wie in der Aufgabe verlangt). Ist es dir denn gelungen die Nachricht zu entschlüsseln? Weil mein Python-Skript hat zwar alle erdenklichen Kombinationen durchprobiert, jedoch leider kein "WETTERBERICHT" ausfindig machen können...



Alle möglichen Kombinationen hast du noch nicht ausprobiert. 
Von Enigma ist bekannt, dass die Walzen unabhängig voneinander rotieren können. Meist wurden sie aber wie ein Kilometerzähler verwendet. Es kann aber auch ganz anders sein, beispielsweise dass Walze 1 jede 10. und Walze 3 jede 2. Eingabe iteriert.


----------



## Technipion (10. November 2019)

zerix hat gesagt.:


> Von Enigma ist bekannt, dass die Walzen unabhängig voneinander rotieren können. Meist wurden sie aber wie ein Kilometerzähler verwendet. Es kann aber auch ganz anders sein


Boah, ist das fies 

Dann muss ich aber sagen ist die Aufgabe sehr komisch gestellt. Ich habe jetzt schon 2 Anläufe gehabt den Code mit einem Python-Programm zu knacken. Bin sogar so weit gegangen mir eine eigene Klasse für die Rollen zu bauen. Aber immer noch Fehlanzeige. Finde das unverständlich so eine Aufgabe an Studenten weiterzureichen. Damit demotiviert man die ja nur.


----------



## zerix (10. November 2019)

Hier ist mein aktuelles Script. Wenn ich richtig denke, sollten so alle Möglichkeiten durchgegangen werden.
Nur vorwärts rotieren habe ich noch nicht getestet. Vorwärts bedeutet hier: Nach einer Rotation aus der Grundstellung verschlüsselt Walze 1 B zu C, C zu E , D zu G usw. Die Funktion ist schon implementiert und heißt rf (rotate forward). Man muss nur rb durch rf ersetzen für W3 (Walze 3).

```
import sys
ALPHABET = [chr(x) for x in range(0x41,0x41+26)]
X1= ('B','D','F','H','J','L','C','P','R','T','X','V','Z','N','Y','E','I','W','G','A','K','M','U','S','Q','O')
X2= ('A','J','D','K','S','I','R','U','X','B','L','H','W','T','M','C','Q','G','Z','N','P','Y','F','V','O','E')
X3= ('E','K','M','F','L','G','D','Q','V','Z','N','T','O','W','Y','H','X','U','S','P','A','I','B','R','C','J')
XU= ('Y','R','U','H','Q','S','L','D','P','X','N','G','O','K','M','I','E','B','F','Z','C','W','V','J','A','T')
E = 'BGLRAOGHKRWRGSKCNSJAXXUUEXNSRXQUDXOSZHNIWLUVKXIPJSNJTM'
to_dict = lambda x: {chr(k+0x41):v for k,v in enumerate(x)}
# key for value
kfv = lambda d,x : [y for y,z in d.items() if z==x][0]
# encrypt
e = lambda x: kfv(W1,kfv(W2, kfv(W3,U[W3[W2[W1[x]]]])))
# predecessor
p = lambda x : ALPHABET[((ord(x)-0x41-1)+26)%26]
# successor
s = lambda x : ALPHABET[((ord(x)-0x41+1)+26)%26]
# rotate back
rb = lambda x : { p(k): p(v) for k,v in x.items() }
# rotate forward
rf = lambda x : { s(k): s(v) for k,v in x.items() }
ow1 = to_dict(X1)
ow2 = to_dict(X2)
ow3 = to_dict(X3)
ou = to_dict(XU)
W1 = to_dict(X1)
W2 = to_dict(X2)
W3 = to_dict(X3)
U = to_dict(XU)
counter_0 = 0
counter_1 = 0
counter_2 = 0
counter_3 = 0
D = ''
r3 = 1
rotated3 = False
rotated2 = False
rotated1 = False
for rw3 in range(1,26*26+1):
    for rw1 in range(1,26*26+1):
        counter_0 = 0
        rotated1 = False
        rotated2 = False
        rotated3 = False
        print(rw3, rw1)
        while True:
            if e(E[0])+\
            e(E[1])+\
            e(E[2])+\
            e(E[3])+\
            e(E[4])+\
            e(E[5]) == 'WETTER':
                for l in E:
                    D += e(l)
                print(D)
                sys.exit()
            counter_0 += 1
           
            if (counter_0) % rw1 == 0:
                W1 = rb(W1)
                rotated1 = True
            if (counter_0) % 21 == 0:
                W2 = rb(W2)
                rotated2 = True
            if counter_0 % rw3 == 0:
                W3 = rb(W3)
                rotated3 = True
            if rotated1 and rotated2 and rotated3 and ow1 == W1 and ow2 == W2 and ow3 == W3 and ou == U:
                break
```


----------



## StormChaser (10. November 2019)

zerix hat gesagt.:


> Nur vorwärts rotieren habe ich noch nicht getestet. Vorwärts bedeutet hier: Nach einer Rotation aus der Grundstellung verschlüsselt Walze 1 B zu C, C zu E , D zu G usw.


@zerix: Bist du sicher, dass das richtig ist? Denn laut Aufgabe heisst es:


> Walze 1 transformiert also in Grundstellung
> beispielsweise A zu B, B zu D und C zu F. Nach einer Rotation aus der Grundstellung verschlusselt Walze 1 ¨ Z zu A, A zu C , B zu E und so fort



Aber durch dein rb() und rf() ist mir erst klar geworden, dass die Rotation auch in die andere Richtung gehen kann - vielleicht ist das ja in der Aufgabenstellung mit  "_jeweils in umgekehrter Richtung_"  gemeint. Dann hiesse das, dass die Walzen bei Eingabe eines einzigen Buchstabens in zwei verschiedene Richtungen drehen (können). In der Umsetzung erhöht das die Anzahl zu berücksichtigender Möglichkeiten; bisher hatten meine Walzen nur die Vorwärts-Richtung gekannt.


----------



## zerix (10. November 2019)

StormChaser hat gesagt.:


> @zerix: Bist du sicher, dass das richtig ist? Denn laut Aufgabe heisst es:
> 
> 
> Aber durch dein rb() und rf() ist mir erst klar geworden, dass die Rotation auch in die andere Richtung gehen kann - vielleicht ist das ja in der Aufgabenstellung mit  "_jeweils in umgekehrter Richtung_"  gemeint. Dann hiesse das, dass die Walzen bei Eingabe eines einzigen Buchstabens in zwei verschiedene Richtungen drehen (können). In der Umsetzung erhöht das die Anzahl zu berücksichtigender Möglichkeiten; bisher hatten meine Walzen nur die Vorwärts-Richtung gekannt.



rb ist rückwärts rotieren. Das ist für Walze 1 und 2 gegeben, in welche Richtung Walze 3 rotiert ist gar nicht angegeben, d.h. sie könnte in die andere Richtung rotieren.
Nein, das "in umgekehrter Richtung" bedeutet was anderes.
Wenn man W verschlüsseln möchte, wird bei Walze 1 an Stelle 'W' geschaut (W1['W']). Beim Rückweg wird dann der Buchstabe der Umkehrrolle genommen, bspw. 'W' und es wird dann geschaut, wo steht das 'W' und dann wird mit den jeweiligen Index weitergemacht.  Das wäre in Grundstellung das 'N'. Das heißt bei Walze 3 steht am Index 'N' das 'W'. W3['N'] = 'W'. Mit dem 'N' geht man dann zur Walze 2 und macht das dort mit den 'N'.


Viele Grüße
Sascha


----------



## StormChaser (10. November 2019)

Dann habe ich Aufgabe noch falscher verstanden. Bei mir geht ein Buchstabe durch 7 Chiffrierungen bis sein Chiffrat ausgegeben wird. Wenn schon das falsch ist, kann ich ja nie auf die Lösung kommen, ganz abgesehen von den Rotationen


----------



## zerix (10. November 2019)

StormChaser hat gesagt.:


> Dann habe ich Aufgabe noch falscher verstanden. Bei mir geht ein Buchstabe durch 7 Chiffrierungen bis sein Chiffrat ausgegeben wird. Wenn schon das falsch ist, kann ich ja nie auf die Lösung kommen, ganz abgesehen von den Rotationen


Geht es ja mehr oder weniger auch.
Bsp:

Eingabe: 'W'
Walze1 ['W']: 'U'
Walze2 ['U']: 'P'
Walze3 ['P']: 'H'
Umkehr['H']: 'D'
Walze3 ['G'] : 'D'
Walze2 ['R']: 'G'
Walze1 ['I']: 'R'

Damit sollte 'W' zu 'I' verschlüsselt werden. Da Enigma mit der Verschlüsselungsmethode auch entschlüsselt, sollte 'I' zu 'W' werden.

Eingabe: 'I'
Walze1 ['I']: 'R'
Walze2 ['R']: 'G'
Walze3 ['G']: 'D'
Umkehr['D']: 'H'
Walze3 ['P'] : 'H'
Walze2 ['U']: 'P'
Walze1 ['W']: 'U'

Damit sollte das passen. Das macht auch so meine encrypt function e.

Viele Grüße
Sascha


----------



## StormChaser (10. November 2019)

UPHD habe ich auch noch, dann gibt es Unterschiede. Muss ich noch mal ran. Diese Umkehrgeschichte macht mir echt zu schaffen.


----------



## zerix (10. November 2019)

Nach der Umkehrwalze schaust du halt, wie der Index zum Buchstaben ist. Also du nimmst das 'D' und läufst durch Walze3 und schaut, wo das 'D' steht. Der Schlüssel zu dem Wert ist dann der gesuchte Buchstabe. (Falls du eine Hashmap oder ein dict nutzt, abhängig von Sprache. )


----------



## StormChaser (10. November 2019)

Nach dem 'D', änderst du da schon die Rotierrichtung?

edit:
Ach, du suchst den KEY zu dem BUCHSTABEN!
Das eröffnet schon wieder völlig neue Möglichkeiten 

edit2: Dann ist das jetzt aber das "_jeweils in umgekehrter Richtung_" . Macht dann auch Sinn.


----------



## zerix (10. November 2019)

StormChaser hat gesagt.:


> Nach dem 'D', änderst du da schon die Rotierrichtung?
> 
> edit:
> Ach, du suchst den KEY zu dem BUCHSTABEN!
> ...


Richtig, das heißt in umgekehrter Richtung. Da wird noch nichts rotiert.


----------



## StormChaser (10. November 2019)

zerix hat gesagt.:


> Eingabe: 'W'
> Walze1 ['W']: 'U'
> Walze2 ['U']: 'P'
> Walze3 ['P']: 'H'
> ...



So, da bin ich inzwischen auch angekommen mit einem Unterschied, der darauf beruht, dass ich die erste Walze nach jeder Eingabe (vorwärts) rotieren lasse, so dass die Eingabe von 'W' zu U=>P => H =>D => G => R => 'W' wird, weil nach der Erzeugung von 'U' die 1. Walze rotiert.

Dies macht ein weiteres Definitionsproblem deutlich: Was gilt als 'Eingabe' ? Nur das, was von aussen kommt, oder auch bereits intern weitergereichte Buchstaben.
Bedeutend ist die Frage für den Hinweis im Eingangspost auf die 22. Rotation der 2. Walze: Zieht man auch die internen Weitergaben mit ein, so erfolgt die  Rotation um den 11. einzugebenden Buchstaben herum, da bei jedem von aussen eingegebenen Buchstaben die Walzen 1, 2 und 3 je 2x besucht werden.


----------



## zerix (10. November 2019)

Eingabe ist nur die tatsächliche Eingabe und nicht die interne Verarbeitung.
Aber du kannst ja mal testen, ob für den verschlüsselten Buchstaben, der richtige Klartextbuchstabe herauskommt, wenn du diesen eingibst, bei gleicher Walzenstellung. Du solltest natürlich nicht das 'W' wählen, sondern einen beliebigen anderen.

Viele Grüße
Sascha


----------



## StormChaser (10. November 2019)

Gebe ich "WETTERBERICHT" ein, erhalte ich *z. B.* "IECHISQOFXXUT". Gebe ich das ein, gibt es alles Mögliche, nur keinen Wetterbericht 
Ich baue dann mal um, so dass die Rotationen erst erfolgen, wenn eine Eingabe abgearbeitet ist.

edit:
so, jetzt geht es zumindest in beide Richtungen, und beide Rotierrichtungen.
Wenn die erste Walze nach jeder Eingabe rotiert,
und die 2. Walze nach mehr als 13 Eingaben,
und die 3. Walze nach mehr als 13 Eingaben,
und die 4. Walze nicht rotiert,
und ich gebe WETTERBERICHT ein,
dann erhalte ich
a) IFZHWEYKTJEXE 
b) IGENLPAOOYABA
Beide lassen sich bei der entsprechenden Rotierrichtung  wieder zu WETTERBERICHT dechiffrieren.

Kann das jemand bestätigen ?


----------



## zerix (11. November 2019)

Hi, 

ich erhalte die gleiche Ausgabe. 
Allerdings weiß ich nicht, warum du vorwärts rotieren lässt. Die Rotationsrichtung für Walze1 und Walze2 sind gegeben.

Viele Grüße


----------



## StormChaser (11. November 2019)

zerix hat gesagt.:


> Hi,
> 
> ich erhalte die gleiche Ausgabe.
> Allerdings weiß ich nicht, warum du vorwärts rotieren lässt. Die Rotationsrichtung für Walze1 und Walze2 sind gegeben.


Danke für die Bestätigung.

Zum Einen als Test, ob es auch in die andere Richtung funktioniert.
Zum Anderen weil für mich nicht klar ist, ob mein "vorwärts" bzw. "rückwärts"  auch das gemeinte "vorwärts" bzw. "rückwärts" ist.
Allerdings ist aus der Aufgabe schon die Rotationsrichtung anzunehmen, insofern mache ich mir hier vielleicht mehr Mühe als nötig.


----------



## Technipion (12. November 2019)

Wo wir schon munter am Raten sind, würde ich einfach mal noch meinen Code in den Pott werfen:


Spoiler: Spaghetticode





```
# tutorials.de: Kryptographie - Enigma

import itertools
import copy
import multiprocessing


def main():
    cyphertext = 'BGLRAOGHKRWRGSKCNSJAXXUUEXNSRXQUDXOSZHNIWLUVKXIPJSNJTM'

    R1 = ['B','D','F','H','J','L','C','P','R','T','X','V','Z','N','Y','E','I','W','G','A','K','M','U','S','Q','O']
    R2 = ['A','J','D','K','S','I','R','U','X','B','L','H','W','T','M','C','Q','G','Z','N','P','Y','F','V','O','E']
    R3 = ['E','K','M','F','L','G','D','Q','V','Z','N','T','O','W','Y','H','X','U','S','P','A','I','B','R','C','J']
    RR = ['Y','R','U','H','Q','S','L','D','P','X','N','G','O','K','M','I','E','B','F','Z','C','W','V','J','A','T']

    rolls = (EnigmaRoll(R1), EnigmaRoll(R2), EnigmaRoll(R3), EnigmaRoll(RR))

    run_test(rolls)

    target = 'WET'
    message = cyphertext[:len(target)]

    candidates = []
    test_sets = [(rot1,
                  copy.deepcopy(rolls),
                  message, target) for rot1 in range(26)]

    with multiprocessing.Pool() as p:
        candidates = p.map(filter_candidates, test_sets)

    candidates = list( filter(lambda x: not x is None, candidates) )
    candidates  = list( itertools.chain(*candidates) ) # flatten
    print(len(candidates), 'candidates found.')

    for c in candidates:
        rot1, rot2, rot3, dirleft = c
        for R in rolls: R.reset()
        rolls[0].rotate(rot1, dirleft)
        rolls[1].rotate(rot2, dirleft)
        rolls[2].rotate(rot3, dirleft)

        print(rot1, rot2, rot3, dirleft, encrypted(cyphertext, rolls, dirleft))

    return 0


def filter_candidates(args):
    rot1, rolls, msg, target = args

    results = []

    for rot2 in range(26):
        for rot3 in range(26):
            for dirleft in (True, False):
                for R in rolls: R.reset()
                rolls[0].rotate(rot1, dirleft)
                rolls[1].rotate(rot2, dirleft)
                rolls[2].rotate(rot3, dirleft)

                if encrypted(msg, rolls, dirleft) == target:
                    results.append( (rot1, rot2, rot3, dirleft) )

    if len(results) == 0:
        return None
    else:
        return results


def run_test(rolls):
    test_msgs = itertools.combinations('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 3)

    for rot1 in range(26):
        for rot2 in range(26):
            for rot3 in range(26):
                for dirleft in (True, False):
                    for msg in test_msgs:
                        msg = ''.join(msg)

                        for R in rolls: R.reset()
                        rolls[0].rotate(rot1, dirleft)
                        rolls[1].rotate(rot2, dirleft)
                        rolls[2].rotate(rot3, dirleft)

                        msg_enc = encrypted(msg, rolls, dirleft)

                        for R in rolls: R.reset()
                        rolls[0].rotate(rot1, dirleft)
                        rolls[1].rotate(rot2, dirleft)
                        rolls[2].rotate(rot3, dirleft)

                        msg_dec = encrypted(msg_enc, rolls, dirleft)

                        if msg_dec != msg:
                            print('ERROR:', msg, '->', msg_enc, '->', msg_dec)
                            raise RuntimeError('run_test failed')

    for R in rolls: R.reset()
    print('run_test was successful')


def encrypted(msg, rolls, dirleft=False):
    R1, R2, R3, RR = rolls

    result = ''

    for i, m in enumerate(msg):
        ch = ord(m) - ord('A')

        ch = R1.transform_forward(ch)
        ch = R2.transform_forward(ch)
        ch = R3.transform_forward(ch)

        ch = RR.transform_forward(ch)

        ch = R3.transform_backward(ch)
        ch = R2.transform_backward(ch)
        ch = R1.transform_backward(ch)

        result += chr(ch + ord('A'))

        R1.rotate(1, dirleft)

    return result


class EnigmaRoll:
    def __init__(self, ground_state):
        channels = []
        for i, c in enumerate(ground_state):
            channels.append( (i, ord(c) - ord('A')) )

        self.channels = channels
        self.rotation = 0


    def transform_forward(self, ch):
        local_ch = ch + self.rotation
        local_ch %= len(self.channels)

        for source, dest in self.channels:
            if source == local_ch:
                local_result = dest
                break

        result = local_result - self.rotation
        if result > len(self.channels):
            result %= len(self.channels)
        while result < 0:
            result += len(self.channels)

        return result


    def transform_backward(self, ch):
        for i in range(len(self.channels)):
            if self.transform_forward(i) == ch:
                return i


    def rotate_left(self, steps=1):
        self.rotation += steps
        self.rotation %= len(self.channels)


    def rotate_right(self, steps=1):
        self.rotation -= steps
        while self.rotation < 0:
            self.rotation += len(self.channels)


    def rotate(self, steps=1, dirleft=False):
        if dirleft:
            self.rotate_left(steps)
        else:
            self.rotate_right(steps)


    def reset(self):
        self.rotation = 0


if __name__ == '__main__':
    main()
```




Aber wie gesagt, ich kriege auch nichts Vernünftiges heraus


----------



## zerix (12. November 2019)

Hier mal meine aktuelle Version. Sie vereinfacht das bruteforcen etwas



Spoiler: enigma





```
import sys

ALPHABET = [chr(x) for x in range(0x41,0x41+26)]
X1= ('B','D','F','H','J','L','C','P','R','T','X','V','Z','N','Y','E','I','W','G','A','K','M','U','S','Q','O')
X2= ('A','J','D','K','S','I','R','U','X','B','L','H','W','T','M','C','Q','G','Z','N','P','Y','F','V','O','E')
X3= ('E','K','M','F','L','G','D','Q','V','Z','N','T','O','W','Y','H','X','U','S','P','A','I','B','R','C','J')
XU= ('Y','R','U','H','Q','S','L','D','P','X','N','G','O','K','M','I','E','B','F','Z','C','W','V','J','A','T')
E = 'BGLRAOGHKRWRGSKCNSJAXXUUEXNSRXQUDXOSZHNIWLUVKXIPJSNJTM'
to_dict = lambda x: {chr(k+0x41):v for k,v in enumerate(x)}
# key for value
kfv = lambda d,x : [y for y,z in d.items() if z==x][0]
# encryptbreak
e = lambda x, w1, w2, w3: kfv(w1,kfv(w2, kfv(w3,U[w3[w2[w1[x]]]])))
# predecessor
p = lambda x : ALPHABET[((ord(x)-0x41-1)+26)%26]
# successor
s = lambda x : ALPHABET[((ord(x)-0x41+1)+26)%26]
# rotate back
rb = lambda x : { p(k): p(v) for k,v in x.items() }
# rotate forward
rf = lambda x : { s(k): s(v) for k,v in x.items() }

ow1 = to_dict(X1)
ow2 = to_dict(X2)
ow3 = to_dict(X3)
ou = to_dict(XU)

W1 = to_dict(X1)
W2 = to_dict(X2)
W3 = to_dict(X3)
U = to_dict(XU)

def encrypt(text, a=1, b=21, c=21*26, fw=False):
    to_return = ''
    counter_0 = 0
    w1 = to_dict(X1)
    w2 = to_dict(X2)
    w3 = to_dict(X3)
    for i in text:
        to_return += e(i,w1,w2,w3)
        counter_0 += 1
        if counter_0 % a == 0:
            w1 = rb(w1)

        if (counter_0) % b == 0:
            w2 = rb(w2)

        if counter_0 % c == 0:
            w3 = rb(w3)
    return to_return

def check(w1, w2, w3):
    return e(E[0], w1, w2, w3)+e(E[1], w1, w2, w3)+e(E[2], w1, w2, w3)+e(E[3], w1, w2, w3)+e(E[4], w1, w2, w3)+e(E[5], w1, w2, w3) == 'WETTER'

def bruteforce(a, b, c, forward=False):
    """
    Rotiert W1(w1) nach jeder a. Eingabe
    Rotiert W2(w2) nach jeder b. Eingabe
    Rotiert W3(w3) nach jeder c. Eingabe

    und
    Rotiert W1(v1) nach jeder c. Eingabe
    Rotiert W2(v2) nach jeder b. Eingabe
    Rotiert W3(v3) nach jeder a. Eingabe

    Beendet sich wenn alle Walzen mindestens einmal bewegt wurden und wieder in Grundstellung stehen.
    """
    w1 = to_dict(X1)
    w2 = to_dict(X2)
    w3 = to_dict(X3)
    v1 = to_dict(X1)
    v2 = to_dict(X2)
    v3 = to_dict(X3)      
    counter_0 = 0
    w1_rotated = False
    w2_rotated = False
    w3_rotated = False
    while True:
        if check(w1, w2, w3) or check(v1,v2,v3):
            for l in E:
                D += e(l, w1, w2, w3)
            print(D)
            sys.exit()
        counter_0 += 1
        if counter_0 % a == 0:
            w1 = rb(w1)
            w1_rotated = True
            if forward:
                v3 = rf(v3)
            else:
                v3 = rb(v3)

        if (counter_0) % b == 0:
            w2 = rb(w2)
            w2_rotated = True
            v2 = rb(v2)

        if counter_0 % c == 0:
            if forward:
                w3 = rf(w3)
            else:
                w3 = rb(w3)
            w3_rotated = True
            v1 = rb(v1)


        if w1_rotated and w2_rotated and w3_rotated and w1 == ow1 and w2 == ow2 and w3 == ow3:
            print(counter_0)
            break


def bruteforce_4():
    """
    Rotiert w1 nach jeder i. Eingabe
    Rotiert v1 nach jeder j. Eingabe

    Rotiert w2 nach jeder 21. Eingabe
    Rotiert v2 nach jeder 21. Eingabe

    Rotiert w3 nach jeder j. Eingabe
    Rotiert v3 nach jeder i. Eingabe
    """
    for i in range(1,27):
        for j in range(1,27):
            print(i, j)
            bruteforce(i, 21, j)
            bruteforce(i, 21, j, True)

def bruteforce_5():
    """
    Rotiert w1 nach jeder i. Eingabe
    Rotiert v1 nach jeder j. Rotation von v2

    Rotiert w2 nach jeder 21. Eingabe
    Rotiert v2 nach jeder 21. Eingabe

    Rotiert w3 nach jeder j. Rotation von w2
    Rotiert v3 nach jeder i. Eingabe
    """
    for i in range(1,27):
        for j in range(1,27):
            print(i, j)
            bruteforce(i, 21, 21*j)
            bruteforce(i, 21, 21*j, True)

def start():
    g = globals()
    for k,v in g.items():
        if k.startswith('bruteforce_'):
            print(k)
            v()

print(encrypt('WETTERBERICHT'))
start()
```


----------



## ikosaeder (13. November 2019)

Ich habe mich auch mal daran versucht.
Auf Basis von dem was die echte Enigma macht, bin ich von folgendem Ausgegangen.
Für die Nullstellung gilt:
Walze 1 rotiert bei jeder Eingabe
Walze 2 rotiert bei jeder 26 Eingabe  (Walze 1 hat eine vollständige Umdrehung gemacht)
Walze 3 rotier bei jeder 26*26 Eingabe (Walze 2 hat eine vollständige Umdrehung gemacht)
Alle 3 Walzen können mit einem Offset versehen werden. D.h. die Walze wird bereit rotiert eingebaut.
Für den vorliegenden Fall scheint der Offset von Walze1 4 zu sein -> wenn sie noch 22 mal rotiert, dann rotiert Walze 2.
Entsprechendes habe ich in meiner Enigma gecodet. Die kann zwar Klartext vor und zurück übersetzen (mit verschiedenen Ausgangstellungen und verschiedenen Rotationsrichtungen. 
Für den Teststring gibt es aber trotzdem kein Ergebnis.
Entweder stimmt die Annahme nicht oder die Offset sind noch nicht richtig.


Spoiler





```
import sys
def rotate(walzeIn,r=False):
    if(r):
        walzeIn.insert(25, walzeIn.pop(0))
    else:
        walzeIn.insert(0,walzeIn.pop())
    return walzeIn


def encrypt(plainText,X1E,X2E,X3E,XUE,offset1,offset2,offset3,r=False):
    count1=offset1
    count2=offset2
    count3=offset3
    for i in range(count1):
        if count1==0:
            break
        rotate(X1E,r)
    for i in range(count2):
        if count2==0:
            break
        rotate(X2E,r)
    for i in range(count3):
        if count3==0:
            break
        rotate(X3E, r)
    encryptedText=""
    for i in plainText:
        letter=i
        chiffre = ALPHABET.index(letter)
        letter = X1E[chiffre]
        chiffre = ALPHABET.index(letter)
        letter = X2E[chiffre]
        chiffre = ALPHABET.index(letter)
        letter = X3E[chiffre]
        chiffre = ALPHABET.index(letter)
        letter = XUE[chiffre]
        chiffre = ALPHABET.index(letter)
        letter = X3E[chiffre]
        chiffre = ALPHABET.index(letter)
        letter = X2E[chiffre]
        chiffre = ALPHABET.index(letter)
        letter = X1E[chiffre]
        rotate(X1E,r)
        count1 += 1
        if(count1==25):
             rotate(X2E,r)
             count2 += 1
             count1=0
        if(count2==25):
             rotate(X3E,r)
             count3 += 1
             count2 = 0
        if(count3==25):
             count3=0
        encryptedText+=letter
    return encryptedText

def decrypt(encryptedText,X1D,X2D,X3D,XUD,offset1,offset2,offset3,r=False):
    count1=offset1
    count2=offset2
    count3=offset3
    for i in range(count1):
        if count1==0:
            break
        rotate(X1D,r)
    for i in range(count2):
        if count2==0:
            break
        rotate(X2D,r)
    for i in range(count3):
        if count3==0:
            break
        rotate(X3D, r)
    plainText=""
    for i in encryptedText:
        letter=i
        chiffre = X1D.index(letter)
        letter = ALPHABET[chiffre]
        chiffre = X2D.index(letter)
        letter = ALPHABET[chiffre]
        chiffre = X3D.index(letter)
        letter = ALPHABET[chiffre]
        chiffre = XUD.index(letter)
        letter = ALPHABET[chiffre]
        chiffre = X3D.index(letter)
        letter = ALPHABET[chiffre]
        chiffre = X2D.index(letter)
        letter = ALPHABET[chiffre]
        chiffre = X1D.index(letter)
        letter = ALPHABET[chiffre]
        rotate(X1D,r)
        count1 += 1
        if (count1 == 25):
            rotate(X2D,r)
            count2 += 1
            count1 = 0
        if (count2 == 25):
            rotate(X3D,r)
            count3 += 1
            count2 = 0
        if (count3 == 25):
            count3 = 0
        plainText+=letter
    return plainText

if __name__ == '__main__':

    ALPHABET = [chr(x) for x in range(0x41, 0x41 + 26)]
    ####['0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5']
    X1 = ['B', 'D', 'F', 'H', 'J', 'L', 'C', 'P', 'R', 'T', 'X', 'V', 'Z', 'N', 'Y', 'E', 'I', 'W', 'G', 'A', 'K', 'M',
          'U', 'S', 'Q', 'O']
    ####['0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5']
    X2 = ['A', 'J', 'D', 'K', 'S', 'I', 'R', 'U', 'X', 'B', 'L', 'H', 'W', 'T', 'M', 'C', 'Q', 'G', 'Z', 'N', 'P', 'Y',
          'F', 'V', 'O', 'E']
    ####['0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5']
    X3 = ['E', 'K', 'M', 'F', 'L', 'G', 'D', 'Q', 'V', 'Z', 'N', 'T', 'O', 'W', 'Y', 'H', 'X', 'U', 'S', 'P', 'A', 'I',
          'B', 'R', 'C', 'J']
    ####['0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5']
    XU = (
    'Y', 'R', 'U', 'H', 'Q', 'S', 'L', 'D', 'P', 'X', 'N', 'G', 'O', 'K', 'M', 'I', 'E', 'B', 'F', 'Z', 'C', 'W', 'V',
    'J', 'A', 'T')
    # E = 'BGLRAOGHKRWRGSKCNSJAXXUUEXNSRXQUDXOSZHNIWLUVKXIPJSNJTM'
    kryptText = "BGLRAOGHKRWRGSKCNSJAXXUUEXNSRXQUDXOSZHNIWLUVKXIPJSNJTM"
    #kryptText = "RFVRQLTOEHZSFASDFASDFASDFSADFSADFSADFSDFSADFSADF"
    klarText = "WETTERBERICHT"
    # klarText="RFVRQLTOEHZSF"
    count1=0
    count2=0
    count3=0

    X1E=list(X1)
    X2E=list(X2)
    X3E=list(X3)
    XUE=list(XU)
    dekrypto=""
    krypto=""

    #kryptText=encrypt(klarText,X1E,X2E,X3E,XUE,count1,count2,count3,True)
    print kryptText
    #dekrypto=decrypt(kryptText,X1D,X2D,X3D,XUD,count1,count2,count3,False)
    #print dekrypto
    #print "orig", X1D
    #for i in range(26):
        #rotate(X1D,True)
        #print i,X1D

    for a in range(27):
        for j in range(27):
            for k in range(27):
                X1D = list(X1)
                X2D = list(X2)
                X3D = list(X3)
                XUD = list(XU)
                dekrypto = decrypt(kryptText,X1D,X2D,X3D,XUD,k,j,a,True)
                print k,j,a
                print dekrypto
                if ("WETTER" in dekrypto):
                    print dekrypto
                    print ('Walze 1: ' + str(k) + " Walze 2: " + str(j) + " Walze 3: " + str(a))
                    sys.exit(0)
```


----------



## StormChaser (13. November 2019)

> Alle 3 Walzen können mit einem Offset versehen werden. D.h. die Walze wird bereit rotiert eingebaut.


Die 4. Walze ebenfalls. Sie rotiert zwar nicht, könnte aber trotzdem "verdreht" eingebaut sein.


Was mich in der Aufgabenstellung ausserdem stutzig gemacht hatte war in diesem Satz 





> Sie dürfen außerdem als bekannt voraussetzen, dass Walze ¨ 2 in der unten angegebenen Grundstellung zum ersten Mal *unmittelbar vor der zweiundzwanzigsten Eingabe* rotiert.


 die hervorgehobene Formulierung.
Wenn dieses "vor" nun für alle Walzen gilt, und die 1. Walze* unmittelbar vor* der ersten Eingabe rotiert, dürften ganz andere Ergebnisse herauskommen.

Das erste  'B' im Chiffrat kann nur erzeugt werden, wenn die Rotation der ersten Walze einen bestimmten Wert hat, da bei Rotation 0 (Grundeinstellung) das 'B' nicht aus der Eingabe 'W' zu erzeugen ist. Die Walze muss also bereits so versetzt eingebaut sein.
Dann schliesst sich die Frage an, ob die Schritte für die weiteren Rotationen ab 0 oder ab dem Versatz gezaehlt werden.
Und falls unmittelbar _vor_ der Eingabe rotiert wird, wäre der Versatz 1 weniger.


----------



## zerix (13. November 2019)

ikosaeder hat gesagt.:


> Für den vorliegenden Fall scheint der Offset von Walze1 4 zu sein -> wenn sie noch 22 mal rotiert, dann rotiert Walze 2.



Das Offset wäre 5 und nicht 4, da vor der 22. Eingabe rotiert wird, d.h. nach der 21. Eingabe. Das hatte ich auch schon mal bedacht, hat aber nicht geholfen.

Viele Grüße
Sascha


----------



## ikosaeder (13. November 2019)

Also ich habe jetzt auch die 4 Walze rotiert (in der Ausgangsstellung) und trotzdem keinen Erfolg gehabt. Meine Enigma verschlüsselt und entschlüsselt und gibt die korrekte Ausgangsstellung der Walzen wieder.
Ich denke für die Lösung fehlt eine Information oder ein anderes Detail.
@*javama Hast du noch mehr Infos? Woher kommt die Aufgabe? *


----------



## StormChaser (21. November 2019)

Da ich schon so einiges erfolglos probiert hatte und bei neuen Versuchen inzwischen schon nicht mehr genau weiss, was ich hatte und was nicht, habe ich mal eine Aufstellung gemacht von dem, was ich für denkbar halte. Diese Aufstellung lässt sich dann übersichtlicher abarbeiten.

Ohne Einschraenkungen betraegt die Anzahl moeglicher Setups vor dem De-/Chiffrieren:
26 ^ 7 = 8.031.810.176
Durch die Einschraenkungen I. b) und I. c) reduziert sich das auf:
26 ^ 5 = 11.881.376‬ ( = 0,1479 % )

I. Vorbedingungen
a) Grundstellung (Versatz = 0 bzw keine Rotation) aller Walzen siehe Post
b) Walze 1 rotiert nach (oder vor) jeder Eingabe
c) Walze 2 rotiert unmittelbar vor 22. Eingabe
d) Walze 4 rotiert nicht
e) Chiffrat + Teil-Dechiffrat siehe Post

II. Moeglichkeiten (fuer Setups und Verarbeitung)
A.
[0] Rotationen erfolgen in Abhaengigkeit der Anzahl der Rotationen der Vorgaenger-Walze
[1] Rotationen erfolgen in Abhaengigkeit der Anzahl der Eingaben

B.
[0] bei versetzten Walzen beginnt Eingabezaehler bei 0
[1] bei versetzten Walzen beginnt Eingabezaehler bei Versatz Modulo Rotierlimit der Walze

C.
[0] Rotierrichtung aller Walzen vorwaerts
[1] Rotierrichtung aller Walzen rueckwaerts

D.
[0] Eingabezaehler erhoehen und ggfs. Walze rotieren NACH Verarbeitung des von aussen kommenden Zeichens
[1] Eingabezaehler erhoehen und ggfs. Walze rotieren VOR Verarbeitung des von aussen kommenden Zeichens

E.
[0] Eingabezaehlererhoehung nur vor dem Passieren der Walze 4
[1] Eingabezaehlererhoehung auch nach dem Passieren der Walze 4


Aus A - E sich ergebende Kombinationsmoeglichkeiten:

1:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Rotationen der Vorgaenger-Walze ("Kilometerzaehler")
- bei versetzten Walzen beginnt Eingabezaehler bei 0
- Rotierrichtung aller Walzen vorwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren NACH Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung nur vor dem Passieren der Walze 4

2:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Rotationen der Vorgaenger-Walze ("Kilometerzaehler")
- bei versetzten Walzen beginnt Eingabezaehler bei 0
- Rotierrichtung aller Walzen vorwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren NACH Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung auch nach dem Passieren der Walze 4

3:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Rotationen der Vorgaenger-Walze ("Kilometerzaehler")
- bei versetzten Walzen beginnt Eingabezaehler bei 0
- Rotierrichtung aller Walzen vorwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren VOR Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung nur vor dem Passieren der Walze 4

4:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Rotationen der Vorgaenger-Walze ("Kilometerzaehler")
- bei versetzten Walzen beginnt Eingabezaehler bei 0
- Rotierrichtung aller Walzen vorwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren VOR Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung auch nach dem Passieren der Walze 4

5:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Rotationen der Vorgaenger-Walze ("Kilometerzaehler")
- bei versetzten Walzen beginnt Eingabezaehler bei 0
- Rotierrichtung aller Walzen rueckwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren NACH Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung nur vor dem Passieren der Walze 4

6:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Rotationen der Vorgaenger-Walze ("Kilometerzaehler")
- bei versetzten Walzen beginnt Eingabezaehler bei 0
- Rotierrichtung aller Walzen rueckwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren NACH Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung auch nach dem Passieren der Walze 4

7:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Rotationen der Vorgaenger-Walze ("Kilometerzaehler")
- bei versetzten Walzen beginnt Eingabezaehler bei 0
- Rotierrichtung aller Walzen rueckwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren VOR Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung nur vor dem Passieren der Walze 4

8:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Rotationen der Vorgaenger-Walze ("Kilometerzaehler")
- bei versetzten Walzen beginnt Eingabezaehler bei 0
- Rotierrichtung aller Walzen rueckwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren VOR Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung auch nach dem Passieren der Walze 4

9:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Rotationen der Vorgaenger-Walze ("Kilometerzaehler")
- bei versetzten Walzen beginnt Eingabezaehler bei Versatz Modulo Rotierlimit der Walze
- Rotierrichtung aller Walzen vorwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren NACH Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung nur vor dem Passieren der Walze 4

10:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Rotationen der Vorgaenger-Walze ("Kilometerzaehler")
- bei versetzten Walzen beginnt Eingabezaehler bei Versatz Modulo Rotierlimit der Walze
- Rotierrichtung aller Walzen vorwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren NACH Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung auch nach dem Passieren der Walze 4

11:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Rotationen der Vorgaenger-Walze ("Kilometerzaehler")
- bei versetzten Walzen beginnt Eingabezaehler bei Versatz Modulo Rotierlimit der Walze
- Rotierrichtung aller Walzen vorwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren VOR Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung nur vor dem Passieren der Walze 4

12:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Rotationen der Vorgaenger-Walze ("Kilometerzaehler")
- bei versetzten Walzen beginnt Eingabezaehler bei Versatz Modulo Rotierlimit der Walze
- Rotierrichtung aller Walzen vorwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren VOR Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung auch nach dem Passieren der Walze 4

13:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Rotationen der Vorgaenger-Walze ("Kilometerzaehler")
- bei versetzten Walzen beginnt Eingabezaehler bei Versatz Modulo Rotierlimit der Walze
- Rotierrichtung aller Walzen rueckwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren NACH Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung nur vor dem Passieren der Walze 4

14:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Rotationen der Vorgaenger-Walze ("Kilometerzaehler")
- bei versetzten Walzen beginnt Eingabezaehler bei Versatz Modulo Rotierlimit der Walze
- Rotierrichtung aller Walzen rueckwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren NACH Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung auch nach dem Passieren der Walze 4

15:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Rotationen der Vorgaenger-Walze ("Kilometerzaehler")
- bei versetzten Walzen beginnt Eingabezaehler bei Versatz Modulo Rotierlimit der Walze
- Rotierrichtung aller Walzen rueckwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren VOR Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung nur vor dem Passieren der Walze 4

16:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Rotationen der Vorgaenger-Walze ("Kilometerzaehler")
- bei versetzten Walzen beginnt Eingabezaehler bei Versatz Modulo Rotierlimit der Walze
- Rotierrichtung aller Walzen rueckwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren VOR Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung auch nach dem Passieren der Walze 4

17:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Eingaben
- bei versetzten Walzen beginnt Eingabezaehler bei 0
- Rotierrichtung aller Walzen vorwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren NACH Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung nur vor dem Passieren der Walze 4

18:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Eingaben
- bei versetzten Walzen beginnt Eingabezaehler bei 0
- Rotierrichtung aller Walzen vorwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren NACH Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung auch nach dem Passieren der Walze 4

19:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Eingaben
- bei versetzten Walzen beginnt Eingabezaehler bei 0
- Rotierrichtung aller Walzen vorwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren VOR Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung nur vor dem Passieren der Walze 4

20:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Eingaben
- bei versetzten Walzen beginnt Eingabezaehler bei 0
- Rotierrichtung aller Walzen vorwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren VOR Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung auch nach dem Passieren der Walze 4

21:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Eingaben
- bei versetzten Walzen beginnt Eingabezaehler bei 0
- Rotierrichtung aller Walzen rueckwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren NACH Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung nur vor dem Passieren der Walze 4

22:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Eingaben
- bei versetzten Walzen beginnt Eingabezaehler bei 0
- Rotierrichtung aller Walzen rueckwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren NACH Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung auch nach dem Passieren der Walze 4

23:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Eingaben
- bei versetzten Walzen beginnt Eingabezaehler bei 0
- Rotierrichtung aller Walzen rueckwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren VOR Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung nur vor dem Passieren der Walze 4

24:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Eingaben
- bei versetzten Walzen beginnt Eingabezaehler bei 0
- Rotierrichtung aller Walzen rueckwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren VOR Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung auch nach dem Passieren der Walze 4

25:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Eingaben
- bei versetzten Walzen beginnt Eingabezaehler bei Versatz Modulo Rotierlimit der Walze
- Rotierrichtung aller Walzen vorwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren NACH Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung nur vor dem Passieren der Walze 4

26:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Eingaben
- bei versetzten Walzen beginnt Eingabezaehler bei Versatz Modulo Rotierlimit der Walze
- Rotierrichtung aller Walzen vorwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren NACH Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung auch nach dem Passieren der Walze 4

27:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Eingaben
- bei versetzten Walzen beginnt Eingabezaehler bei Versatz Modulo Rotierlimit der Walze
- Rotierrichtung aller Walzen vorwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren VOR Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung nur vor dem Passieren der Walze 4

28:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Eingaben
- bei versetzten Walzen beginnt Eingabezaehler bei Versatz Modulo Rotierlimit der Walze
- Rotierrichtung aller Walzen vorwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren VOR Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung auch nach dem Passieren der Walze 4

29:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Eingaben
- bei versetzten Walzen beginnt Eingabezaehler bei Versatz Modulo Rotierlimit der Walze
- Rotierrichtung aller Walzen rueckwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren NACH Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung nur vor dem Passieren der Walze 4

30:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Eingaben
- bei versetzten Walzen beginnt Eingabezaehler bei Versatz Modulo Rotierlimit der Walze
- Rotierrichtung aller Walzen rueckwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren NACH Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung auch nach dem Passieren der Walze 4

31:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Eingaben
- bei versetzten Walzen beginnt Eingabezaehler bei Versatz Modulo Rotierlimit der Walze
- Rotierrichtung aller Walzen rueckwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren VOR Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung nur vor dem Passieren der Walze 4

32:
- Rotationen erfolgen in Abhaengigkeit der Anzahl der Eingaben
- bei versetzten Walzen beginnt Eingabezaehler bei Versatz Modulo Rotierlimit der Walze
- Rotierrichtung aller Walzen rueckwaerts
- Eingabezaehler erhoehen und ggfs. Walze rotieren VOR Verarbeitung des von aussen kommenden Zeichens
- Eingabezaehlererhoehung auch nach dem Passieren der Walze 4


----------



## Technipion (21. November 2019)

StormChaser hat gesagt.:


> ...


Alter.

Verdammt, jetzt muss ich mich auch nochmal daran setzen...


----------



## ikosaeder (21. November 2019)

Vielleicht habe ich es überlesen, aber mein letzter Gedanke war, das es 2 Arten von Versatz gibt. 
1. Die Walze wird verdreht eingesetzt, was einer Anzahl von X Rotationen vor der ersten Eingabe entspricht
2. Der Haken, der die Rotation der nächsten Walze steuert ist variable an der Walze angebracht.
Das würde bedeuten, das es zu B eine dritte Variante gibt.


----------



## StormChaser (21. November 2019)

Fall 1: Versatzzähler 0
Stellt man sich eine Walze als einen Ring vor, auf dem 26 Löcher angebracht sind, die zur Aufnahmen von "Haken" oder "Stiften" dienen, kann ein Haken/Stift an jeder beliebigen Position angebracht werden. Zieht man den Stift heraus, dreht die Walze (z. B. Versatz 8) und steckt den Stift wieder rein, wäre der Versatz 8, aber der Zähler bei 0, denn erst nach 26 Rotationen wäre der Stift wieder an derselben Stelle.

Fall 2: Versatzzähler = Versatz
Wie in Fall 1, doch man zieht den Stift nicht heraus, sondern dreht die Walze mitsamt Stift. Bei Versatz 8 müsste der Eingabezaehler auch auf 8 gestellt werden.

Soll z. B. bei jeder 2. Eingabe die nächste Walze rotiert werden, müsste die aktuelle Walze 13 Stifte erhalten.

Als neue Varianten wären dann hinzuzunehmen, wieviele Stifte und an welchen Positionen. Nach dem ich mir das als Datas aufgeschrieben hatte, habe ich das aber erstmal verworfen, weil das mMn mit Haushaltsmittteln nicht mehr in vernünftiger Zeit zu bruteforcen ist:

;Stifte
;db '--- STIFTE ---'
;s1: db 255, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;s2: db 255, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;s3: db 255, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;s4: db 255, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0


----------



## ikosaeder (21. November 2019)

Die meisten Enigmas hatten 1 Stift pro Walze. Wenn der Stift der 1. Walze in der Grundstellung bei 4 (notch) ist und die  und die Walze um 8 (offset) verdreht wird, ist der Versatz bei den Buchstaben 8, die erste Rotation der 2. Walze findet aber bei 14 (26-8 -4) statt. Also die Rotation ist damit (Rot W1-notch -offset)%26.


----------



## StormChaser (21. November 2019)

Ich denke, ich verstehe jetzt, was Du mit der dritten Möglichkeit gemeint hast.

Ab der 2. Rotation werden die Walzen (bei Schaltung als "Kilometerzähler") bei 1 Stift nur alle 26 Rotationen der Vorgängerwalze rotiert.

Wie sich die erste Rotation aus deinem Beispiel auswirkt, müsste ich erstmal ausprobieren, fehlt mir momentan die Vorstellungskraft.


----------



## ikosaeder (21. November 2019)

Hier mal meine aktuelle Version:


Spoiler: Enigma





```
#!python
import sys


def rotate(walzeIn):
    walzeIn.insert(0, walzeIn.pop())
    return walzeIn


def encrypt(plainText, X1E, X2E, X3E, XUE, offset1, offset2, offset3,offset4,notch1,notch2, r=False):
    count1 = notch1
    count2 = notch2
    count3 = 0
    if r:
        X1E.reverse()
        X2E.reverse()
        X3E.reverse()

    for i in range(offset1):
        if offset1 == 0:
            break
        rotate(X1E)

    for i in range(offset2):
        if offset2 == 0:
            break
        rotate(X2E)

    for i in range(offset3):
        if offset3 == 0:
            break
        rotate(X3E)
    for i in range(offset4):
        if offset4 == 0:
            break
        rotate(XUE)

    encryptedText = ""
    for i in plainText:
        count1 += 1
        rotate(X1E)
        if (count1 == 25):
            rotate(X2E)
            count2 += 1
            count1 = 0
        if (count2 == 25):
            rotate(X3E)
            count3 += 1
            count2 = 0
        if (count3 == 25):
            count3 = 0
        letter = i
        chiffre = ALPHABET.index(letter)
        letter = X1E[chiffre]
        chiffre = ALPHABET.index(letter)
        letter = X2E[chiffre]
        chiffre = ALPHABET.index(letter)
        letter = X3E[chiffre]
        chiffre = ALPHABET.index(letter)
        letter = XUE[chiffre]
        chiffre = ALPHABET.index(letter)
        letter = X3E[chiffre]
        chiffre = ALPHABET.index(letter)
        letter = X2E[chiffre]
        chiffre = ALPHABET.index(letter)
        letter = X1E[chiffre]

        encryptedText += letter

    return encryptedText


def decrypt(encryptedText, X1D, X2D, X3D, XUD, offset1, offset2, offset3,offset4,notch1,notch2, r=False):
    count1 = notch1
    count2 = notch2
    count3 = 0
    if r:
        X1D.reverse()
        X2D.reverse()
        X3D.reverse()

    for i in range(offset1):
        if offset1 == 0:
            break
        rotate(X1D)

    for i in range(offset2):
        if offset2 == 0:
            break
        rotate(X2D)

    for i in range(offset3):
        if offset3 == 0:
            break
        rotate(X3D)
    for i in range(offset4):
        if offset4 == 0:
            break
        rotate(XUD)

    plainText = ""

    for i in encryptedText:
        count1 += 1
        rotate(X1D)
        if (count1 == 25):
            rotate(X2D)
            count2 += 1
            count1 = 0
        if (count2 == 25):
            rotate(X3D)
            count3 += 1
            count2 = 0
        if (count3 == 25):
            count3 = 0
        letter = i
        chiffre = X1D.index(letter)
        letter = ALPHABET[chiffre]
        chiffre = X2D.index(letter)
        letter = ALPHABET[chiffre]
        chiffre = X3D.index(letter)
        letter = ALPHABET[chiffre]
        chiffre = XUD.index(letter)
        letter = ALPHABET[chiffre]
        chiffre = X3D.index(letter)
        letter = ALPHABET[chiffre]
        chiffre = X2D.index(letter)
        letter = ALPHABET[chiffre]
        chiffre = X1D.index(letter)
        letter = ALPHABET[chiffre]
        plainText += letter

    return plainText


if __name__ == '__main__':

    ALPHABET = [chr(x) for x in range(0x41, 0x41 + 26)]

    ####['0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5']

    X1 = ['B', 'D', 'F', 'H', 'J', 'L', 'C', 'P', 'R', 'T', 'X', 'V', 'Z', 'N', 'Y', 'E', 'I', 'W', 'G', 'A', 'K', 'M','U', 'S', 'Q', 'O']

    ####['0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5']

    X2 = ['A', 'J', 'D', 'K', 'S', 'I', 'R', 'U', 'X', 'B', 'L', 'H', 'W', 'T', 'M', 'C', 'Q', 'G', 'Z', 'N', 'P', 'Y','F', 'V', 'O', 'E']

    ####['0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5']

    X3 = ['E', 'K', 'M', 'F', 'L', 'G', 'D', 'Q', 'V', 'Z', 'N', 'T', 'O', 'W', 'Y', 'H', 'X', 'U', 'S', 'P', 'A', 'I','B', 'R', 'C', 'J']

    ####['0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5']

    XU = ['Y', 'R', 'U', 'H', 'Q', 'S', 'L', 'D', 'P', 'X', 'N', 'G', 'O', 'K', 'M', 'I', 'E', 'B', 'F', 'Z', 'C', 'W','V','J', 'A', 'T']

    # E = 'BGLRAOGHKRWRGSKCNSJAXXUUEXNSRXQUDXOSZHNIWLUVKXIPJSNJTM'

    kryptText = "BGLRAOGHKRWRGSKCNSJAXXUUEXNSRXQUDXOSZHNIWLUVKXIPJSNJTM"

    # kryptText = "RFVRQLTOEHZSFASDFASDFASDFSADFSADFSADFSDFSADFSADF"

    klarText = "WETTERBERICHT"

    # klarText="RFVRQLTOEHZSF"

    offset1 = 0
    offset2 = 3
    offset3 = 0
    offset4 = 0
    notch1=2
    notch2=2
    X1E = list(X1)
    X2E = list(X2)
    X3E = list(X3)
    XUE = list(XU)
    dekrypto = ""
    krypto = ""

    #kryptText=encrypt(klarText,X1E,X2E,X3E,XUE,offset1,offset2,offset3,offset4,notch1,notch2,True)
    print kryptText
    # dekrypto=decrypt(kryptText,X1D,X2D,X3D,XUD,count1,count2,count3,False)
    # print dekrypto
    # print "orig", X1D
    # for i in range(26):
    # rotate(X1D,True)

    # print i,X1D

    for a in range(26):
        for j in range(26):
            for k in range(26):
                for l in range(26):
                    for m in range(26):
                        for n in range(26):
                            X1D = list(X1)
                            X2D = list(X2)
                            X3D = list(X3)
                            XUD = list(XU)
                            dekrypto = decrypt(kryptText, X1D, X2D, X3D, XUD, k, j, a,l,n,m, True)
                            #print k, j, a
                            #print dekrypto
                            if ("WETTER" in dekrypto):
                                print dekrypto
                                print ('Walze 1: ' + str(k) + " Walze 2: " + str(j) + " Walze 3: " + str(a)+ " Walze 4: " + str(l))
                                print ('Notch 1: '+str(n), 'Notch 2: '+str(m))
                                sys.exit(0)
    print ("Krypto not cracked")
```


----------



## StormChaser (22. November 2019)

Zu den Rotationen habe ich mal ein kleines Tool erstellt und die einzelnen Rotationen aller Walzen in einem kurzen Video aufgenommen. Für Vergleichszwecke hoffentlich hilfreich, denn mit den richtigen Rotationen steht und fällt ja jeder Dechiffrierungsversuch.


----------

