TEXT – QKD (Week 2)#

Generating a secret key#

The next step of the experiment will be using the BB84 protocol to generate a secret key. You should be familiar with BB84 from your prsrequisite course, although there are links below to various resources describing the protocol. This text is intended to help you understand what the protocol aims to do and how it works. The pre-lab questions are brief and are located at the bottom of the page.

This text covers the following topics:

One time pad encryption#

One time pad encryption is a perfectly secure means of communicating a message. Alice takes the original message, the raw text, and encrypts it with a pad of random bits the same length as the message, resulting in the ciphertext. Alice transmits the ciphertext through a public channel to Bob. The channel is public because an eavesdropper Eve is able to intercept the entire message. Once Bob receives the ciphertext, he decrypts the ciphertext using the same pad Alice used initially. This allows him to read the original message.

The benefit of OTP is its security: it’s impossible for an eavesdropper to decode the message.

The drawbacks are the key distribution. You need a key that’s the same length as the message. Additionally, you need a new key for every message you want to encrypt and send: the protocol is only secure when each pad is used only once.

Thus, the challenge is generating and distributing a new key for each message. This is the gap that QKD aims to fill.

The code cell below is designed as a very basic tutorial for how OTP works. Encrypting and decrypting a message is simple: bitwise XOR with the key. If you XOR the raw message with the key, you get the ciphertext. Then if you XOR the cypher test with the key, you get the initial message back.

import numpy as np

LENGTH = 10;
# Generate a random message
mess = np.random.randint(low = 0, high = 2, size = (LENGTH,))

# Generate a random key
key = np.random.randint(low = 0, high = 2, size = (LENGTH,))

# Generate the ciphertext by performing bitwise XOR on the key and the message
cypher = mess^key

# Recover the original message by performing bitwise XOR on the cypher
# and the key
recover = cypher^key

print("Message: % s" %(mess))
print("Key    : % s" %(key))
print("Now XOR those to get the cyphertext:")
print("Cypher : % s" %(cypher))
print("To recover the original message, you XOR the key and the cypher")
print("Key    : % s" %(key))
print("Cypher : % s" %(cypher))
print("The recovered message after decryption is")
print("Decrypt: % s" %(recover))
print("Compare with original message")
print("Message: % s" %(mess))
Message: [0 0 0 1 1 1 1 1 0 0]
Key    : [1 0 0 0 1 0 1 0 1 0]
Now XOR those to get the cyphertext:
Cypher : [1 0 0 1 0 1 0 1 1 0]
To recover the original message, you XOR the key and the cypher
Key    : [1 0 0 0 1 0 1 0 1 0]
Cypher : [1 0 0 1 0 1 0 1 1 0]
The recovered message after decryption is
Decrypt: [0 0 0 1 1 1 1 1 0 0]
Compare with original message
Message: [0 0 0 1 1 1 1 1 0 0]

Description of BB84 protocol#

BB84 is the first QKD protocol, so there are a lot of great resources available to describe it. I’ll include a few here. You don’t have to read all of them, but make sure you understand what makes the protocol secure, how it’s related to quantum mechanics, and what the procedure of the protocol is.

The original BB84 paper lays out the protocol in an accessible and concise way. Section III is the most important part of the paper because it’s where the authors walk through the protocol.

quTools also providesa manual on performing the QKD experiment with the quED. The BB84 protocol is described on pages 8 through 11.

If you’d prefer to watch a video, there’s a lecture from the University of Waterloo’s Institute of Quantum Computing. Starting from 13:00 to about 21:00 is a walk-through of the QKD protocol.

%%HTML
<iframe width="560" height="315" src="https://www.youtube.com/embed/ToOLbdrWst4?start=783" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

Python simulation#

The following code simulates a BB84 set-up. This is being provided to you so that you can look at the effects of Eve’s instrusion and the effects of loss. You can set the number of photons Alice sends as NN, the transmission from Alice to Bob as TT, and Eve’s intrustion as FE.

import numpy as np
import random

# How many photons does Alice send?
NN = 1000

# What is the transmission between Alice and Bob? 
# Transmission of 1 implies there's no loss at all
# Transmission of 0 implies Eve is blocking the Alice to Bob channel
TT = 0.9

# How often does Eve listen in? 0 is never, 1 is always
FE = 0.1

# Initialize arrays

# What bits did Alice's transmitted message send?
bits_tx = np.zeros((NN)) - 1
# What polarization did Alice use?
pol_tx = np.zeros((NN)) - 1

