Danke für die Bestätigung.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.
# 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()
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()
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)
Die 4. Walze ebenfalls. Sie rotiert zwar nicht, könnte aber trotzdem "verdreht" eingebaut sein.Alle 3 Walzen können mit einem Offset versehen werden. D.h. die Walze wird bereit rotiert eingebaut.
die hervorgehobene Formulierung.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.
Für den vorliegenden Fall scheint der Offset von Walze1 4 zu sein -> wenn sie noch 22 mal rotiert, dann rotiert Walze 2.
Alter.