Quantum Cryptography BB84 simulation
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

99 lines
4.0 KiB

import json
import os.path
from alice import Alice
from bob import Bob
from channel import ChannelSym
from threading import Thread
import typing
import sympy as sp
from eve import EveBS
def run_qkd(alice: Alice, bob: Bob, n: int = 1000):
alice_thread = Thread(target=lambda: alice.generate_key(n))
bob_thread = Thread(target=lambda: bob.generate_key(n))
alice_thread.start()
bob_thread.start()
while alice_thread.is_alive() or bob_thread.is_alive():
pass
def get_e_and_r(alice, bob, n=1000) -> typing.Tuple[float, float]:
return 1 - sum(k1 == k2 for k1, k2 in zip(alice.key, bob.key)) / len(alice.key), len(alice.key) / n
channel_parameters = {'p_opt': 0.05, 'p_dc': 0.05, 'mu': 1, 'detector_sensitivity': 0.8, 'transmittance': 0.8}
PAR_NAMES = {'p_opt': 'p_{opt}', 'p_dc': 'p_{dc}', 'mu': r'\mu', 'detector_sensitivity': r'\eta', 'transmittance': 't'}
mu, t, p_dc, p_opt, eta = sp.symbols(r'\mu t p_{dc} p_{opt} \eta')
e_theory = 0.5 * (p_dc + p_opt * mu * t * eta) / (2 * p_dc + mu * t * eta)
q_theory = (mu * t * eta + 2 * p_dc) / 2 * (1 - e_theory * 2)
def plot(parameter, values, add_eve: bool = False):
data_r, data_e = [], []
data_r_theoretical, data_e_theoretical = [], []
parameters_sp = {PAR_NAMES[pname]: channel_parameters[pname] for pname in PAR_NAMES.keys()}
n = 10000
for val in values:
print(val)
channel = ChannelSym(**{parameter: val})
alice, bob = Alice(channel), Bob(channel)
if add_eve:
eve = EveBS()
channel.eve = eve
run_qkd(alice, bob, n)
e, r = get_e_and_r(alice, bob, n)
data_r.append(r)
data_e.append(e)
parameters_sp[PAR_NAMES.get(parameter, parameter)] = val
data_r_theoretical.append(float(q_theory.evalf(subs=parameters_sp)))
data_e_theoretical.append(float(e_theory.evalf(subs=parameters_sp)))
from matplotlib import pyplot as plt
plt.plot(values, data_r, label='$R$')
plt.plot(values, data_e, label='$E$')
plt.plot(values, data_r_theoretical, label='$R_{theory}$')
plt.plot(values, data_e_theoretical, label='$E_{theory}$')
plt.legend()
if not os.path.exists('output'):
os.mkdir('output')
with open(f'output/dep_{parameter}.json', 'w') as f:
f.write(json.dumps([list(values), data_r, data_e, data_r_theoretical, data_e_theoretical]))
plt.xlabel('$' + PAR_NAMES.get(parameter, parameter) + '$')
plt.title('$R$ and $E$ vs. $' + PAR_NAMES.get(parameter, parameter) + '$' + ' with Eve' * add_eve)
plt.savefig(f'output/dep_{parameter}.png')
plt.show()
def run_one():
N = 1000
channel = ChannelSym()
alice, bob = Alice(channel), Bob(channel)
run_qkd(alice, bob)
# print(list(map(int, alice.key)))
# print(list(map(int, bob.key)))
print('Alice bits: ', *list(map(int, alice.sent)))
print('Bob bits: ',
*list(map(lambda t: {(0, 1): 1, (1, 0): 0, (0, 0): 2, (1, 1): 3}[(int(t[0]), int(t[1]))], bob.my_results)))
print('Alice basises:', *list(map(int, alice.my_basises)))
print('Bob basises: ', *list(map(int, bob.my_basises)))
bob_correctness = [left + right == 1 for left, right in bob.my_results]
print(' ', *[
int(k) if c and b1 == b2 else ' '
for c, k, b1, b2 in zip(bob_correctness, alice.sent, bob.my_basises, alice.my_basises)])
print(' ', *[
{(0, 1): 1, (1, 0): 0, (0, 0): 2, (1, 1): 3}[(int(k[0]), int(k[1]))] if c and b1 == b2 else ' '
for c, k, b1, b2 in zip(bob_correctness, bob.my_results, bob.my_basises, alice.my_basises)])
print(
f'{100 * sum(k1 == k2 for k1, k2 in zip(alice.key, bob.key)) / len(alice.key):.2f}%, '
f'key length: {len(alice.key)}')
e, r = get_e_and_r(alice, bob, N)
print(f'E: {e * 100:.1f}%, R: {r}')
if __name__ == '__main__':
import numpy as np
plot('p_dc', np.arange(0, 0.1, 0.01))
plot('detector_sensitivity', np.arange(0.5, 1, 0.05))
plot('mu', np.arange(0.5, 1.5, 0.1))