M-209 Home Page
M-209 Workings Home Page
|
IntroductionThe following program emulates the operation of a M-209. It is written in Python. There are few comments, but his logic translates the mechanical or mathematical operations already studied.The Program# m209.py def letter2number( letter ): return "ABCDEFGHIJKLMNOPQRSTUVWXYZ".find( letter ) def number2letter( number ): return "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[ number ] def external2Number( wheel, letter ): return Wheels[ wheel ].find( letter ) def number2External( wheel, number ): return Wheels[ wheel ][ number % len( Wheels[wheel] ) ] def cipherOrDecipher( letter ): # 1. Convert Plain letter to Plain index P = letter2number( letter ) if DEBUG: print "%1s %2d " % (letter, P), # 2. Calculate Key K = 0 for aBar in range( len(Lugs) ): aBarShifted = False for aWheel in range(len(Wheels)): if Pins[aWheel][ activePins[aWheel] % len(Pins[aWheel]) ] * Lugs[aBar][aWheel] : aBarShifted = True if aBarShifted : K = K + 1 if DEBUG: for aWheel in range(len(Wheels)): print Pins[aWheel][ activePins[aWheel] % len(Pins[aWheel]) ], # 3. Cipher (or Decipher) C = (25 + K) - P C = C % 26 # 4. Convert Cipher index to Cipher letter letter = number2letter( C ) if DEBUG: print " %2d %2d " % (K, C), return letter def cipherOrDecipherBis( letter ): # 1. Convert Plain letter to Plain index P = letter2number( letter ) if DEBUG: print "%1s %2d " % (letter, P), # 2. Calculate Overlaps Overlaps = 0 for x in sorted( LugsXY.keys() ): indx1 = int( x[0] ) indx2 = int( x[1] ) if Pins[indx1][ activePins[indx1]%len(Pins[indx1])] * \ Pins[indx2][ activePins[indx2]%len(Pins[indx2])]: Overlaps += LugsXY[ x ] if DEBUG: for aWheel in range(len(Wheels)): print Pins[aWheel][ activePins[aWheel] % len(Pins[aWheel]) ], # 3. Calculate Key K = 0 for aWheel in range(len(Wheels)): K = K + Pins[aWheel][activePins[aWheel] % len(Pins[aWheel]) ]*LugsByWheel[aWheel] K = K - Overlaps # 4. Cipher (or Decipher) C = (25 + K) - P C = C % 26 # 5. Convert Cipher index to Cipher letter letter = number2letter( C ) if DEBUG: print " %2d %2d %2d " % (K,Overlaps,C), return letter def bars2lugsAndOverlaps(): for aWheel in range(len(Wheels)): LugsByWheel[ aWheel ] = 0 numberOfOverlaps = 0 for aBar in range(27): nbLugs = 0 for aWheel in range(len(Wheels)): if Lugs[aBar][aWheel]: LugsByWheel[aWheel] = LugsByWheel[aWheel] + 1 nbLugs = nbLugs + 1 if nbLugs > 1: numberOfOverlaps = numberOfOverlaps + 1 ndx = "" for aWheel in range(len(Wheels)): if Lugs[aBar][aWheel]: ndx = ndx + str(aWheel) if ndx in LugsXY: LugsXY[ ndx ] = LugsXY[ ndx ] + 1 else: LugsXY[ ndx ] = 1 # Internal Key (from TM 11-380, 1944) Pins = [ [1,1,0,1,0,0,0,1,1,0,1,0,1,1,0,0,0,0,1,1,0,1,1,0,0,0], [1,0,0,1,1,0,1,0,0,1,1,1,0,0,1,0,0,1,1,0,1,0,1,0,0], [1,1,0,0,0,0,1,1,0,1,0,1,1,1,0,0,0,1,1,1,1,0,1], [0,0,1,0,1,1,0,1,1,0,0,0,1,1,0,1,0,0,1,1,1], [0,1,0,1,1,1,0,1,1,0,0,0,1,1,0,1,0,0,1], [1,1,0,1,0,0,0,1,0,0,1,0,0,1,1,0,1] ] Lugs = [ [0,0,1,0,0,1], [0,1,0,0,0,0], [0,1,0,0,0,0], [0,0,0,0,0,1], [0,1,0,0,0,0], [0,1,0,0,1,0], [1,0,0,0,0,1], [0,1,0,0,0,0], [0,1,0,0,1,0], [1,0,0,0,1,0], [0,1,0,0,0,0], [0,0,0,0,1,0], [0,0,0,1,1,0], [0,1,0,0,0,0], [0,0,0,0,1,0], [0,0,0,1,0,0], [0,1,0,0,0,0], [0,0,0,0,1,0], [0,0,0,1,0,0], [0,1,0,0,0,0], [0,0,0,0,1,0], [0,0,0,1,0,0], [0,1,0,0,0,0], [0,0,0,0,1,0], [0,0,0,1,0,0], [0,1,0,0,0,0], [0,0,0,0,1,0], ] Wheels = [ "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "ABCDEFGHIJKLMNOPQRSTUVXYZ", "ABCDEFGHIJKLMNOPQRSTUVX", "ABCDEFGHIJKLMNOPQRSTU", "ABCDEFGHIJKLMNOPQRS", "ABCDEFGHIJKLMNOPQ" ] LugsByWheel = [ 0, 0, 0, 0, 0, 0 ] LugsXY = {} External2Internal = [ 15, 14, 13, 12, 11, 10 ] activePins = [ 0, 0, 0, 0, 0, 0 ] ExternalKey = "PEOPLE" DEBUG=True Plain_text = "ATTACKZATZDAWN" Cipher_text = "" # activePins for aWheel in range(len(Wheels)): activePins[aWheel] = External2Internal[aWheel] + external2Number( aWheel, ExternalKey[aWheel] ) # Cipher a text for letter in Plain_text: if DEBUG: for aWheel in range(len(Wheels)): print number2External( aWheel, (activePins[aWheel] - External2Internal[aWheel]) % len(Wheels[aWheel] ) ), print " : ", result = cipherOrDecipher( letter ) print result, if DEBUG: print Cipher_text = Cipher_text + result for aWheel in range(len(Wheels)): activePins[aWheel] = activePins[aWheel] + 1 print if DEBUG: for aWheel in range(len(Wheels)): print number2External( aWheel, (activePins[aWheel] - External2Internal[aWheel]) % len(Wheels[aWheel] ) ), print # Convert Lugs in LugsByWheel and Overlaps bars2lugsAndOverlaps() print LugsByWheel print LugsXY print # Decipher a text for aWheel in range(len(Wheels)): activePins[aWheel] = External2Internal[aWheel] + external2Number( aWheel, ExternalKey[aWheel] ) for letter in Cipher_text: if DEBUG: for aWheel in range(len(Wheels)): print number2External( aWheel, activePins[aWheel] ), print " : ", result = cipherOrDecipherBis( letter ) print result, if DEBUG: print for aWheel in range(len(Wheels)): activePins[aWheel] = activePins[aWheel] + 1 print ExecutionC:\> python m209.py P E O P L E : A 0 0 1 0 0 1 1 23 22 W Q F P Q M F : T 19 0 0 0 1 1 0 14 20 U R G Q R N G : T 19 0 1 1 1 1 1 27 7 H S H R S O H : A 0 1 0 1 0 0 1 4 3 D T I S T P I : C 2 1 1 0 0 1 1 23 20 U U J T U Q J : K 10 0 0 1 0 1 0 11 0 A V K U A R K : Z 25 1 0 0 1 0 1 9 9 J W L V B S L : A 0 0 1 1 1 0 0 18 17 R X M X C A M : T 19 1 0 1 0 0 0 3 9 J Y N A D B N : Z 25 1 0 1 1 1 0 16 16 Q Z O B E C O : D 3 0 1 0 0 1 1 23 19 T A P C F D P : A 0 0 1 0 0 0 0 12 11 L B Q D G E Q : W 22 0 0 0 1 1 0 14 17 R C R E H F A : N 13 0 1 1 1 0 1 20 6 G D S F I G B [2, 12, 1, 5, 10, 3] {'25': 1, '34': 1, '14': 2, '04': 1, '05': 1} E S E G D O : W 22 0 1 0 0 1 1 23 2 0 A F T F H E P : U 20 0 0 0 1 1 0 14 1 19 T G U G I F Q : H 7 0 1 1 1 1 1 27 4 19 T H V H J G A : D 3 1 0 1 0 0 1 4 2 0 A I X I K H B : U 20 1 1 0 0 1 1 23 4 2 C J Y J L I C : A 0 0 0 1 0 1 0 11 0 10 K K Z K M J D : J 9 1 0 0 1 0 1 9 1 25 Z L A L N K E : R 17 0 1 1 1 0 0 18 0 0 A M B M O L F : J 9 1 0 1 0 0 0 3 0 19 T N C N P M G : Q 16 1 0 1 1 1 0 16 2 25 Z O D O Q N H : T 19 0 1 0 0 1 1 23 2 3 D P E P R O I : L 11 0 1 0 0 0 0 12 0 0 A Q F Q S P J : R 17 0 0 0 1 1 0 14 1 22 W R G R T Q K : G 6 0 1 1 1 0 1 20 1 13 N |