def _perform_error_estimation(self): print('Performing error estimation...', end='\r') error_estimation_indices = [] key_part = [] for i in range(0, self.n): r = random.randint(0, len(self.sifted_key) - 1) while r in error_estimation_indices: r = random.randint(0, len(self.sifted_key) - 1) error_estimation_indices.append(r) key_part.append(self.sifted_key[r]) communication.send_message(self.cqc, self.receiver, self.skey, error_estimation_indices) communication.send_binary_list(self.cqc, self.receiver, self.skey, key_part) receiver_key_part = communication.receive_binary_list( self.cqc, self.receiver_pkey) num_errors = 0.0 for i in range(0, len(key_part)): if receiver_key_part[i] != key_part[i]: num_errors += 1.0 self.error_estimation = num_errors / len(key_part) print('Performing error estimation... Done!') print('Error rate = {}'.format(self.error_estimation)) error_estimation_indices.sort() self.sifted_key = utils.remove_indices(self.sifted_key, error_estimation_indices) remaining_bits = len(self.sifted_key) min_entropy = remaining_bits * (1 - utils.h(self.error_estimation)) max_key = min_entropy - 2 * utils.log(1 / self.security_param, 2) - 1 return self.n <= max_key
def receive(self, sender='Alice'): with CQCConnection(self.name) as self.cqc: self.cqc.closeClassicalServer() self.sender = sender self.sender_pkey = auth.get_public_key(sender) config = communication.receive_list(self.cqc, self.sender_pkey) self.n = config['n'] self.correctness_param = config['correctness_param'] self.security_param = config['security_param'] filename = os.path.basename(config['filename']) self.N = math.ceil((4 + self.correctness_param) * self.n) + 25 self._receive_qubits() self._perform_basis_sift() can_continue = self._perform_error_estimation() if not can_continue: print('Not enough min entropy :(') return self._perform_error_correction() self._perform_privacy_amplification() cyphertext = communication.receive_binary_list(self.cqc, self.sender_pkey) plaintext = self._decrypt(cyphertext) print(plaintext) f = open(self.name + '-' + filename, 'wb') f.write(plaintext) f.close()
def _perform_error_estimation(self): # print('Performing error estimation...', end='\r') error_estimation_indices = communication.receive_list(self.cqc, self.sender_pkey) sender_key_part = communication.receive_binary_list(self.cqc, self.sender_pkey) num_errors = 0.0 key_part = [] for i in range(0, len(error_estimation_indices)): key_part.append(self.sifted_key[error_estimation_indices[i]]) if sender_key_part[i] != key_part[i]: num_errors += 1.0 communication.send_binary_list(self.cqc, self.sender, self.skey, key_part) self.error_estimation = num_errors / len(key_part) # print('B Performing error estimation... Done!') # print('B Error rate = {}'.format(self.error_estimation)) error_estimation_indices.sort() self.sifted_key = utils.remove_indices(self.sifted_key, error_estimation_indices) remaining_bits = len(self.sifted_key) min_entropy = remaining_bits * (1 - utils.h(self.error_estimation)) max_key = min_entropy - 2 * utils.log(1/self.security_param, 2) - 1 return self.n <= max_key
def _perform_basis_sift(self): # print("Performing Basis sift...", end='\r') receiver_basis = communication.receive_binary_list(self.cqc, self.sender_pkey) communication.send_binary_list(self.cqc, self.sender, self.skey, self.basis_list) diff_basis = [] for i in range(0, len(receiver_basis)): if receiver_basis[i] != self.basis_list[i]: diff_basis.append(i) self.sifted_key = utils.remove_indices(self.raw_key, diff_basis) self.sifted_basis = utils.remove_indices(self.basis_list, diff_basis)
def run_algorithm(self): n = math.ceil(0.73 / self.party.error_estimation) iterations = [[]] # 1st iteration for i in range(0, len(self.party.sifted_key), n): iterations[0].append( list(range(i, min(i + n, len(self.party.sifted_key) - 1)))) parities = [ utils.calculate_parities(self.party.sifted_key, iterations[0]) ] alice_parities = [ communication.receive_binary_list(self.party.cqc, self.party.sender_pkey) ] for i in range(0, len(alice_parities[0])): if parities[0][i] != alice_parities[0][i]: communication.send_message(self.party.cqc, self.party.sender, self.party.skey, i) self._binary(iterations[0][i]) parities[0][i] ^= 1 communication.send_message(self.party.cqc, self.party.sender, self.party.skey, 'ALL DONE') # nth iteration for iter_num in range(1, 4): n = 2 * n iterations.append([]) temp_indices = communication.receive_list(self.party.cqc, self.party.sender_pkey) for i in range(0, len(self.party.sifted_key), n): iterations[iter_num].append( temp_indices[i:min(i + n, len(self.party.sifted_key) - 1)]) parities.append( utils.calculate_parities(self.party.sifted_key, iterations[iter_num])) alice_parities.append( communication.receive_binary_list(self.party.cqc, self.party.sender_pkey)) for i in range(0, len(alice_parities[iter_num])): blocks_to_process = [(iter_num, i)] while blocks_to_process: (correcting_iter, correcting_block) = blocks_to_process.pop() if parities[correcting_iter][ correcting_block] != alice_parities[ correcting_iter][correcting_block]: communication.send_message( self.party.cqc, self.party.sender, self.party.skey, [correcting_iter, correcting_block]) corrected_index = self._binary( iterations[correcting_iter][correcting_block]) for i in range(0, iter_num): block_containing_index = utils.get_num_block_with_index( iterations[correcting_iter], corrected_index) parities[i][block_containing_index] ^= 1 if i != correcting_iter: blocks_to_process.append( (i, block_containing_index)) communication.send_message(self.party.cqc, self.party.sender, self.party.skey, 'ALL DONE') print(self.party.sifted_key)
def _perform_privacy_amplification(self): seed = communication.receive_binary_list(self.cqc, self.sender_pkey) seed_col = seed[:self.n] seed_row = seed[self.n:] self.final_key = matmul(toeplitz(seed_col, seed_row), self.sifted_key)