量子アルゴリズム⑤　B92プロトコル

長らく開きましたが，B92プロトコルを勉強しました．
[今回使ったコードのディレクトリ](https://github.com/awlaplace/Quantum/tree/master/QKD/B92)

## 概要

[C. H. Bennett: ``Quantum cryptography using any two nonorthogonal states'', Physical review letters, 1992, 68.21: 3121.](https://www.infoamerica.org/documentos_pdf/bennett1.pdf)

かなり前に [BB84プロトコル](https://qiita.com/0917laplace/items/b2ad19c134d8a6afbb7d) を扱いましたが，今回はその改善版である B92プロトコルを扱います．
量子鍵配送は盗聴を検知することができ，その内容を盗聴されることなく安全に情報を伝達できるプロトコルです．
今回は実装で参考にできるものがなかったので， [M. A. Nielsen and I.L. Chuang: ``Quantum Computation and Quantum Information''，Cambridge University Press，2000.　の和訳版III](https://www.amazon.co.jp/-/en/%E3%83%9F%E3%82%AB%E3%82%A8%E3%83%AB-%E3%83%8B%E3%83%BC%E3%83%AB%E3%82%BB%E3%83%B3/dp/4274200094/ref=pd_lpo_1?pd_rd_w=DRsbA&content-id=amzn1.sym.d769922e-188a-40cc-a180-3315f856e8d6&pf_rd_p=d769922e-188a-40cc-a180-3315f856e8d6&pf_rd_r=YFWQBPF5PEKM0M35K0CV&pd_rd_wg=Kp7jM&pd_rd_r=b27562ee-fdeb-46db-b56d-7a9f33c43621&pd_rd_i=4274200094&psc=1) を参照しました

## B92プロトコルの概要

i). Alice はランダムなビット列を選ぶ
ii). Alice はビットを使って、量子ビット列上にエンコードし、Bob に送信する
iii). Bob はランダムなビット列を使って、Alice のメッセージを測定する
iv). Bob の測定結果から，Alice と Bob で秘密鍵を共有する
v). Alice と Bob は鍵のランダムサンプリングを比較する

[B84 プロトコル](https://qiita.com/drafts/b2ad19c134d8a6afbb7d) との違いは，Alice側は基底を1つ用意すれば十分ということです．

## 実装

以下，100量子ビットで固定して seed $= 0$ とします．

```python:B92_import.py
# 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)

```python:B92_step1.py
# Step 1
## Alice choose random bit sequence
alice_bits = randint(2, size=n)
```

ii)

```python:B92_step2.py
## 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)

```python:B92_step3.py
## 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)

```python:B92_step4.py
## 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)

```python:B92_step5.py
## 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関数

```python:B92.py
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 が次のように盗聴しようとしたとします．

```python:B92_intercept.py
## 盗聴
### 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 の理論に入っていきます．