diff --git a/src/utils.py b/src/utils.py index 22d21a5..038e914 100644 --- a/src/utils.py +++ b/src/utils.py @@ -1,25 +1,83 @@ import secrets -def random_number_in_range(min_val: int, max_val: int) -> int: - """ originally secure_rand """ - return min_val + secrets.randbelow(max_val - min_val + 1) +def secure_fisher_yates_shuffle(arr: list) -> list: + n = len(arr) + for i in range(n - 1, 0, -1): + j = secrets.randbelow(i + 1) + arr[i], arr[j] = arr[j], arr[i] + return arr -def random_number_in_range_excluding(min_val: int, max_val: int, exclude: list[int]) -> int: - """ originally secure_rand """ - - return min_val + secrets.randbelow(max_val - min_val + 1) +def generate_random_nonrepeating_list(list_len: int, min_val: int = 0, max_val: int = 2 ** 16) -> list[int]: + assert(max_val-min_val >= list_len) + return secure_fisher_yates_shuffle(list(range(min_val, max_val))[:list_len]) -def generate_random_list(list_len: int, min_val: int = 0, max_val: int = 255) -> list[int]: - return [random_number_in_range(min_val, max_val) for _ in range(list_len)] - - -def generate_random_matrix(rows: int, cols: int, min_val: int = 0, max_val: int = 255) -> list[list[int]]: - return [[random_number_in_range(min_val, max_val) for _ in range(rows)] for _ in range(cols)] +def generate_random_nonrepeating_matrix(rows: int, cols: int, min_val: int = 0, max_val: int = 2 ** 16) -> list[list[int]]: + values = generate_random_nonrepeating_list(rows*cols, min_val, max_val) + matrix = [] + idx = 0 + for _ in range(cols): + row = [] + for _ in range(rows): + row.append(values[idx]) + idx += 1 + matrix.append(row) + return matrix def xor_lists(l1: list[int], l2: list[int]): assert len(l1) == len(l2) return [l2[i] ^ l1[i] for i in range(len(l1))] + + +def generate_random_index_interface(height: int, width: int) -> list[list[int]]: + interface = [] + idx = 0 + for i in range(height): + key = [] + for j in range(width): + key.append(idx) + idx += 1 + key = secure_fisher_yates_shuffle(key) + interface.append(key) + return interface + + +def generate_serialized_index_interface(height: int, width: int) -> list[list[int]]: + interface = [] + idx = 0 + for i in range(height): + key = [] + for j in range(width): + key.append(idx) + idx += 1 + interface.append(key) + return interface + + +def interface_transpose(interface: list[list[int]]) -> list[list[int]]: + return [list(row) for row in zip(*interface)] + + +def shuffle_interface(self): + pass + + +def disperse_interface(user_interface: list[list[int]]): + shuffled_keys = secure_fisher_yates_shuffle(user_interface) + dispersed_interface = random_attribute_rotation(shuffled_keys) + return dispersed_interface + + +def random_attribute_rotation(user_interface: list[list[int]]) -> list[list[int]]: + numb_attr = len(user_interface[0]) + numb_keys = len(user_interface) + attr_rotation = secure_fisher_yates_shuffle(list(range(numb_keys)))[:numb_attr] + transposed_user_interface = interface_transpose(user_interface) + assert (len(attr_rotation) == len(transposed_user_interface)) + for idx, attr_set in enumerate(transposed_user_interface): + rotation = attr_rotation[idx] + transposed_user_interface[idx] = attr_set[rotation:] + attr_set[:rotation] + return interface_transpose(transposed_user_interface)