from utils import CipherUtils CLEAR_LIST = [0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1] INIT_STATE = [0, 1, 1, 0] COEFFICIENTS = [1, 1, 1, 0] def create_shift_register(init_state: [int], coefficients: [int]) -> [int]: """ Creates and returns the maximum bit stream for the given input state via a linear shift register. Especially the coefficients are important as choosing the correct ones for any given shift register length will provide the maximum amount of bits before they repeat :param init_state: The initial bits in the shift register :param coefficients: The coefficients of every field in the shift register :return: The maximum length bit stream generated by the linear shift register """ return_list = [] current_state = init_state.copy() if (size := len(init_state)) != len(coefficients): print('Length of lists does not match.') exit() for x in range(2 ** size): return_list.append(current_state[-1]) new_state_value = 0 for i in range(size): new_state_value = (new_state_value + current_state[i] * coefficients[i]) % 2 current_state.insert(0, new_state_value) current_state.pop(-1) if current_state == init_state: # For ideal coefficients, the output is perfectly fine. # However, for unideal coefficients, it might appear that we reach a state after lets say 1 iteration. # We still need to output [size] amount of bits, hence the following line. if x != (2 ** size) - 2: return_list.extend(current_state[1:][::-1]) break return return_list if __name__ == '__main__': key = create_shift_register(INIT_STATE, COEFFICIENTS) encrypted = CipherUtils.xor_two_lists(CLEAR_LIST, key) decrypted = CipherUtils.xor_two_lists(encrypted, key) print(CLEAR_LIST) print(encrypted) print(decrypted)