# Did the photon make it?
photon_rx = np.zeros((NN)) - 1
# Bob's measurement basis
pol_rx = np.zeros((NN)) - 1
# Bob's received photons
bits_rx = np.zeros((NN)) - 1

# Did Eve interefere?
Eve_rx = np.zeros((NN)) - 1
Eve_pol = np.zeros((NN)) - 1
Eve_bit = np.zeros((NN)) - 1



for i in range (NN):
    # Alice generates a random bit to send
    bit_A = random.randint(0,1)
    bits_tx[i] = bit_A
    # Now she selects a basis
    bas_A = random.randint(0,1)
    pol_tx[i] = bas_A
    
   # Now decide if Eve does something
    if random.random() <= FE: # if Eve -DOES- decide to eavesdrop & send
        Eve_rx[i] = 1 # Record that this is an occurence of Eve eavesdropping
        Eve_bas = random.randint(0,1) # She randomly selects a basis
        Eve_pol[i] = Eve_bas
        if Eve_bas == bas_A: # If her basis matches Alice's
            Eve_bit[i] = bit_A # Then she recovers the bit perfectly
        else:
            Eve_bit[i] = random.randint(0,1) # otherwise, it's a coin toss   
        bit_rx = Eve_bit[i] # Now the bit Bob receives will be the bit Eve sends
        bas_rx = Eve_bas # In the basis that Eve sends
    else: # If Eve isn't measuring and sending out photons
        pho_E = 0 # Mark this as no Eve involvement
        bit_rx = bit_A # The bit Bob receives is ths bit Alice sends
        bas_rx = bas_A # in the basis in which Alice sent it
        
    # If the photon makes it through the loss channel
    if random.random() <= TT:
        photon_rx[i] = 1
        bas_B = random.randint(0,1) # Bob randomly selects a basis
        pol_rx[i] = bas_B
        if bas_B == bas_rx:
            bit_B = bit_rx
        else:
            bit_B = random.randint(0,1)
        bits_rx[i] = bit_B
    else:
        photon_rx[i] = 0;

# now do some processing


# First limit ourselves to cases where Alice and Bob used the same bases
ix = np.array([np.where(pol_tx == pol_rx)])
bits_tx_sifted = np.array(bits_tx[ix])
bits_tx_sifted = bits_tx_sifted[0,0]
bits_rx_sifted = np.array(bits_rx[ix])
bits_rx_sifted = bits_rx_sifted[0,0]

# Now look bit error rate (BER)
errors = (bits_tx_sifted != bits_rx_sifted).astype(int)
errors_total = errors.sum()
usable_key = ix.size - errors_total
BER = 1.0/ix.size * errors.sum()

# What did Eve get?
ixe = np.array([np.where((Eve_rx ==1) & (Eve_pol == pol_tx))])


print("Alice sent Bob % d bits"% NN)
print("Bob received % d bits"% photon_rx.sum())
print("They used the same basis in %d of those bits" %ix.size)
print("This resulted in a total of %d bits without errors" %usable_key)
print("The BER was %10.2E" %BER)
print("Eve got %d bits" %ixe.size)
Alice sent Bob  1000 bits
Bob received  909 bits
They used the same basis in 407 of those bits
This resulted in a total of 396 bits without errors
The BER was   2.70E-02
Eve got 48 bits

Based on this code, we see that as Eve listens in more often, she receives more bits of the key and Alice and Bob see more errors. Additionally, the loss of the system doesn’t contribute to errors.

Introduction to Ekert protocol#

BB84 is possibly the most well-known QKD protocol, but there are others. One important protocol is Ekert 91, which was published in 1991. Its main difference from BB84 is that it relies on the correlation of entangled photons. In this protocol, Alice and Bob each get one photon from a source of entangled photons and then do independent measurements on the polarization of their photon and report back which basis they used - either horizontal-vertical or diagonal-antidiagonal.

Artur Ekert, who first publised the protocol, has made many YouTube videos on quantum information in general and QKD in particular. He teaches a class whose lecture materials are available online, and the QKD lectures are gathered together. For this text, I’ve embedded one short video where Ekert walks through the protocol. You’ll note that he uses X and Z measurements on qubits. This is analogous to measuring the polarization in either the horizontal-vertical or diagonal-antidiagonal basis of linearly polarized photons.

%%HTML
<iframe width="560" height="315" src="https://www.youtube.com/embed/2ExG7UJgfmQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

Pre-Lab questions#

  1. What makes B84 secure?

  2. When Eve interferes on every bit, what is the resulting BER?

  3. Why is it important that Alice only sends Bob 1 photon at a time?