由於BB84協議中有古典通道可以驗證,因此Espian不能用MITM的手段,假裝自己是合法用戶。
因此他可以用另一種策略,對量子位元進行攔截重發攻擊。
但這種攻擊手段可以透過QBER計算破解。
Espian 攔截 Asja 發送給 Balvis 的量子位並以隨機選擇的base對其進行測量,因為他沒有的資訊。
Espian 無法在沒有測量的情況下攔截量子位,這會改變狀態和訊息。大量丟失的量子位元將暴露他的存在,並將迫使用戶切換到另一個頻道。他需要為他攔截的所有回合發送“假”狀態,因此Balvis將收到量子位,認為這些來自Asja。
但是由於Espian不知道的資訊,他最好的策略是將「假」狀態編碼為,根據他的測量結果並將這些量子位元發送給Balvis。
例如:
# import all necessary objects and methods for quantum circuits
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, execute, Aer
from random import randrange
#Source: awards/teach_me_qiskit_2018/cryptography/Cryptography.ipynb
def SendState(qc1, qc2, qc1_name):
''' This function takes the output of a circuit qc1 (made up only of x and
h gates and initializes another circuit qc2 with the same state
'''
# Quantum state is retrieved from qasm code of qc1
qs = qc1.qasm().split(sep=';')[4:-1]
# Process the code to get the instructions
for index, instruction in enumerate(qs):
qs[index] = instruction.lstrip()
# Parse the instructions and apply to new circuit
for instruction in qs:
if instruction[0] == 'x':
if instruction[5] == '[':
old_qr = int(instruction[6:-1])
else:
old_qr = int(instruction[5:-1])
qc2.x(qreg[old_qr])
elif instruction[0] == 'h':
if instruction[5] == '[':
old_qr = int(instruction[6:-1])
else:
old_qr = int(instruction[5:-1])
qc2.h(qreg[old_qr])
elif instruction[0] == 'm': # exclude measuring:
pass
else:
raise Exception('Unable to parse instruction')
def print_outcomes_in_reserve(counts): # takes a dictionary variable
for outcome in counts: # for each key-value in dictionary
reverse_outcome = ''
for i in outcome: # each string can be considered as a list of characters
reverse_outcome = i + reverse_outcome # each new symbol comes before the old symbol(s)
return reverse_outcome
def split_list(bit_string, parts=1):
length = len(bit_string)
return [ bit_string[i*length // parts: (i+1)*length // parts]
for i in range(parts) ]
qreg = QuantumRegister(24)
creg = ClassicalRegister(24)
asja = QuantumCircuit(qreg, creg, name='Asja')
send=[] #Initial bit string ot send
asja_basis=[]
balvis_basis=[]
espian_basis=[]
#Creating random bit string
for i in range(24):
bit = randrange(2)
send.append(bit)
#Asja preparing qubits
for i, n in enumerate(send):
if n==1:
asja.x(qreg[i]) # apply x-gate
#Asja encoding
for i in range(24):
r=randrange(2)
if r==0: #if bit is 0, then she encodes in Z basis
asja_basis.append('Z')
else: #if bit is 1, then she encodes in X basis
asja.h(qreg[i])
asja_basis.append('X')
espian = QuantumCircuit(qreg, creg, name='Espian') #Defining Espian circuit
SendState(asja, espian, 'Asja') #Asja sends states to Espian
#Espian intercepts and measures qubits
for i in range(24):
r=randrange(2) #Randomly pick a basis
if r==0: #if bit is 0, then measures in Z basis
espian.measure(qreg[i],creg[i])
espian_basis.append('Z')
else: #if bit is 1, then measures in X basis
espian.h(qreg[i])
espian.measure(qreg[i],creg[i])
espian_basis.append('X')
job = execute(espian,Aer.get_backend('qasm_simulator'),shots=1) #Espian has only has one shot to measure qubits
counts = job.result().get_counts(espian) # counts is a dictionary object in python
counts = print_outcomes_in_reserve(counts)
espian_received = list(map(int, counts)) #Saving Espian received string as a list
#Espian preparing fake states
espian_fake = QuantumCircuit(qreg, creg, name='Espian_fake')
for i, n in enumerate(espian_received): #if measured bit is 1 - apply X gate
if n==1:
espian_fake.x(qreg[i]) # apply x-gate
for i, n in enumerate(espian_basis):
if i == 'X': #if Espian used X basis to measure qubit, she applies H gate for same round
espian_fake.h(qreg[i])
else:
pass
balvis = QuantumCircuit(qreg, creg, name='Balvis') #Defining Balvis circuit
SendState(espian_fake, balvis, 'Espian') #Espian sends states to Balvis
#Balvis receives qubits
for i in range(24):
r=randrange(2) #Randomly pick a basis
if r==0: #if bit is 0, then measures in Z basis
balvis.measure(qreg[i],creg[i])
balvis_basis.append('Z')
else: #if bit is 1, then measures in X basis
balvis.h(qreg[i])
balvis.measure(qreg[i],creg[i])
balvis_basis.append('X')
job_b = execute(balvis,Aer.get_backend('qasm_simulator'),shots=1) #Balvis has only has one shot to measure qubits
counts_b = job_b.result().get_counts(balvis) # counts is a dictionary object in python
counts_b = print_outcomes_in_reserve(counts_b)
received = list(map(int, counts_b)) #Saving Balvis received string as a list
#Sifting
asja_key=[] #Asjas register for matching rounds
balvis_key=[] #Balvis register for matching rounds
for j in range(0,len(asja_basis)): #Going through list of bases
if asja_basis[j] == balvis_basis[j]: #Comparing
asja_key.append(send[j])
balvis_key.append(received[j]) #Keeping key bit if bases matched
else:
pass #Discard round if bases mismatched
#QBER
rounds = len(asja_key)//3
errors=0
for i in range(rounds):
bit_index = randrange(len(asja_key))
tested_bit = asja_key[bit_index]
if asja_key[bit_index]!=balvis_key[bit_index]: #comparing tested rounds
errors=errors+1 #calculating errors
del asja_key[bit_index] #removing tested bits from key strings
del balvis_key[bit_index]
QBER=errors/rounds #calculating QBER
QBER=round(QBER,2) #saving the answer to two decimal places
print("QBER value =", QBER)
print("Asja's secret key =", asja_key)
print("Balvis' secret key =", balvis_key)
QBER value = 0.67
Asja's secret key = [1, 1, 0, 1, 1, 1, 0, 1]
Balvis' secret key = [0, 1, 1, 1, 0, 1, 0, 1]
從QBER的結果可以知道,Espian的攻擊手段被發現了。
因此,QBER 有助於驗證量子位元交換期間竊聽者的存在。
參考資料:womanium 教材