def q_bit(host, encode): q = Qubit(host) if encode == '+': q.H() if encode == '-': q.X() q.H() if encode == '0': q.I() if encode == '1': q.X() return q
def protocol_alice(alice, bob, secret_key, sample_len): for bit in secret_key: q_bit = Qubit(alice) if bit == 1: q_bit.H() alice.send_qubit(bob, q_bit, await_ack=True) mes = alice.get_next_classical(bob) if mes is not None: test = mes.content secret_key = element_by_indexes(secret_key, test, 1) mes = alice.get_next_classical(bob) if mes is not None: sample_bob = mes.content if sample_bob == secret_key[:sample_len]: alice.send_classical(bob, "NO INTERCEPT", await_ack=True) print("alice key ", secret_key) else: alice.send_classical(bob, "EVE IS LISTENING", await_ack=True) print("STACCAH STACCAH")
def entangle(host): # 01 - 10 q1 = Qubit(host) q2 = Qubit(host) q1.X() q1.H() q2.X() q1.cnot(q2) return q1, q2
def alice(alice, bob, number_of_entanglement_pairs): angles = [0, np.pi / 4, np.pi / 2] bases_choice = [ random.randint(1, 3) for i in range(number_of_entanglement_pairs) ] test_results_alice = [] test_bases_alice = [] sifted_key_alice = [] for i in range(number_of_entanglement_pairs): qubit_a = Qubit(alice) qubit_b = Qubit(alice) # preparation of singlet state (1/sqrt(2))*(|01> - |10>) qubit_a.X() qubit_b.X() qubit_a.H() qubit_a.cnot(qubit_b) print('Sending EPR pair %d' % (i + 1)) _, ack_arrived = alice.send_qubit(bob, qubit_b, await_ack=True) if ack_arrived: #rotate qubit and measure base_a = bases_choice[i] qubit_a.rz(angles[base_a - 1]) meas_a = qubit_a.measure() ack_arrived = alice.send_classical(bob, base_a, await_ack=True) if not ack_arrived: print("Send data failed!") message = alice.get_next_classical(bob, wait=2) if message is not None: base_b = message.content if (base_a == 2 and base_b == 1) or (base_a == 3 and base_b == 2): sifted_key_alice.append(meas_a) elif (base_a == 1 and base_b == 1) or (base_a == 1 and base_b == 3) or ( base_a == 3 and base_b == 1) or (base_a == 3 and base_b == 3): test_bases_alice.append('a' + str(base_a)) test_results_alice.append(str(meas_a)) else: print("The message did not arrive") else: print('The EPR pair was not properly established') ack_arrived = alice.send_classical(bob, (test_results_alice, test_bases_alice), await_ack=True) if not ack_arrived: print("Send data failed!") print("Sifted_key_alice: ", sifted_key_alice)
def encode(self, host_sender, bitstring, bases): encoded_qubits = [] for i in range(len(bitstring)): q = Qubit(host_sender) if bases[i] == "0": if bitstring[i] == "0": pass # initialized in 0 elif bitstring[i] == "1": q.X() elif bases[i] == "1": if bitstring[i] == "0": q.H() elif bitstring[i] == "1": q.X() q.H() encoded_qubits.append(q) # Stop the network at the end of the example # network.stop(stop_hosts=True) return encoded_qubits
def preparation_and_distribution(): for serial in range(NO_OF_SERIALS): for bit_no in range(QUBITS_PER_MONEY): random_bit = randint(0, 1) random_base = randint(0, 1) bank_bits[serial].append(random_bit) bank_basis[serial].append(random_base) q = Qubit(host) if random_bit == 1: q.X() if random_base == 1: q.H() host.send_qubit(customer, q, True)
def sender_qkd(alice, secret_key, receiver): sent_qubit_counter = 0 for bit in secret_key: success = False while success == False: qubit = Qubit(alice) if bit == 1: qubit.H() # If we want to send 0, we'll send |0> # If we want to send 1, we'll send |+> alice.send_qubit(receiver, qubit, await_ack=True) message = alice.get_next_classical(receiver, wait=-1) if message is not None: if message.content == 'qubit successfully acquired': print(f'Alice sent qubit {sent_qubit_counter+1} to Bob') success = True sent_qubit_counter += 1
def _send_key(packet): receiver = network.get_host(packet.receiver) sender = network.get_host(packet.sender) key_size = packet.payload[Constants.KEYSIZE] packet.protocol = Constants.KEY network.send(packet) secret_key = np.random.randint(2, size=key_size) msg_buff = [] sender.qkd_keys[receiver.host_id] = secret_key.tolist() sequence_nr = 0 # iterate over all bits in the secret key. for bit in secret_key: ack = False while not ack: # get a random base. 0 for Z base and 1 for X base. base = random.randint(0, 1) # create qubit q_bit = Qubit(sender) # Set qubit to the bit from the secret key. if bit == 1: q_bit.X() # Apply basis change to the bit if necessary. if base == 1: q_bit.H() # Send Qubit to Receiver sender.send_qubit(receiver.host_id, q_bit, await_ack=True) # Get measured basis of Receiver message = sender.get_next_classical_message(receiver.host_id, msg_buff, sequence_nr) # Compare to send basis, if same, answer with 0 and set ack True and go to next bit, # otherwise, send 1 and repeat. if message == "%d:%d" % (sequence_nr, base): ack = True sender.send_classical(receiver.host_id, ("%d:0" % sequence_nr), await_ack=True) else: ack = False sender.send_classical(receiver.host_id, ("%d:1" % sequence_nr), await_ack=True) sequence_nr += 1
def _establish_epr(self, sender, receiver, q_id, o_seq_num, blocked): """ Instead doing an entanglement swap, for efficiency we establish EPR pairs directly for simulation, if an entanglement swap would have been possible. Args: sender (Host): Sender of the EPR pair receiver (Host): Receiver of the EPR pair q_id (str): Qubit ID of the sent EPR pair o_seq_num (int): The original sequence number blocked (bool): If the pair being distributed is blocked or not """ host_sender = self.get_host(sender) host_receiver = self.get_host(receiver) q1 = Qubit(host_sender) q2 = Qubit(host_sender) q1.H() q1.cnot(q2) host_sender.add_epr(receiver, q1, q_id, blocked) host_receiver.add_epr(sender, q2, q_id, blocked) host_receiver.send_ack(sender, o_seq_num)
def alice_qkd(alice, msg_buff, secret_key, receiver): sequence_nr = 0 # iterate over all bits in the secret key. for bit in secret_key: ack = False while not ack: print("Alice sent %d key bits" % (sequence_nr + 1)) # get a random base. 0 for Z base and 1 for X base. base = random.randint(0, 1) # create qubit q_bit = Qubit(alice) # Set qubit to the bit from the secret key. if bit == 1: q_bit.X() # Apply basis change to the bit if necessary. if base == 1: q_bit.H() # Send Qubit to Bob alice.send_qubit(receiver, q_bit, await_ack=True) # Get measured basis of Bob message = alice.get_next_classical_message(receiver, msg_buff, sequence_nr) # Compare to send basis, if same, answer with 0 and set ack True and go to next bit, # otherwise, send 1 and repeat. if message == ("%d:%d") % (sequence_nr, base): ack = True alice.send_classical(receiver, ("%d:0" % sequence_nr), await_ack=True) else: ack = False alice.send_classical(receiver, ("%d:1" % sequence_nr), await_ack=True) sequence_nr += 1
def test_single_gates(self): for b in TestBackend.backends: backend = b() network = Network.get_instance() network.start(["Alice", "Bob"], backend) alice = Host('Alice', backend) bob = Host('Bob', backend) alice.start() bob.start() network.add_host(alice) network.add_host(bob) q = Qubit(alice) q.X() self.assertEqual(1, q.measure()) q = Qubit(alice) q.H() q.H() self.assertEqual(0, q.measure()) network.stop(True)
def _send_key(packet): def helper_recv(host, receive_from_id, buffer, sequence_nr): buffer.append(host.get_next_classical(receive_from_id, wait=-1)) msg = "ACK" while msg == "ACK" or (msg.split(':')[0] != ("%d" % sequence_nr)): if len(buffer) == 0: buffer.append(host.get_next_classical(receive_from_id, wait=-1)) ele = buffer.pop(0) msg = ele.content return msg receiver = network.get_host(packet.receiver) sender = network.get_host(packet.sender) key_size = packet.payload[Constants.KEYSIZE] packet.protocol = Constants.REC_KEY network.send(packet) secret_key = [] msg_buff = [] sequence_nr = 0 attempt_counter = 0 # iterate over all bits in the secret key. for _ in range(key_size): ack = False while not ack: # get a random base. 0 for Z base and 1 for X base. base = random.randint(0, 1) bit = random.randint(0, 1) # create qubit q_bit = Qubit(sender) # Set qubit to the bit from the secret key. if bit == 1: q_bit.X() # Apply basis change to the bit if necessary. if base == 1: q_bit.H() # Send Qubit to Receiver sender.send_qubit(receiver.host_id, q_bit, await_ack=True) # Get measured basis of Receiver message = helper_recv(sender, receiver.host_id, msg_buff, sequence_nr) # Compare to send basis, if same, answer with 0 and set ack True and go to next bit, # otherwise, send 1 and repeat. if message == "%d:%d" % (sequence_nr, base): ack = True # Bit got accepted, add to key secret_key.append(bit) sender.send_classical(receiver.host_id, ("%d:0" % sequence_nr), await_ack=True) else: ack = False sender.send_classical(receiver.host_id, ("%d:1" % sequence_nr), await_ack=True) sequence_nr += 1 attempt_counter += 1 # Add key to keys of sender sender.qkd_keys[receiver.host_id] = (secret_key, attempt_counter)
def handshake_receiver(host, sender_id): """ Establishes a classical TCP-like handshake with the sender . If successful starts to receive the qubits , otherwise terminated the connection. :param host: Receiver host :param sender_id: ID of the sender :return: If successful returns True, otherwise False """ latest_seq_num = host.get_sequence_number_receiver(sender_id) # Receive the EPR half of Alice and the SYN message qb_2 = host.get_data_qubit(sender_id, wait=WAIT_TIME) if qb_2 is None: print('qb_2 is None') return False message_recv = host.get_classical(sender_id, (latest_seq_num + 1), wait=WAIT_TIME) if not message_recv: print('No message has arrived') return False message_recv = message_recv.content if message_recv == '10': print("SYN is received by Bob") else: return False # Create an EPR pair. qb_3 = Qubit(host) qb_4 = Qubit(host) qb_3.H() qb_3.cnot(qb_4) # Send half of the EPR pair created (qubit 3) and send back the qubit 2 that Alice has sent first. _, ack_received = host.send_qubit(sender_id, qb_2, await_ack=True) if ack_received is False: print('ACK is not received') return False _, ack_received = host.send_qubit(sender_id, qb_3, await_ack=True) if ack_received is False: print('ACK is not received') return False # Send SYN-ACK message. host.send_classical(sender_id, SYN_ACK, True) latest_seq_num = host.get_sequence_number_receiver(sender_id) # Receive the ACK message. message = host.get_classical(sender_id, latest_seq_num, wait=WAIT_TIME) if message is None: print('ACK was not received by Bob') return False if message.content == '01': print('ACK was received by Bob') # Receive the qubit 3. qa_3 = host.get_data_qubit(sender_id, wait=WAIT_TIME) if qa_3 is None: return False # Make a Bell State measurement in qubit 3 and qubit 4. qa_3.cnot(qb_4) qa_3.H() qa_3_check = qa_3.measure() qb_4_check = qb_4.measure() # If measurement results are as expected , establish the TCP connection. # Else report that there is something wrong. if qa_3_check == 0 and qb_4_check == 0: print("TCP connection established.") return True else: print("Something is wrong.") return False
def handshake_sender(host, receiver_id): """ Establishes a classical TCP-like handshake with the receiver . If successful starts the transmission of qubits , otherwise terminated the connection. :param host: Sender of qubits :param receiver_id: ID of the receiver :return: If successful returns True, otherwise False """ # Create an EPR pair. qa_1 = Qubit(host) qa_2 = Qubit(host) qa_1.H() qa_1.cnot(qa_2) # Send a half of EPR pair and the SYN message to Bob. _, ack_received = host.send_qubit(receiver_id, qa_2, await_ack=True) if ack_received is False: print('ACK is not received') return False ack_received = host.send_classical(receiver_id, SYN, await_ack=True) if ack_received is False: print('ACK is not received') return False syn_seq_num = host.get_sequence_number_receiver(receiver_id) # Receive the qubits Bob has sent (qubit 2 and qubit 3) for SYN-ACK. qb_2 = host.get_data_qubit(receiver_id, wait=WAIT_TIME) if qb_2 is None: return False qb_3 = host.get_data_qubit(receiver_id, wait=WAIT_TIME) if qb_3 is None: return False # Receive the classical message Bob has sent for SYN-ACK. message_recv = host.get_classical(receiver_id, syn_seq_num + 2, wait=WAIT_TIME) if message_recv is None: return False if message_recv.content == '11': print("SYN-ACK is received by Alice") else: print('Connection terminated - 1 ') return False # Make a Bell State measurement on qubit 1 and qubit 2. qa_1.cnot(qb_2) qa_1.H() qa_1_check = qa_1.measure() qb_2_check = qb_2.measure() # If measurement results are as expected, send Bob a ACK message and the qubit 3 that he has sent previously. # Else report that there is something wrong. if qa_1_check == 0 and qb_2_check == 0: ack_received = host.send_classical(receiver_id, ACK, await_ack=True) if ack_received is False: print('ACK is not received') return False _, ack_received = host.send_qubit(receiver_id, qb_3, await_ack=True) if ack_received is False: print('ACK is not received') return False return True else: print("Something is wrong.") return False