Advertisement
JpRuEcIQedVCHB

Untitled

Dec 30th, 2024
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.64 KB | None | 0 0
  1. #!/usr/bin/python
  2. # -*- encoding: utf-8 -*-
  3. import secretpy.alphabets as al
  4.  
  5.  
  6. class Enigmini:
  7.     """
  8.    The Enigmini Cipher
  9.    """
  10.  
  11.     class Rotor:
  12.         def __init__(self, name, key, turnover, position=0, ringsetting=0):
  13.             self.name = name
  14.             self.position = position % 6
  15.             self.ring = ringsetting % 6
  16.             self.key = [int(c) - 1 for c in key]
  17.             self.next_rotor = None
  18.             self.turnover = turnover
  19.  
  20.         def encrypt_coordinate(self, c):
  21.             i = (c - self.position) % 6
  22.             e = (self.key[i] + self.position) % 6
  23.             #print(f"    rotor {self.name} encrypt {c} -> wiring[{c} + {self.position}] = {e}      wiring: {self.key}")
  24.             return e
  25.  
  26.         def inverse_encrypt(self, c):
  27.             i = (c - self.position) % 6
  28.             e = (self.key.index(i) + self.position) % 6
  29.             #print(f"    rotor {self.name} inv encrypt {c} -> {self.key.index(i)} + {self.position} = {e}")
  30.             return e
  31.  
  32.         def rotate(self):
  33.             if str(self.position + 1) in self.turnover:
  34.                 if self.next_rotor:
  35.                     self.next_rotor.rotate()
  36.             self.position = (self.position + 1) % 6
  37.  
  38.         def set_next_rotor(self, rotor):
  39.             self.next_rotor = rotor
  40.  
  41.         # end of class Rotor
  42.  
  43.     def encryptCoordinate(self, c, rotors, plugboard):
  44.         # see Errata, plugboard is only used in one direction in the Enigmini
  45.         # c = plugboard[c]
  46.  
  47.         # we go from right to left
  48.         for r in reversed(rotors):
  49.             c = r.encrypt_coordinate(c)
  50.  
  51.         it = iter(rotors)
  52.         next(it)  # omit reflector
  53.  
  54.         # and then go back
  55.         for r in it:
  56.             c = r.inverse_encrypt(c)
  57.  
  58.         c = plugboard[c]
  59.  
  60.         # rotate after send a char
  61.         rotors[-1].rotate()
  62.  
  63.         return c
  64.  
  65.  
  66.     def encrypt(self, text, key=None):
  67.         """
  68.        Encryption method
  69.  
  70.        :param text: Text to encrypt
  71.        :param key: Encryption key
  72.        :type text: string
  73.        :type key: dict
  74.        :return: encrypted text
  75.        :rtype: string
  76.        """
  77.         if not isinstance(key, dict):
  78.             key = {
  79.                 'square': '3Z9TWIR7E0XJUNLBSD6VK8GO1A5P4HFYCQM2', # JKP
  80.                 'reflector': 'JKP',
  81.                 'rotor_offsets': (2, 0), # Grundstellung
  82.                 'ring_offsets': (0, 0), # Ringstellung
  83.                 'rotor_order': ('JKP_II', 'JKP_I'),
  84.                 'steckers': []
  85.             }
  86.  
  87.         exist_rotors = {
  88.             'JKP_I':  {'wiring': '152346', 'overturn': '6'},
  89.             'JKP_II': {'wiring': '152643', 'overturn': '6'},
  90.             'KP_I':  {'wiring': '254613', 'overturn': '6'},
  91.             'KP_II': {'wiring': '315624', 'overturn': '6'}
  92.         }
  93.  
  94.         exist_reflectors = {
  95.             'JKP': '645231',
  96.             'KP': '546213'
  97.         }
  98.  
  99.         plugboard = [int(c) - 1 for c in '123456']
  100.         for s1, s2 in key['steckers']:
  101.             plugboard[s1 - 1] = s2 - 1
  102.             plugboard[s2 - 1] = s1 - 1
  103.  
  104.         # set reflector, it behaves as a rotor without rotation
  105.         rotors = [self.Rotor('reflector', exist_reflectors[key['reflector']], '', 0, 0)]
  106.  
  107.         # set other rotors
  108.         for i, ri in enumerate(key['rotor_order']):
  109.             r = exist_rotors[ri]
  110.             rotor = self.Rotor(ri, r['wiring'], r['overturn'], key['rotor_offsets'][i], key['ring_offsets'][i])
  111.             rotors.append(rotor)
  112.  
  113.         # connect rotors
  114.         for i in range(len(rotors) - 1, 1, -1):
  115.             rotors[i].set_next_rotor(rotors[i - 1])
  116.  
  117.         # puntuation
  118.         punctuation = "!.\",:? ;_'"
  119.         punct_replace = "1358620974"
  120.  
  121.         res = []
  122.         for nextChar in text:
  123.  
  124.  
  125.             if nextChar in punctuation:
  126.                 nextChar = punct_replace[punctuation.index(nextChar)]
  127.  
  128.             nextIndex = key['square'].index(nextChar)
  129.  
  130.             #print(f"encrypt {nextChar} ({nextIndex}): Y {nextIndex // 6}")
  131.             encY = self.encryptCoordinate(nextIndex // 6, rotors, plugboard)
  132.             #print(f"encrypt {nextChar} ({nextIndex}): X {nextIndex % 6}")
  133.             encX = self.encryptCoordinate(nextIndex % 6, rotors, plugboard)
  134.  
  135.             c = key['square'][encY * 6 + encX]
  136.             res.append(c)
  137.  
  138.         return "".join(res)
  139.  
  140.     def decrypt(self, text, key=None):
  141.         """
  142.        Decryption method
  143.  
  144.        :param text: Text to decrypt
  145.        :param key: Decryption key
  146.        :type text: string
  147.        :type key: dict
  148.        :return: decrypted text
  149.        :rtype: string
  150.        """
  151.         return self.encrypt(text, key)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement