def _encrypt_block_ints(self, block_ints: List[int]) -> List[int]: """Encrypt the text block's integers.""" s = self.__s # Join individual block bytes into 4 registers. regs = [] for i in range(0, len(block_ints), 4): reg = bin_join(block_ints[i:i + 4], BYTE_BITS) regs.append(reg) [a, b, c, d] = regs b = (b + s[0]) % MOD d = (d + s[1]) % MOD for i in range(1, R + 1): t = rotl((b * (2 * b + 1)) % MOD, LG_W, W) u = rotl((d * (2 * d + 1)) % MOD, LG_W, W) a = (rotl(a ^ t, u, W) + s[2 * i]) % MOD c = (rotl(c ^ u, t, W) + s[2 * i + 1]) % MOD (a, b, c, d) = (b, c, d, a) a = (a + s[2 * R + 2]) % MOD c = (c + s[2 * R + 3]) % MOD cipher_int = bin_join([a, b, c, d], W) cipher_ints = bin_split(cipher_int, BLOCK_BITS, BYTE_BITS) return cipher_ints
def _decrypt_block_ints(self, block_ints: List[int]) -> List[int]: """Decrypt the cipher block's integers.""" s = self.__s # Join individual block bytes into 4 registers. regs = [] for i in range(0, len(block_ints), 4): reg = bin_join(block_ints[i:i + 4], BYTE_BITS) regs.append(reg) [a, b, c, d] = regs c = (c - s[2 * R + 3]) % MOD a = (a - s[2 * R + 2]) % MOD for j in range(R, 0, -1): (a, b, c, d) = (d, a, b, c) u = rotl((d * (2 * d + 1)) % MOD, LG_W, W) t = rotl((b * (2 * b + 1)) % MOD, LG_W, W) c = (rotr((c - s[2 * j + 1]) % MOD, t, W) ^ u) a = (rotr((a - s[2 * j]) % MOD, u, W) ^ t) d = (d - s[1]) % MOD b = (b - s[0]) % MOD text_int = bin_join([a, b, c, d], W) text_ints = bin_split(text_int, BLOCK_BITS, BYTE_BITS) return text_ints
def __process_block(self, block_ints: List[int], is_encrypt: bool) -> List[int]: """Process the input block's integers (works in both ways).""" block_int = bin_join(block_ints, BYTE_BITS) l, r = bin_split(block_int, BLOCK_BITS, SUBBLOCK_BITS) l, r = _process_subblocks(l, r, self.__p, self.__s, is_encrypt) output_bin = bin_join([l, r], SUBBLOCK_BITS) return bin_split(output_bin, BLOCK_BITS, BYTE_BITS)
def __process_block(self, block_ints: List[int]) -> List[int]: """Process the input block's integers (works in both ways).""" block_bin = bin_join(block_ints, BYTE_BITS) [x1, x2, x3, x4] = bin_split(block_bin, BLOCK_BITS, SUBBLOCK_BITS) for i in range(ROUNDS_N): y1, y2, y3, y4 = _ka_layer(x1, x2, x3, x4, self.__subkeys[i][:4]) x1, x2, x3, x4 = _ma_layer(y1, y2, y3, y4, self.__subkeys[i][4:]) y1, y2, y3, y4 = _ka_layer(x1, x3, x2, x4, self.__subkeys[ROUNDS_N]) output_bin = bin_join([y1, y2, y3, y4], SUBBLOCK_BITS) output_ints = bin_split(output_bin, BLOCK_BITS, BYTE_BITS) return output_ints
def _generate_subkeys(key_ints: List[int]) -> BlockSubkeys: """Generate the subkeys from the given key.""" key_bin = bin_join(key_ints, BYTE_BITS) subkeys = [] while len(subkeys) < SUBKEYS_N: subkeys += bin_split(key_bin, KEY_BITS, SUBKEY_BITS) key_bin = rotl(key_bin, 25, KEY_BITS) subkeys = subkeys[:SUBKEYS_N] step = SUBKEYS_N // ROUNDS_N subkeys = [subkeys[i:i + step] for i in range(0, len(subkeys), step)] return subkeys
def __get_subkey(self, round_n: int) -> List[int]: """Function used for subkey generation by shifted cyclic reading of 32-bit key.""" key_ints = self.__key_ints bytes_cut = round_n // BYTE_BITS bits_cut = round_n % BYTE_BITS # +1 because in order to slice we need to have some extra bits. req_key_length = bytes_cut + self.key_bytes + 1 while len(key_ints) < req_key_length: key_ints += key_ints key_ints = key_ints[bytes_cut:req_key_length] subkey = bin_join(key_ints, BYTE_BITS) subkey_width = len(key_ints) * BYTE_BITS key_bits = self.key_bytes * BYTE_BITS subkey = bin_slice(subkey, bits_cut, key_bits + bits_cut, subkey_width) subkey_ints = bin_split(subkey, key_bits, BYTE_BITS) return subkey_ints