Advertisement
ranisalt

Untitled

Feb 24th, 2015
405
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.03 KB | None | 0 0
  1. from builtins import KeyError
  2. import string
  3.  
  4.  
  5. class Steckerbrett:
  6.     def __init__(self, *args):
  7.         self.map = {}
  8.  
  9.         for arg in args:
  10.             if arg[0] in self.map or arg[1] in self.map:
  11.                 raise KeyError('Same letter used twice in plugboard')
  12.  
  13.             self.map[arg[0]] = arg[1]
  14.             self.map[arg[1]] = arg[0]
  15.  
  16.     def swap(self, letter):
  17.         if letter in self.map:
  18.             return self.map[letter]
  19.         return letter
  20.  
  21.  
  22. class Umkehrwalze:
  23.     def __init__(self, wiring):
  24.         self.wiring = wiring
  25.  
  26.     def encode(self, letter):
  27.         return self.wiring[string.ascii_uppercase.index(letter)]
  28.  
  29.  
  30. class Walzen:
  31.     def __init__(self, notch, wiring, offset='A'):
  32.         assert isinstance(notch, str)
  33.         assert isinstance(wiring, str)
  34.         assert len(wiring) == len(string.ascii_uppercase)
  35.  
  36.         self.notch = notch
  37.  
  38.         if isinstance(offset, str) and len(offset) == 1:
  39.             self.offset = string.ascii_uppercase.index(offset)
  40.         elif isinstance(offset, int) and 0 <= offset < len(wiring):
  41.             self.offset = offset
  42.         else:
  43.             raise ValueError('offset must be character or integer')
  44.  
  45.         self.wiring = wiring
  46.  
  47.     def encode(self, letter):
  48.         index = (string.ascii_uppercase.index(letter) + self.offset) % len(
  49.             self.wiring)
  50.  
  51.         letter = self.wiring[index]
  52.         return letter
  53.  
  54.     def encode_reverse(self, letter):
  55.         index = (self.wiring.index(letter) + self.offset) % len(
  56.             self.wiring)
  57.  
  58.         letter = string.ascii_uppercase[index]
  59.         return letter
  60.  
  61.  
  62. class Enigma:
  63.     def __init__(self, rotors, reflector, plugboard=None):
  64.         # Assert that plugboard is a Steckerbrett if not None
  65.         assert plugboard is None or isinstance(plugboard, Steckerbrett)
  66.  
  67.         # Assert that rotors is a tuple and each tuple element is a Walzen
  68.         assert isinstance(rotors, tuple)
  69.         for index in range(len(rotors)):
  70.             assert isinstance(rotors[index], Walzen)
  71.  
  72.         # Assert that reflector is an Umkehrwalze
  73.         assert isinstance(reflector, Umkehrwalze)
  74.  
  75.         self.plugboard = plugboard
  76.         self.rotors = rotors
  77.         self.reflector = reflector
  78.  
  79.     def cipher(self, message):
  80.         assert isinstance(message, str)
  81.  
  82.         message = message.upper()
  83.         ciphered = ''
  84.  
  85.         for letter in message:
  86.             if letter in string.ascii_uppercase:
  87.                 self._rotate()
  88.  
  89.                 if self.plugboard is not None:
  90.                     letter = self.plugboard.swap(letter)
  91.  
  92.                 for rotor in self.rotors:
  93.                     letter = rotor.encode(letter)
  94.  
  95.                 letter = self.reflector.encode(letter)
  96.  
  97.                 for rotor in self.rotors[::-1]:
  98.                     letter = rotor.encode_reverse(letter)
  99.  
  100.                 if self.plugboard is not None:
  101.                     letter = self.plugboard.swap(letter)
  102.  
  103.             ciphered += letter
  104.  
  105.         return ciphered
  106.  
  107.     def _rotate(self):
  108.         wiring = self.rotors[0].wiring
  109.         self.rotors[0].wiring = wiring[1:] + wiring[0]
  110.  
  111.         for index in range(len(self.rotors) - 1):
  112.             if self.rotors[index].notch == self.rotors[index].wiring[0]:
  113.                 if index == 1:
  114.                     wiring = self.rotors[index].wiring
  115.                     self.rotors[index].wiring = wiring[1:] + wiring[0]
  116.  
  117.                 wiring = self.rotors[index + 1].wiring
  118.                 self.rotors[index + 1].wiring = wiring[1:] + wiring[0]
  119.  
  120.  
  121.  
  122. if __name__ == '__main__':
  123.     plugboard = Steckerbrett('PO', 'ML', 'IU', 'KJ', 'NH', 'YT', 'GB', 'VF',
  124.                              'RE', 'DC')
  125.  
  126.     rotors = (
  127.         Walzen(wiring='EKMFLGDQVZNTOWYHXUSPAIBRCJ', notch='Q'),
  128.         Walzen(wiring='AJDKSIRUXBLHWTMCQGZNPYFVOE', notch='E'),
  129.         Walzen(wiring='BDFHJLCPRTXVZNYEIWGAKMUSQO', notch='V'),
  130.     )
  131.  
  132.     reflector = Umkehrwalze(wiring='YRUHQSLDPXNGOKMIEBFZCWVJAT')
  133.  
  134.     machine = Enigma(rotors=rotors, reflector=reflector)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement