-
Notifications
You must be signed in to change notification settings - Fork 57
/
Copy pathbb84.py
117 lines (93 loc) · 3.46 KB
/
bb84.py
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/bin/env python
# -*- coding: utf-8 -*-
##
# bb84.py: Defines and runs a simulation of the BB84 protocol for quantum key
# distribution. Uses the single qubit simulator defined in simulator.py,
# and the interface to the simulator defined in interface.py.
##
# Copyright (c) Sarah Kaiser and Chris Granade.
# Code sample from the book "Learn Quantum Computing with Python and Q#" by
# Sarah Kaiser and Chris Granade, published by Manning Publications Co.
# Book ISBN 9781617296130.
# Code licensed under the MIT License.
##
from interface import QuantumDevice, Qubit
from simulator import SingleQubitSimulator
from typing import List
def sample_random_bit(device: QuantumDevice) -> bool:
with device.using_qubit() as q:
q.h()
result = q.measure()
q.reset()
return result
def prepare_message_qubit(message: bool, basis: bool, q: Qubit) -> None:
if message:
q.x()
if basis:
q.h()
def measure_message_qubit(basis: bool, q: Qubit) -> bool:
if basis:
q.h()
result = q.measure()
q.reset()
return result
def convert_to_hex(bits: List[bool]) -> str:
return hex(int(
"".join(["1" if bit else "0" for bit in bits]),
2
))
def send_single_bit_with_bb84(
your_device: QuantumDevice,
eve_device: QuantumDevice
) -> tuple:
[your_message, your_basis] = [
sample_random_bit(your_device) for _ in range(2)
]
eve_basis = sample_random_bit(eve_device)
with your_device.using_qubit() as q:
prepare_message_qubit(your_message, your_basis, q)
# QUBIT SENDING...
eve_result = measure_message_qubit(eve_basis, q)
return ((your_message, your_basis), (eve_result, eve_basis))
def simulate_bb84(n_bits: int) -> list:
your_device = SingleQubitSimulator()
eve_device = SingleQubitSimulator()
key = []
n_rounds = 0
while len(key) < n_bits:
n_rounds += 1
((your_message, your_basis), (eve_result, eve_basis)) = \
send_single_bit_with_bb84(your_device, eve_device)
if your_basis is eve_basis:
assert your_message is eve_result
key.append(your_message)
print(f"Took {n_rounds} rounds to generate a {n_bits}-bit key.")
return key
def apply_one_time_pad(message: List[bool], key: List[bool]) -> List[bool]:
return [
message_bit ^ key_bit
for (message_bit, key_bit) in zip(message, key)
]
if __name__ == "__main__":
print("Generating a 96-bit key by simulating BB84...")
key = simulate_bb84(96)
print(f"Got key {convert_to_hex(key)}.")
message = [
1, 1, 0, 1, 1, 0, 0, 0,
0, 0, 1, 1, 1, 1, 0, 1,
1, 1, 0, 1, 1, 1, 0, 0,
1, 0, 0, 1, 0, 1, 1, 0,
1, 1, 0, 1, 1, 0, 0, 0,
0, 0, 1, 1, 1, 1, 0, 1,
1, 1, 0, 1, 1, 1, 0, 0,
0, 0, 0, 0, 1, 1, 0, 1,
1, 1, 0, 1, 1, 0, 0, 0,
0, 0, 1, 1, 1, 1, 0, 1,
1, 1, 0, 1, 1, 1, 0, 0,
1, 0, 1, 1, 1, 0, 1, 1
]
print(f"Using key to send secret message: {convert_to_hex(message)}.")
encrypted_message = apply_one_time_pad(message, key)
print(f"Encrypted message: {convert_to_hex(encrypted_message)}.")
decrypted_message = apply_one_time_pad(encrypted_message, key)
print(f"Eve decrypted to get: {convert_to_hex(decrypted_message)}.")