BB84でノイズが入ると,結果にどんな影響が現れるのか,qiskitを用いて実験してみました.
BB84について
AliceとBobで乱数を共有したい状況を考えます.Aliceは送りたいビットが$0$ならば$|0\rangle,|+\rangle$を,$1$ならば$|1\rangle,|-\rangle$をランダムに準備し,Bobに送ります.Bobは$Z$測定か$X$測定をランダムに行い,その結果から$0$か$1$かを判定します.この後に,Aliceが準備した状態が固有状態となる演算子1と,Bobが測定した演算子を公開し,これらが一致したタイミングの結果のみを保存します.
詳細はBB84をQiskitで実装してみたに記載されていますので,参考にしてみてください.
ノイズについて
Aliceが状態を作る段階で,ゲート操作が入ります.そこに自作の量子ノイズを追加します.
実験
コードはBB84をQiskitで実装してみたを現在のQiskitに対応するように作り直し,またノイズを追加するように変更しました.
class Person(object):
def __init__(self, message_length):
self.message_length = message_length
# 任意の2進数を生成する。
def generate_bit(self):
bits_list = [random.randint(0, 1) for _ in range(self.message_length)]
return ''.join(map(str, bits_list))
# キーを生成する
def generate_key(self, bits1, bits2, target):
key = []
x = format(int(bits1, 2) ^ int(bits2, 2), 'b').zfill(self.message_length)
for i in range(self.message_length):
if '0' == x[i]:
key.append(int(target[i]))
else:
key.append(2)
return key
class Alice(Person):
# 初期化
def __init__(self, message_length, error_prob, error_type):
self.error_prob = error_prob
self.error_type = error_type
super().__init__(message_length)
# Aliceのaを生成する (Aliceの準備 準備1 2つの2進数の生成)
def generate_message_and_basis(self):
self.message = super().generate_bit()
self.basis = super().generate_bit()
# Aliceはa,bをもとに量子状態を生成する (Aliceの準備 準備2 量子状態の生成)
def make_quantum_circuit(self):
# 量子回路を準備
self.quantum_register = QuantumRegister(self.message_length, 'q_a')
self.quantum_circuit = QuantumCircuit(self.quantum_register)
self.quantum_circuit = self._generate_qubit(self.quantum_circuit, self.quantum_register, self.message, self.basis, self.message_length, self.error_prob)
return self.quantum_circuit
# 量子状態を生成する
def _generate_qubit(self, quantum_circuit, quantum_register, message, basis, message_length, error_prob):
if self.error_type == "amp_damp":
error = amp_damp_noise(error_prob)
elif self.error_type == "dephase":
error = dephasing_noise(error_prob)
elif self.error_type == "depolar":
error = depolarizing_noise(error_prob)
for i in range(message_length):
if '0' == message[message_length - 1 - i]:
if '1' == basis[message_length - 1 - i]:
# |+>
quantum_circuit.h(quantum_register[i])
quantum_circuit.append(error, [quantum_register[i]])
else:
if '0' == basis[message_length - 1 - i]:
# |1>
quantum_circuit.x(quantum_register[i])
quantum_circuit.append(error, [quantum_register[i]])
else:
# |->
quantum_circuit.x(quantum_register[i])
quantum_circuit.append(error, [quantum_register[i]])
quantum_circuit.h(quantum_register[i])
quantum_circuit.append(error, [quantum_register[i]])
quantum_circuit.barrier(quantum_register)
return quantum_circuit
class Bob(Person):
# 初期化
def __init__(self, message_length):
super().__init__(message_length)
# Bobのbを生成する (Bobによる測定 準備 1つの2進数を生成)
def generate_basis(self):
self.basis = super().generate_bit()
# 量子状態を受信する (AliceからBobへ量子状態の送信)
def recieve_alice_circuit(self, alice_quantum_circuit):
# 量子回路を準備
self.classical_register = ClassicalRegister(self.message_length, 'c_b')
self.quantum_register = QuantumRegister(self.message_length, 'q_b')
self.quantum_circuit = QuantumCircuit(self.quantum_register, self.classical_register)
self.quantum_circuit = alice_quantum_circuit.compose(self.quantum_circuit)
# Bobによる測定 (Bobによる測定 測定)
def measure_qubit(self):
for i in range(self.message_length):
if '0' == self.basis[self.message_length - 1 - i]:
self._z_measure(self.quantum_circuit, i, self.classical_register[i])
else:
self._x_measure(self.quantum_circuit, i, self.classical_register[i])
result = execute(self.quantum_circuit, Aer.get_backend('qasm_simulator')).result()
result_count = result.get_counts()
self.result_bob = random.choice(list(result_count.keys()))
return self.result_bob
# Z測定を行う
def _z_measure(self, qc, qr, cr):
qc.measure(qr, cr)
# X測定を行う
def _x_measure(self, qc, qr, cr):
qc.h(qr)
qc.measure(qr, cr)
実際に各ノイズが入るとどの程度エラーが入るか見てみます.今回は4000量子ビット用意し,それをAliceからBobに送っています2.基底照合で25%のシフト鍵が残るので,平均1000ビットの乱数が共有されているという状況です.
実際のBB84では,ノイズもしくは盗聴者がいる場合,このように共有した乱数が一致しないため,誤り訂正,秘匿性増強を行うプロセスが入ります3.また,鍵エラー率が11%以下であれば誤り訂正・秘匿性増強を用いることで,情報理論的安全な通信が可能となることが知られています3.これより,どのノイズの種類に対しても,ノイズの大きさが十分小さくなくてはならないことが分かります.
鍵エラー率が単調に増加すると思っていましたが,そうなっていないのは,鍵長が短いからだと思われます4.
最後に
今回はノイズを含むBB84について計算してみました.
Version Information
Software | Version |
---|---|
qiskit | 0.45.0 |
System information | |
---|---|
Python version | 3.10.12 |
-
つまり,Aliceが$|0\rangle,|1\rangle$を準備した場合は$Z$,$|+\rangle,|-\rangle$を準備した場合は$X$が対応する.どちらの演算子に対応する状態をBobに送ったかを公開する. ↩
-
また,ノイズによってAliceとBobの共有した乱数がどの程度異なるか調べたいので,乱数の長さは長くしました.Qiskitでは1量子ビットゲートしか使わなくても,量子ビット数が増えるとシミュレーション時間が膨大になるみたいなので,10量子ビットでの実験を何回も繰り返すようにしました. ↩
-
量子通信と量子鍵配布(PDF).この誤り訂正や秘匿性増強のコードか,それに関する記事などあれば教えてください. ↩ ↩2
-
本当は分散も表示したほうが良いです.気が向いたら更新します. ↩