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.

100 lines
4.0 KiB

import json
import os.path
3 years ago
from alice import Alice
from bob import Bob
from channel import ChannelSym
3 years ago
from threading import Thread
import typing
import sympy as sp
3 years ago
from eve import EveBS
def run_qkd(alice: Alice, bob: Bob, n: int = 1000):
3 years ago
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))