|
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
Execution
C:\> 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
|