Advertisement
MarkUa

Untitled

Oct 7th, 2019
482
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.80 KB | None | 0 0
  1. class RC5:
  2.  
  3.     def __init__(self, w, R, key, strip_extra_nulls=False):
  4.         self.w = w  # block size (32, 64 or 128 bits)
  5.         self.R = R  # number of rounds (0 to 255)
  6.         self.key = key  # key (0 to 2040 bits)
  7.         self.strip_extra_nulls = strip_extra_nulls
  8.         # some useful constants
  9.         self.T = 2 * (R + 1)
  10.         self.w4 = w // 4
  11.         self.w8 = w // 8
  12.         self.mod = 2 ** self.w
  13.         self.mask = self.mod - 1
  14.         self.b = len(key)
  15.  
  16.         self.__keyAlign()
  17.         self.__keyExtend()
  18.         self.__shuffle()
  19.  
  20.     def __lshift(self, val, n):
  21.         n %= self.w
  22.         return ((val << n) & self.mask) | ((val & self.mask) >> (self.w - n))
  23.  
  24.     def __rshift(self, val, n):
  25.         n %= self.w
  26.         return ((val & self.mask) >> n) | (val << (self.w - n) & self.mask)
  27.  
  28.     def __const(self):  # constants generation
  29.         if self.w == 16:
  30.             return 0xB7E1, 0x9E37  # return P, Q values
  31.         elif self.w == 32:
  32.             return 0xB7E15163, 0x9E3779B9
  33.         elif self.w == 64:
  34.             return 0xB7E151628AED2A6B, 0x9E3779B97F4A7C15
  35.  
  36.     def __keyAlign(self):
  37.         if self.b == 0:  # key is empty
  38.             self.c = 1
  39.         elif self.b % self.w8:
  40.             self.key += b'\x00' * (self.w8 - self.b % self.w8)  # fill key with \x00 bytes
  41.             self.b = len(self.key)
  42.             self.c = self.b // self.w8
  43.         else:
  44.             self.c = self.b // self.w8
  45.         L = [0] * self.c
  46.         for i in range(self.b - 1, -1, -1):
  47.             L[i // self.w8] = (L[i // self.w8] << 8) + self.key[i]
  48.         self.L = L
  49.  
  50.     def __keyExtend(self):
  51.         P, Q = self.__const()
  52.         self.S = [(P + i * Q) % self.mod for i in range(self.T)]
  53.  
  54.     def __shuffle(self):
  55.         i, j, A, B = 0, 0, 0, 0
  56.         for k in range(3 * max(self.c, self.T)):
  57.             A = self.S[i] = self.__lshift((self.S[i] + A + B), 3)
  58.             B = self.L[j] = self.__lshift((self.L[j] + A + B), A + B)
  59.             i = (i + 1) % self.T
  60.             j = (j + 1) % self.c
  61.  
  62.     def encryptBlock(self, data):
  63.         A = int.from_bytes(data[:self.w8], byteorder='little')
  64.         B = int.from_bytes(data[self.w8:], byteorder='little')
  65.         A = (A + self.S[0]) % self.mod
  66.         B = (B + self.S[1]) % self.mod
  67.         for i in range(1, self.R + 1):
  68.             A = (self.__lshift((A ^ B), B) + self.S[2 * i]) % self.mod
  69.             B = (self.__lshift((A ^ B), A) + self.S[2 * i + 1]) % self.mod
  70.         return (A.to_bytes(self.w8, byteorder='little')
  71.                 + B.to_bytes(self.w8, byteorder='little'))
  72.  
  73.     def decryptBlock(self, data):
  74.         A = int.from_bytes(data[:self.w8], byteorder='little')
  75.         B = int.from_bytes(data[self.w8:], byteorder='little')
  76.         for i in range(self.R, 0, -1):
  77.             B = self.__rshift(B - self.S[2 * i + 1], A) ^ A
  78.             A = self.__rshift(A - self.S[2 * i], B) ^ B
  79.         B = (B - self.S[1]) % self.mod
  80.         A = (A - self.S[0]) % self.mod
  81.         return (A.to_bytes(self.w8, byteorder='little')
  82.                 + B.to_bytes(self.w8, byteorder='little'))
  83.  
  84.     def encryptBytes(self, data):
  85.         res, run = b'', True
  86.         while run:
  87.             temp = data[:self.w4]
  88.             if len(temp) != self.w4:
  89.                 data = data.ljust(self.w4, b'\x00')
  90.                 run = False
  91.             res += self.encryptBlock(temp)
  92.             data = data[self.w4:]
  93.             if not data:
  94.                 break
  95.         return res
  96.  
  97.     def decryptBytes(self, data):
  98.         res, run = b'', True
  99.         while run:
  100.             temp = data[:self.w4]
  101.             if len(temp) != self.w4:
  102.                 run = False
  103.             res += self.decryptBlock(temp)
  104.             data = data[self.w4:]
  105.             if not data:
  106.                 break
  107.         return res.rstrip(b'\x00')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement