Eavesdropping on channels¶
In this example we see how we can add an eavesdropper, or packet sniffer, to the network. First, as always, we initialize our network:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | network = Network.get_instance()
nodes = ["Alice", "Bob", "Eve"]
network.start(nodes)
network.delay = 0.0
host_alice = Host('Alice')
host_alice.add_connection('Bob')
host_alice.start()
host_bob = Host('Bob')
host_bob.add_connection('Alice')
host_bob.add_connection('Eve')
host_bob.start()
host_eve = Host('Eve')
host_eve.add_connection('Bob')
host_eve.delay = 0.2
host_eve.start()
network.add_host(host_alice)
network.add_host(host_bob)
network.add_host(host_eve)
|
Next we can define the protocols for Alice and Eve. First Alice is sending classical messages to Eve and next prepares qubits in the excited state and also sends them the Eve. Eve simply prints her messages and measures her qubits.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | amount_to_transmit = 5
def alice(host):
for _ in range(amount_to_transmit):
s = 'Hi Eve.'
print("Alice sends: %s" % s)
host.send_classical('Eve', s, await_ack=True)
for _ in range(amount_to_transmit):
print("Alice sends qubit in the |1> state")
q = Qubit(host)
q.X()
host.send_qubit('Eve', q, await_ack=True)
def eve(host):
for i in range(amount_to_transmit):
alice_message = host.get_classical('Alice', wait=5, seq_num=i)
print("Eve Received classical: %s." % alice_message.content)
for i in range(amount_to_transmit):
q = host.get_qubit('Alice', wait=10)
m = q.measure()
print("Eve measured: %d." % m)
|
Now we want to program Bob who sits between Alice and Eve in the network to manipulate the content of the messages being sent between them. For packets that contain qubits, Bob performs an \(X\) operation on them, which will undo Alice’s \(X\) operation. For packets with classical messages, Bob changes the content so as to let the receiver know that he saw that message.
1 2 3 4 5 6 7 8 | def bob_sniffing_quantum(sender, receiver, qubit):
# Bob applies an X operation to all qubits that are routed through him
qubit.X()
def bob_sniffing_classical(sender, receiver, msg):
# Bob modifies the message content of all classical messages routed through him
msg.content = "** Bob was here :) ** " + msg.content
|
We set these protocols to the hosts via the following code:
1 2 3 4 5 6 7 8 | host_bob.q_relay_sniffing = True
host_bob.q_relay_sniffing_fn = eve_sniffing_quantum
host_bob.c_relay_sniffing = True
host_bob.c_relay_sniffing_fn = bob_sniffing_classical
t1 = host_alice.run_protocol(alice)
t2 = host_eve.run_protocol(eve)
|
We should see the following output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | Alice sends: Hi Eve.
Eve Received classical: ** Bob was here :) ** Hi Eve..
Alice sends: Hi Eve.
Eve Received classical: ** Bob was here :) ** Hi Eve..
Alice sends: Hi Eve.
Eve Received classical: ** Bob was here :) ** Hi Eve..
Alice sends: Hi Eve.
Eve Received classical: ** Bob was here :) ** Hi Eve..
Alice sends: Hi Eve.
Eve Received classical: ** Bob was here :) ** Hi Eve..
Alice sends qubit in the |1> state
Eve measured: 0.
Alice sends qubit in the |1> state
Eve measured: 0.
Alice sends qubit in the |1> state
Eve measured: 0.
Alice sends qubit in the |1> state
Eve measured: 0.
Alice sends qubit in the |1> state
Eve measured: 0.
|
The full example is below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | from qunetsim.components import Host
from qunetsim.components import Network
from qunetsim.objects import Message
from qunetsim.objects import Qubit
from qunetsim.objects import Logger
Logger.DISABLED = True
amount_transmit = 5
def alice(host):
for _ in range(amount_transmit):
s = 'Hi Eve.'
print("Alice sends: %s" % s)
host.send_classical('Eve', s, await_ack=True)
for _ in range(amount_transmit):
print("Alice sends qubit in the |1> state")
q = Qubit(host)
q.X()
host.send_qubit('Eve', q, await_ack=True)
def bob_sniffing_quantum(sender, receiver, qubit):
# Bob applies an X operation to all qubits that are routed through him
qubit.X()
def bob_sniffing_classical(sender, receiver, msg):
# Bob modifies the message content of all classical messages routed through him
if isinstance(msg, Message):
msg.content = "** Bob was here :) ** " + msg.content
def eve(host):
for i in range(amount_transmit):
alice_message = host.get_classical('Alice', wait=5, seq_num=i)
print("Eve Received classical: %s." % alice_message.content)
for i in range(amount_transmit):
q = host.get_qubit('Alice', wait=10)
m = q.measure()
print("Eve measured: %d." % m)
def main():
network = Network.get_instance()
nodes = ["Alice", "Bob", "Eve"]
network.start(nodes)
network.delay = 0.0
host_alice = Host('Alice')
host_alice.add_connection('Bob')
host_alice.start()
host_bob = Host('Bob')
host_bob.add_connection('Alice')
host_bob.add_connection('Eve')
host_bob.start()
host_eve = Host('Eve')
host_eve.add_connection('Bob')
host_eve.delay = 0.2
host_eve.start()
network.add_host(host_alice)
network.add_host(host_bob)
network.add_host(host_eve)
host_bob.q_relay_sniffing = True
host_bob.q_relay_sniffing_fn = eve_sniffing_quantum
host_bob.c_relay_sniffing = True
host_bob.c_relay_sniffing_fn = bob_sniffing_classical
t1 = host_alice.run_protocol(alice)
t2 = host_eve.run_protocol(eve)
t1.join()
t2.join()
network.stop(True)
exit()
if __name__ == '__main__':
main()
|