def _sdes_s(bs: BitString) -> BitString: bs_l = BitString(bs[:_sdes_block_length // 2]) bs_r = BitString(bs[_sdes_block_length // 2:]) result_l = _sdes_s_single_box(bs_l, 0) result_r = _sdes_s_single_box(bs_r, 1) return operator.add(result_l, result_r)
def _sdes_s_single_box(bs: BitString, i: int) -> BitString: bs_l = BitString(bs[0] + bs[3]) bs_r = BitString(bs[1] + bs[2]) result = _sdes_s_table[i][_sdes_s_row_determination_table[bs_l]][ _sdes_s_row_determination_table[bs_r]] return bit_string.small_int_to_bit_string(result, _sdes_s_input_length // 2)
def _des_s_single_block(bs: BitString, group_number: int) -> BitString: curr_row = _des_s_row_determination_table[BitString(''.join( map(lambda x: bs[x], _des_s_row_determination_bit_index_table)))] curr_column = _des_s_column_determination_table[BitString(''.join( map(lambda x: bs[x], _des_s_column_determination_bit_index_table)))] curr_result_block = _des_s_table[group_number][curr_row][curr_column] return bit_string.small_int_to_bit_string(curr_result_block, _des_s_output_group_length)
def _des_s(bs: BitString) -> BitString: result_list = [] for group_number in range(_des_s_group_count): curr_slice = bs[group_number * _des_s_group_length:group_number * _des_s_group_length + _des_s_group_length] curr_slice = BitString(curr_slice) result_list.append(_des_s_single_block(curr_slice, group_number)) result = BitString(''.join(result_list)) return result
def _sdes(bs: BitString, key_list: List[BitString]) -> BitString: result = _sdes_ip(bs) result_l = BitString(result[:_sdes_block_length // 2]) result_r = BitString(result[_sdes_block_length // 2:]) result_l = bit_string.xor(result_l, _sdes_f(result_r, key_list[0])) result_l, result_r = result_r, result_l result_l = bit_string.xor(result_l, _sdes_f(result_r, key_list[1])) result = operator.add(result_l, result_r) result = _sdes_ip_inv(result) return result
def feistel_round(s: BitString, k: BitString, f: Callable[[BitString, BitString], BitString]) -> BitString: length = len(s) if length % 2 != 0: raise ValueError("feistel_round: s not of even length") l = BitString(s[0:length // 2]) r = BitString(s[length // 2:]) l_new = r r_new = bit_string.xor(l, f(r, k)) result = BitString(l_new + r_new) return result
class BitPermutation(object): @slot_supporter('bitstring') def __init__(self, permutation_list): if permutation_list is not None: self._permutation_list = permutation_list else: self._permutation_list = None self._input_bitstring = None self._output_bitstring = None def permute(self, permutation_list=None): """ Permute according to permutation list """ if permutation_list is not None: return self._bitstring.permute(permutation_list) else: if self._permutation_list is not None: return self._bitstring.permute(self._permutation_list) raise ValueError("Permutation list is not given nor initialized.") def bitstring_handler(self, **kwargs): self._input_bitstring = BitString(bitstring=kwargs['bitstring']) self.apply() def apply(self): self._output_bitstring = self._input_bitstring.permute(self._permutation_list)
def decrypt(c: int, sk: Tuple[List[int], int, int]) -> BitString: result = '' w = sk[0] q = sk[1] r = sk[2] if gcd.gcd(q, r) != 1: raise ValueError("decrypt(): q and r not coprime") c_real = (c * gcd.get_modular_inverse(r, q)) % q for w_i in reversed(w): if c_real >= w_i: c_real -= w_i result += '1' else: result += '0' if c_real < 0: raise ValueError("decrypt(): decrypt error") if c_real != 0: raise ValueError("decrypt(): decrypt error") return BitString(result)
def _des_3round_iter_possible_keys(possible_key_chunks: List[Set[BitString]]): mid = _des_actual_key_length // 2 total_left_rshift_rounds = sum( _des_gen_key_shift_count_table[0:_des_3round_round_count]) for known_bits in itertools.product(*possible_key_chunks): for unknown_bits in itertools.product( *itertools.repeat(bit_string.all_bits, _des_s_group_count)): # 从 DES 轮密钥结构推出 curr_k_3 = BitString(''.join(known_bits) + ''.join(unknown_bits)) curr_k_0 = _des_gen_key_pc_2_inv(curr_k_3) # XXX: why curr_k_0[:mid] and curr_k_0_l + curr_k_0_r still return a str? curr_k_0_l = bit_string.right_rshift(BitString(curr_k_0[:mid]), total_left_rshift_rounds) curr_k_0_r = bit_string.right_rshift(BitString(curr_k_0[mid:]), total_left_rshift_rounds) curr_k_0 = operator.add(curr_k_0_l, curr_k_0_r) curr_k = _des_gen_key_pc_1_inv(curr_k_0) yield curr_k return
def _des_gen_key_pc_1_inv(bs: BitString) -> BitString: result = bit_string.permutation_by_table_with_completion( bs, _des_gen_key_pc_1_inv_table) _des_gen_key_pc_2_inv_block_length = 8 parity_bit_list = [] result_block_list = [ result[i:i + _des_gen_key_pc_2_inv_block_length - 1] for i in range( 0, des_orig_key_length, _des_gen_key_pc_2_inv_block_length) ] for block in result_block_list: one_count = len( list(filter(lambda x: ord(x) == bit_string.ord_1, block))) parity_bit_list.append( BitString('1') if one_count % 2 == 0 else BitString('0')) result = BitString(''.join( map(operator.add, result_block_list, parity_bit_list))) return result
def _des_gen_key_list(k: bytes) -> List[BitString]: k_str = _des_gen_key_pc_1(bit_string.bytes_to_bit_string(k)) c = k_str[0:_des_actual_key_length // 2] d = k_str[_des_actual_key_length // 2:] result = [] for round_number in range(_des_gen_key_rounds): c = bit_string.left_rshift( c, _des_gen_key_shift_count_table[round_number]) d = bit_string.left_rshift( d, _des_gen_key_shift_count_table[round_number]) k = _des_gen_key_pc_2(BitString(c + d)) result.append(k) return result
def _des_3round_cryptanalysis_differential_two_pairs( p1: BitString, c1: BitString, p2: BitString, c2: BitString) -> List[Set[BitString]]: mid = des_block_length // 2 r_3_1 = BitString(c1[mid:]) r_3_2 = BitString(c2[mid:]) r_3_diff = bit_string.xor(r_3_1, r_3_2) l_0_1 = BitString(p1[:mid]) l_0_2 = BitString(p2[:mid]) l_0_diff = bit_string.xor(l_0_1, l_0_2) c_diff = _des_p_inv(bit_string.xor(r_3_diff, l_0_diff)) l_3_1 = BitString(c1[:mid]) l_3_2 = BitString(c2[:mid]) e_1 = _des_e(l_3_1) e_2 = _des_e(l_3_2) c_diff_list = list( map(lambda x: BitString(c_diff[x:x + _des_s_output_group_length]), range(0, des_block_length, _des_s_output_group_length))) e_1_list = list( map(lambda x: BitString(e_1[x:x + _des_s_group_length]), range(0, _des_s_input_length, _des_s_group_length))) e_2_list = list( map(lambda x: BitString(e_2[x:x + _des_s_group_length]), range(0, _des_s_input_length, _des_s_group_length))) result = [] for i in range(_des_s_group_count): result.append( _des_3round_cryptanalysis_differential_gen_test_set( e_1_list[i], e_2_list[i], c_diff_list[i], i)) return result
def cryptanalysis_lll(c: int, pk: List[int]) -> BitString: delta = 0.75 if len(pk) <= 1: raise ValueError("cryptanalysis_lll(): pk too short") n = len(pk) + 1 m = [[0 for _ in range(n)] for _ in range(n)] # fill in identity matrix for i in range(n - 1): m[i][i] = 1 # fill in public key for i in range(n - 1): m[i][n - 1] = pk[i] m[n - 1][n - 1] = -c m_lll = lll.lll(m, delta) print(m_lll) valid_row = None for row in m_lll: is_valid = True for elem in row[:-1]: if elem != 0 and elem != 1: is_valid = False if row[-1] != 0: is_valid = False if is_valid: valid_row = row if valid_row is None: raise ValueError("cryptanalysis_lll(): cryptanalysis failed") return BitString(''.join(map(str, valid_row[:-1])))
from knapsack import * from bit_string import BitString key_length = 5 key = gen_key(key_length) print(key) sk, pk = key m = BitString('10101') c = encrypt(m, pk) print(c) m_recovered = decrypt(c, sk) print(m_recovered) print(m_recovered == m) w = [2, 3, 7, 14, 30, 57, 120, 251] q = 491 r = 41 sk = (w, q, r) pk = [82, 123, 287, 83, 248, 373, 10, 471] m = BitString('00101111') c = encrypt(m, pk) print(c) m_recovered = cryptanalysis_lll(c, pk) print(m_recovered) print(m == m_recovered)
_sdes_gen_key_lshift_count_table = [1, 2] _sdes_gen_key_p8_table = [6, 3, 7, 4, 8, 5, 10, 9] _sdes_rounds = 2 _sdes_block_length = 8 _sdes_ip_table = [2, 6, 3, 1, 4, 8, 5, 7] _sdes_e_table = [4, 1, 2, 3, 2, 3, 4, 1] _sdes_s_input_length = 4 _sdes_s_row_determination_table = { BitString('00'): 0, BitString('01'): 1, BitString('10'): 2, BitString('11'): 3 } _sdes_s_table = [[[1, 0, 3, 2], [3, 2, 1, 0], [0, 2, 1, 3], [3, 1, 3, 2]], [[0, 1, 2, 3], [2, 0, 1, 3], [3, 0, 1, 0], [2, 1, 0, 3]]] _sdes_p4_table = [2, 4, 3, 1] _sdes_ip_inv_table = [4, 1, 3, 5, 7, 2, 8, 6] def _sdes_gen_key(k: BitString) -> List[BitString]: actual_key = bit_string.permutation_by_table(k, _sdes_gen_key_p10_table)
def bitstring_handler(self, **kwargs): self._input_bitstring = BitString(bitstring=kwargs['bitstring']) self.apply()
_des_e_table = [ 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1 ] _des_s_input_length = 48 _des_s_group_count = 8 _des_s_group_length = 6 _des_s_output_group_length = 4 _des_s_output_length = 32 _des_s_row_determination_bit_index_table = [0, 5] _des_s_row_determination_table = { BitString('00'): 0, BitString('01'): 1, BitString('10'): 2, BitString('11'): 3 } _des_s_column_determination_bit_index_table = [1, 2, 3, 4] _des_s_column_determination_table = { BitString('0000'): 0, BitString('0001'): 1, BitString('0010'): 2, BitString('0011'): 3, BitString('0100'): 4, BitString('0101'): 5, BitString('0110'): 6,