長らく開きましたが,B92プロトコルを勉強しました.
今回使ったコードのディレクトリ
概要
かなり前に BB84プロトコル を扱いましたが,今回はその改善版である B92プロトコルを扱います.
量子鍵配送は盗聴を検知することができ,その内容を盗聴されることなく安全に情報を伝達できるプロトコルです.
今回は実装で参考にできるものがなかったので, M. A. Nielsen and I.L. Chuang: ``Quantum Computation and Quantum Information'',Cambridge University Press,2000. の和訳版III を参照しました
B92プロトコルの概要
i). Alice はランダムなビット列を選ぶ
ii). Alice はビットを使って、量子ビット列上にエンコードし、Bob に送信する
iii). Bob はランダムなビット列を使って、Alice のメッセージを測定する
iv). Bob の測定結果から,Alice と Bob で秘密鍵を共有する
v). Alice と Bob は鍵のランダムサンプリングを比較する
B84 プロトコル との違いは,Alice側は基底を1つ用意すれば十分ということです.
実装
以下,100量子ビットで固定して seed $= 0$ とします.
# preprocessing
from qiskit import QuantumCircuit, Aer, transpile, assemble
from qiskit.visualization import plot_histogram, plot_bloch_multivector
from numpy.random import randint
import numpy as np
np.random.seed(seed=0)
# fix 100 quantum bits
n = 100
i)
# Step 1
## Alice choose random bit sequence
alice_bits = randint(2, size=n)
ii)
## Step 2
### Alice はビットを使って、量子ビット列上にエンコードし、Bob に送信する
def encode_message(bits):
message = []
for i in range(n):
qc = QuantumCircuit(1,1)
if bits[i] == 0:
pass
else:
qc.h(0)
qc.barrier()
message.append(qc)
return message
iii)
## Step 3
### Bob はランダムなビット列を使って、Alice のメッセージを測定する
def measure_message(message, bits):
backend = Aer.get_backend('aer_simulator')
measurements = []
for q in range(n):
if bits[q] == 0: # measuring in Z-basis
message[q].measure(0,0)
else: # measuring in X-basis
message[q].h(0)
message[q].measure(0,0)
aer_sim = Aer.get_backend('aer_simulator')
qobj = assemble(message[q], shots=1, memory=True)
result = aer_sim.run(qobj).result()
measured_bit = int(result.get_memory()[0])
measurements.append(measured_bit)
return measurements
iv)
## Step 4
### Bob の測定結果から,Alice と Bob で秘密鍵を共有する
### Alice と Bob のビットのうち,Bob の測定結果で1のインデックスの箇所の要素を格納する
def remove_garbage(bases, bits):
good_bits = []
for q in range(n):
if bits[q] == 1:
good_bits.append(bases[q])
return good_bits
v)
## Step 5
### Alice と Bob は鍵のランダムサンプリングを比較する
def sample_bits(bits, selection):
sample = []
for i in selection:
# use np.mod to make sure the bit we sample is always in the list range
i = np.mod(i, len(bits))
# pop(i) removes the element of the list at index 'i'
sample.append(bits.pop(i))
return sample
以上のサブルーチンを基にしたmain関数
def main():
# Step 1
## Alice choose random bit sequence
alice_bits = randint(2, size=n)
# Step 2
## Alice encodes quantum bit sequence by using classical bits, send Bob that
message = encode_message(alice_bits)
## 盗聴
### Eve はランダムな基底を使って、Alice のメッセージを盗聴(測定)する
eve_bases = randint(2, size=n)
intercepted_message = measure_message(message, eve_bases)
# Step 3
## Bob measures Alice's message by using random bases
bob_bases = randint(2, size=n)
bob_results = measure_message(message, bob_bases)
# Step 4
## Alice and Bob publish each bases and share the secret key
bob_key = remove_garbage(bob_bases, bob_results)
alice_key = remove_garbage(alice_bits, bob_results)
# Step 5
sample_size = 15
bit_selection = randint(n, size=sample_size)
bob_sample = sample_bits(bob_key, bit_selection)
print(" bob_sample = " + str(bob_sample))
alice_sample = sample_bits(alice_key, bit_selection)
print("alice_sample = "+ str(alice_sample))
アウトプットは例えば次のようになります.
bob_sample = [1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0]
alice_sample = [0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1]
BobがX基底で測定した箇所だけ残っていて,値が異なる部分しか見ていないので,上記のようにインデックスが同じ箇所の値が被っていないことが分かります.そして,これを秘密鍵として使えば良い,ということになります.
ちなみに ii) と iii) の間で Eve が次のように盗聴しようとしたとします.
## 盗聴
### Eve はランダムな基底を使って、Alice のメッセージを盗聴(測定)する
eve_bases = randint(2, size=n)
intercepted_message = measure_message(message, eve_bases)
このとき,最後に測定される互いの鍵のサンプリングは次のようになります.
bob_sample = [1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1]
alice_sample = [1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1]
このようになり,同じインデックスで値が一致する箇所がそこそこあることが分かります.つまり,盗聴されている,ということが分かります.
まとめ
そろそろ Quantum Blockchain の理論的なことを扱うべく,先に有名なプロトコルは抑えようと思って,B92プロトコルを勉強しました.今回でBB84プロトコルの復習とB92プロトコルがどのようなものかは大体分かった気がします.
そのうち,E91プロトコルも勉強したら,Quantum Blockchain の理論に入っていきます.