Перейти до основного вмісту

Квантовий розподіл ключів

Для цього модуля Qiskit in Classrooms студентам потрібне робоче середовище Python із встановленими такими пакетами:

  • qiskit v2.1.0 або новіший
  • qiskit-ibm-runtime v0.40.1 або новіший
  • qiskit-aer v0.17.0 або новіший
  • qiskit.visualization
  • numpy
  • pylatexenc

Щоб налаштувати та встановити зазначені пакети, перегляньте посібник Встановлення Qiskit. Щоб запускати завдання на реальних квантових комп'ютерах, студентам потрібно створити обліковий запис IBM Quantum®, дотримуючись кроків із посібника Налаштування облікового запису IBM Cloud.

Цей модуль було протестовано і використав 5 секунд часу QPU. Це лише оцінка. Фактичне використання може відрізнятися.

# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit qiskit-aer qiskit-ibm-runtime
# Uncomment and modify this line as needed to install dependencies
#!pip install 'qiskit>=2.1.0' 'qiskit-ibm-runtime>=0.40.1' 'qiskit-aer>=0.17.0' 'numpy' 'pylatexenc'

Переглянь розбір модуля від Dr. Katie McCormick нижче або натисни тут, щоб подивитися на YouTube.


Вступ і мотивація

Існує нескінченно багато способів шифрування та дешифрування інформації, і буквально тисячі з них добре вивчені. Тут ми обмежимося дуже раннім і дуже простим методом шифрування, який називається «просте заміщення», щоб зосередитися на квантовій частині цього протоколу. Квантову частину можна адаптувати до багатьох інших протоколів із відносно невеликими змінами.

Просте заміщення

Шифрування за простим заміщенням — це таке, при якому одна буква або цифра замінюється іншою, так що існує відповідність 1:1 між буквами та цифрами в повідомленні й буквами та цифрами, що використовуються в зашифрованій послідовності. Прикладом із поп-культури є загадка-криптоцитата або криптограма, де цитата або фраза шифрується за допомогою простого заміщення, і гравець має її розшифрувати. Вони легко вирішуються, якщо достатньо довгі. Розглянь приклад:

R WVXRWVW GSZG R'W YVGGVI NZPV GSRH KIVGGB OLMT. GSZG DZB, KVLKOV DROO SZEV ZM VZHRVI GRNV HLOERMT RG. R SLKV R NZWV RG HRNKOV VMLFTS.

Люди, які вирішують такі загадки вручну, здебільшого використовують прийоми, пов'язані зі знанням структури мови оригінального повідомлення. Наприклад, в англійській мові єдині однолітерні слова, подібні до зашифрованого «R», — це «a» та «I». Подвоєні букви у, наприклад, «KIVGGB» можуть набувати лише певних значень. Є й тонші підказки, як-от те, що найпоширеніше слово, яке пасує до шаблону «GSZG», — це «that». Люди, які використовують код для розв'язання таких завдань, мають набагато більше варіантів, зокрема просте перебирання можливостей до відновлення англійського слова та подальше оновлення зі збереженням цього слова. Один простий, але потужний метод — це частотний аналіз букв, особливо коли повідомлення достатньо довге, щоб бути репрезентативною вибіркою англійської.

Контрольне запитання

Спробуй розшифрувати це сам, якщо хочеш, хоча це й не є обов'язковим для решти модуля. Натисни на стрілку нижче, щоб побачити повідомлення.

Відповідь:

I decided that I'd better make this pretty long. That way, people will have an easier time solving it. I hope I made it simple enough.

Наведений вище приклад пов'язаний із «ключем» — відображенням із зашифрованих до розшифрованих букв. У цьому випадку ключ такий:

  • A (не використовується, умовно назвемо Z)
  • B->Y
  • C (не використовується, умовно назвемо X)
  • D->W
  • E->V
  • F->U
  • ...

І так далі. М'яко кажучи, це поганий ключ. Ключі, в яких зашифровані та розшифровані букви є просто зрушеними версіями алфавіту (як A->B і B->C), називаються шифрами «зсуву Цезаря».

Зауваж, що їх дуже важко зламати, якщо вони короткі. Насправді, якщо вони дуже короткі, вони невизначені. Розглянь:

URYYP

Існує багато можливих варіантів розшифрування з різними ключами: HELLO, PETTY, HAPPY, JIGGY, STOOL. Чи можеш ти придумати інші?

Але якщо ти надсилатимеш багато таких повідомлень, врешті-решт шифрування буде зламано. Тому не варто використовувати один і той самий «ключ» надто часто. Найкраще — використовувати певне заміщення лише один раз. Не в одному повідомленні, а лише для одного символу! Тобто у тебе буде своя схема шифрування або ключ для кожного символу, що використовується в повідомленні, по порядку. Якщо ти хочеш надіслати повідомлення другу за допомогою такої схеми, вам обом знадобиться аркуш паперу (у старі добрі часи), на якому записано цей постійно мінливий ключ. Ти використовуєш його лише один раз. Це і є «одноразовий блокнот».

Одноразовий блокнот

Подивимося, як це працює, на прикладі. Можна робити це суто з буквами, але зазвичай їх переводять у числа, наприклад, присвоюючи A=0, B=1, C=2…. Припустимо, ми з тобою друзі, залучені до таємної діяльності, і ми поділилися блокнотом. В ідеалі ми б поділилися кількома блокнотами, але сьогоднішній такий:

EDGRPOJNCUWQZVMK…

Або, перетворюючи в числа за позицією в алфавіті:

4,3,6,17,15, 14, 9, 13, 2, 20, 22, 16, 25, 21, 12, 10…

Припустимо, я хочу передати тобі повідомлення:

«I love quantum!»

Або, еквівалентно:

8, 11, 14, 21, 4, 16, 20, 0, 13, 19, 20, 12

Ми не хочемо надсилати наведений вище код; це просте заміщення, яке зовсім не є безпечним. Ми хочемо якось поєднати це з нашим ключем. Поширений спосіб — додавання за модулем 26. Ми додаємо значення повідомлення до значення ключа, беручи mod 26, доки не досягнемо кінця повідомлення. Тоді ми надішлемо:

8+4 (mod 26) = 12, 11+3 (mod 26) = 14, 14+6 (mod 26) = 20, 21+17 (mod 26) = 12…

= 12, 14, 20, 12, 19, 4, 3, 13, 15, 13, 16, 2

Зауваж, що якщо хтось перехопить це і НЕ матиме ключа, розшифрувати його абсолютно неможливо! Навіть дві букви «u» у слові «quantum» закодовані різними числами! Перша — це 3, а друга — 16… в одному слові!

Отже, я надсилаю це тобі, а ти маєш той самий ключ, що й я. Ти скасовуєш додавання за модулем 26, яке, ти знаєш, я виконав:

12, 14, 20, 12, 19, 4, 3, 13, 15, 13, 16, 2

=(4+x1) (mod 26), (3+x2) (mod 26), (6+x3) (mod 26), (17+x4) (mod 26),…

Тож повідомлення x1, x2, x3, x4… має бути:

8, 11, 14, 21…

Нарешті, перетворюючи це в текст, отримаємо:

«I love quantum».

Це і є одноразовий блокнот.

Зауваж, що якщо ключ коротший за повідомлення, ми починаємо повторювати кодування. Це все одно була б складна задача дешифрування, але не неможлива, якщо повторень достатньо. Тому тобі потрібен довгий ключ (або «блокнот»).

примітка

У багатьох контекстах студенти вже знайомі з таким шифруванням, тому цю діяльність можна пропустити. Але це відносно швидке та просте повторення матеріалу.

Крок 1: Знайди партнера і поділіться послідовністю з 4 букв для використання як ключа. Підійде будь-яка відповідна для класу послідовність із 4 букв.
Крок 2: Обери секретне слово з 4 букв, яке хочеш надіслати партнеру (обидва партнери роблять це, щоб надсилати одне одному різні секретні слова)
Крок 3: Перетвори 4-буквений ключ/блокнот і кожне із 4-буквених секретних слів у числа, використовуючи A = 1, B = 2 і так далі.
Крок 4: Поєднай своє 4-буквене слово з одноразовим блокнотом за допомогою додавання за модулем 26.
Крок 5: Передай партнеру послідовність чисел, що кодує твоє секретне слово, а партнер передасть тобі свою.
Крок 6: Розшифруйте слова одне одного за допомогою віднімання за модулем 26.
Крок 7: Перевірте. Чи вийшло?

Продовження

Обміняйся зашифрованими словами з іншою групою, яка не має доступу до твого одноразового блокнота. Чи можеш ти розшифрувати їх слово? Поясни, чому так чи ні?

Сподіваємося, вправа вище дала зрозуміти, що одноразовий блокнот є незламною формою шифрування за кількох припущень, зокрема:

  • Ключ такої ж довжини, що й повідомлення, яке надсилається, або довший
  • Ключ є справді випадковим
  • Ключ використовується лише один раз, а потім знищується

Отже, це чудово. Ми маємо незламне шифрування… якщо тільки хтось не отримає наш ключ. Якщо хтось отримає наш ключ, все буде розшифровано. Ця різниця між незламним шифруванням і повним розкриттям усіх наших секретів робить безпечне поширення ключа надзвичайно важливим. Мета квантового розподілу ключів — використати обмеження, які природа наклала на квантову інформацію, для захисту спільного ключа/одноразового блокнота.

Використання квантових станів як ключа

Припустимо, ми працюємо з кубітами (підкреслюючи, що кубіти мають два власні стани). Можна використовувати квантові системи з більшою кількістю квантових станів, але найсучасніші квантові комп'ютери IBM® використовують кубіти. Немає проблем закодувати наші A, B, C у послідовності з 0 і 1. Отже, нам достатньо поділитися ключем із 0 і 1 та виконувати додавання за модулем 2 для кожного біта, що зберігає букву.

Перевір своє розуміння

Прочитай запитання нижче, обміркуй свою відповідь, а потім натисни на трикутник, щоб побачити рішення.

Якщо нас цікавлять лише літери англійського алфавіту, скільки бітів нам потрібно?

Відповідь:

24=1625=325 bits2^4=16\\ 2^5 = 32 \rightarrow 5 \text{ bits}

Наші друзі Аліса та Боб хочуть поділитися квантовим ключем так, щоб ніхто інший не міг його перехопити (або принаймні не без їхнього відома). Їм потрібен спосіб надсилати квантові стани одне одному. Зробити це з високою точністю та без шумів/помилок — непросте завдання. Але є два підходи, які ми повинні вміти зрозуміти на цьому етапі:

  1. Волоконно-оптичний кабель дозволяє надсилати світло… яке є дуже квантово-механічним. Одиночні фотони можна виявляти з високою точністю на відстані в багато кілометрів оптичного волокна. Це не ідеальний безпомилковий квантовий канал, але він може бути дуже хорошим.
  2. Ми могли б використати квантову телепортацію, описану в попередньому модулі. Тобто Аліса та Боб могли б поділитися заплутаними кубітами, і стан міг би бути надісланий від Аліси до Боба за протоколом телепортації.

У цьому модулі ми не хочемо вимагати від тебе оптичного обладнання високої точності для обміну фотонами, тому ми будемо використовувати другий метод для обміну квантовими станами. Але це не означає, що він є найбільш реалістичним для обміну квантовими ключами на великих відстанях.

Тепер ми дослідимо протокол, вперше запропонований Чарльзом Беннетом і Жілем Брасаром у 1984 році для обміну станами, виміряними в різних базисах, від Аліси до Боба. Ми використаємо хитру схему вимірювань для формування ключа, який буде використаний у подальшому шифруванні. Іншими словами, ми розподіляємо квантовий ключ між двома сторонами, які хочуть спілкуватися — звідси й назва «квантовий розподіл ключів» (QKD).

Крок 1 QKD: випадкові біти та випадкові базиси Аліси

Аліса починає з генерації випадкової послідовності 0 і 1. Потім вона випадково вибирає базис, у якому підготує квантовий стан для кожного випадкового біта, використовуючи таблицю нижче (таблицю, яка також є у Боба):

Базисbit = 0bit = 1
Z0\vert 0\rangle1\vert 1\rangle
X+\vert +\rangle\vert -\rangle

Наприклад, припустимо, що Аліса випадково згенерувала 0 і випадково вибрала базис X. Тоді вона підготує квантовий стан ψ=+x=12(0+1)|\psi\rangle = |+\rangle_x = \frac{1}{\sqrt{2}}(|0\rangle+|1\rangle). Безперечно, можна використати квантову випадковість для генерації випадкового набору 0 і 1 та випадкового вибору базису. Поки що просто припустимо, що випадковий набір вже згенеровано, наприклад:

Біти Аліси010011010...
Базиси АлісиXXZZZXZZX...
Стани Аліси+\vert +\rangle\vert -\rangle0\vert 0\rangle0\vert 0\rangle1\vert 1\rangle\vert -\rangle0\vert 0\rangle1\vert 1\rangle+\vert +\rangle...

Цей набір випадкових бітів, базисів і відповідних станів продовжується у довгій послідовності, щоб сформувати ключ достатньої довжини.

Крок 2 QKD: випадкові базиси Боба

Боб також робить випадковий вибір базисів. Однак, якщо Аліса використовувала вибір базису для підготовки свого стану, Боб насправді робитиме вимірювання в цих базисах. Якщо Боб вимірює в тому ж базисі, в якому Аліса підготувала стан, ми можемо передбачити результат вимірювання Боба. Коли Боб випадково вибирає інший базис, ніж той, який Аліса використовувала при підготовці, ми не можемо знати результат вимірювання Боба.

Біти Аліси010011010...
Базиси АлісиXXZZZXZZX...
Стани Аліси+\vert +\rangle\vert -\rangle0\vert 0\rangle0\vert 0\rangle1\vert 1\rangle\vert -\rangle0\vert 0\rangle1\vert 1\rangle+\vert +\rangle...
Базиси БобаXZXZXXZXX...
Стани Боба (апріорі)+\vert +\rangle??0\vert 0\rangle?\vert -\rangle0\vert 0\rangle?+\vert +\rangle...
Стани Боба (виміряні)+\vert +\rangle0\vert 0\rangle\vert -\rangle0\vert 0\rangle+\vert +\rangle\vert -\rangle0\vert 0\rangle\vert -\rangle+\vert +\rangle...
У таблиці нижче розглянь перший стовпець. Аліса підготувала стан +,\vert +\rangle, який є власним станом X. Оскільки Боб також випадково вибрав вимірювання в базисі X, для виміряного стану Боба є лише один можливий результат: +.\vert +\rangle. Однак у другому стовпці вони вибрали різні базиси. Стан, надісланий Алісою, — =12(01).\vert -\rangle = \frac{1}{\sqrt{2}}(\vert 0\rangle-\vert 1 \rangle). Він має 50% шанс бути виміряним Бобом у стані 0\vert 0\rangle і 50% шанс бути виміряним у стані 1.\vert 1\rangle. Тому рядок, що показує, що ми знаємо апріорі про вимірювання Боба, не може бути заповнений для стовпця 2. Але Боб зробить вимірювання і отримає власний стан (у цьому стовпці) Z. У нижньому рядку ми заповнюємо те, що ці вимірювання фактично дали.

Крок 3 QKD: публічне обговорення базисів

Тепер Аліса та Боб можуть повідомити одне одному, який базис вони вибрали в кожному випадку. Для всіх стовпців, де вони випадково вибрали однаковий базис, кожен із них точно знає, який стан був у іншого. Боб може перетворити стан і базис у 0 або 1 згідно з конвенцією, відомою обом сторонам. Ми можемо переписати таблицю вище, щоб показати лише випадки, де базиси Аліси та Боба збіглися:

Біти Аліси00100...
Базиси АлісиXZXZX...
Стани Аліси+\vert +\rangle0\vert 0\rangle\vert -\rangle0\vert 0\rangle+\vert +\rangle...
Базиси БобаXZXZXX
Стани Боба (апріорі)+\vert +\rangle0\vert 0\rangle\vert -\rangle0\vert 0\rangle+\vert +\rangle...
Стани Боба (виміряні)+\vert +\rangle0\vert 0\rangle\vert -\rangle0\vert 0\rangle+\vert +\rangle...
Біти Боба00100...

Аліса успішно передала Бобу бітовий рядок 00100... Якщо друзі заздалегідь домовилися використовувати 5-бітові рядки як числа у своєму одноразовому блокноті, ці перші п'ять бітів дають їм число 4=0×24+0×23+1×22+0×21+0×20.4 = 0\times2^4+0\times2^3+1\times2^2+0\times2^1+0\times2^0.

Крок 4 QKD: верифікація та надсилання секрету

Перш ніж Аліса та Боб підуть далі, їм слід вибрати підмножину своїх класичних бітів для порівняння. Оскільки вони зберегли лише вимірювання кубітів, підготовлених і виміряних в одному базисі, усі виміряні значення мають збігатися. Якщо дуже малий відсоток не збігається, це може бути пов'язано з квантовим шумом або помилками. Але якщо багато не збігається — щось пішло не так!

Тут ми не будемо розглядати, яку частку ключа слід використовувати для верифікації. Поки що припустимо, що ця перевірка пройшла успішно; ми повернемося до цього в розділі нижче про підслуховування.

Потім друзі надіслали б одне одному зашифроване повідомлення класичними каналами. Вони б використали числа у своєму одноразовому блокноті для шифрування/дешифрування секретних повідомлень, не передаючи одноразовий блокнот з одного місця в інше. Для наступного розділу про підслуховування пам'ятай, що весь цей обмін ключем відбувається до розкриття зашифрованого секрету через класичні канали.

Аліса та Боб повідомили свій вибір базису через класичні канали, то хіба це не можна перехопити? Так! Але знання базису, який вони використали для вимірювання, не розповідає тобі, який біт вони надіслали або отримали. Це можливо лише якщо ти також знаєш початкові біти Аліси. Але тоді ти б мав доступ до комп'ютера Аліси, де зберігаються секрети, і безпечна передача секретів стає безпредметною. Тому перехоплення класичного зв'язку не зламує шифрування. Але що щодо перехоплення інформації в квантовому каналі?

Стійкість QKD до підслуховування

У Аліси та Боба є подруга Єва, яка сумно відома своїм підслуховуванням. Єва хоче перехопити квантовий ключ Аліси та Боба, щоб використати його для дешифрування повідомлень між ними. Це неодмінно мало б відбутися між підготовкою станів Алісою та їх вимірюванням Бобом, оскільки вимірювання руйнує квантовий стан. Зокрема, це означає, що підслуховування мало б відбутися до того, як відбудеться будь-який обмін або порівняння базисів.

Єва має вгадати, який базис був використаний при кодуванні кожного біта. Знову ж таки, якщо вона не має доступу до комп'ютера Аліси, у неї немає підстав для цього вгадування, і воно буде випадковим. Припустимо, що початок Аліси той самий, що й раніше, і додатково припустимо, що випадковий вибір базису вимірювання Бобом такий самий, як і раніше. Заповнимо, що Єва отримує, якщо вона робить вимірювання квантового каналу. Як і раніше, якщо Єва випадково вибирає той самий базис, що й Аліса, ми знаємо, що вона отримає. Якщо ні — вона може отримати один із двох результатів, кожен із вірогідністю 50%.

Біти Аліси010011010...
Базиси АлісиXXZZZXZZX...
Стани Аліси+\vert +\rangle\vert -\rangle0\vert 0\rangle0\vert 0\rangle1\vert 1\rangle\vert -\rangle0\vert 0\rangle1\vert 1\rangle+\vert +\rangle...
Вгадані базиси ЄвиZXXZXZZXX...
Стани Єви (апріорі)?\vert -\rangle?0\vert 0\rangle??0\vert 0\rangle?+\vert +\rangle...
Стани Єви (виміряні)1\vert 1\rangle\vert -\rangle+\vert +\rangle0\vert 0\rangle\vert -\rangle0\vert 0\rangle0\vert 0\rangle\vert -\rangle+\vert +\rangle...
Базиси БобаXZXZXXZXX...

Оскільки Єва не знає, збігся її базис із базисом Аліси чи ні, вона не знає, що передати Бобу, щоб це відповідало оригінальним станам Аліси. Коли Єва вимірює, наприклад, 0,|0\rangle, вона знає лише те, що Аліса не підготувала стан 1|1\rangle для цього кубіта. Але Аліса могла підготувати 0,|0\rangle, +|+\rangle або .|-\rangle. Усі вони сумісні з вимірюванням Єви. Тому Єва повинна зробити вибір. Вона може передати далі саме той стан, який виміряла, або може спробувати вгадати випадки, коли її вимірювання не було власним станом, надісланим Алісою. Ми включимо суміш у нашу таблицю:

Біти Аліси010011010...
Базиси АлісиXXZZZXZZX...
Стани Аліси+\vert +\rangle\vert -\rangle0\vert 0\rangle0\vert 0\rangle1\vert 1\rangle\vert -\rangle0\vert 0\rangle1\vert 1\rangle+\vert +\rangle...
Вгадані базиси ЄвиZXXZXZZXX...
Стани Єви (апріорі)?\vert -\rangle?0\vert 0\rangle??0\vert 0\rangle?+\vert +\rangle...
Стани Єви (виміряні)1\vert 1\rangle\vert -\rangle+\vert +\rangle0\vert 0\rangle\vert -\rangle0\vert 0\rangle0\vert 0\rangle\vert -\rangle+\vert +\rangle...
Стани Єви (передані далі)1\vert 1\rangle0\vert 0\rangle1\vert 1\rangle0\vert 0\rangle\vert -\rangle+\vert +\rangle0\vert 0\rangle\vert -\rangle0\vert 0\rangle...
Базиси БобаXZXZXXZXX...
Стани Боба (апріорі)?0\vert 0\rangle?0\vert 0\rangle\vert -\rangle+\vert +\rangle0\vert 0\rangle\vert -\rangle+\vert +\rangle...
Стани Боба (виміряні)\vert -\rangle0\vert 0\rangle+\vert +\rangle0\vert 0\rangle\vert -\rangle+\vert +\rangle0\vert 0\rangle\vert -\rangle+\vert +\rangle...
Біти Боба100010010...

На цьому етапі доречно запитати: «Чому Єва просто не зробить копію квантового стану Аліси, залишить одну для вимірювання, а іншу передасть Бобу?» Відповідь — теорема про заборону клонування. Неформально вона стверджує, що не існує унітарної (квантово-механічної) операції, яка може зробити другу копію довільного квантового стану, зберігаючи при цьому першу копію. Доведення відносно просте і залишено як підказана вправа. Але поки зрозумій, що клонування квантових станів Євою заборонено фундаментальними законами природи, і це є принциповою перевагою QKD. Як і раніше, Аліса та Боб зателефонують одне одному та порівняють базиси. Вони зведуть цю таблицю до випадків, де обидва друзі вибрали однакові базиси:

Біти Аліси00100...
Базиси АлісиXZXZX...
Стани Аліси+\vert +\rangle0\vert 0\rangle\vert -\rangle0\vert 0\rangle+\vert +\rangle...
Вгадані базиси ЄвиZZZZX...
Стани Єви (апріорі)?0\vert 0\rangle?0\vert 0\rangle+\vert +\rangle...
Стани Єви (виміряні)1\vert 1\rangle0\vert 0\rangle0\vert 0\rangle0\vert 0\rangle+\vert +\rangle...
Стани Єви (передані далі)1\vert 1\rangle0\vert 0\rangle+\vert +\rangle0\vert 0\rangle0\vert 0\rangle...
Базиси БобаXZXZX...
Стани Боба (апріорі)?0\vert 0\rangle+\vert +\rangle0\vert 0\rangle+\vert +\rangle...
Стани Боба (виміряні)\vert -\rangle0\vert 0\rangle+\vert +\rangle0\vert 0\rangle+\vert +\rangle...
Біти Боба10000...

Аліса та Боб знову передали бітовий рядок… але рядки не збіглися. Крайній лівий і середній біти перевернуті. Переглядаючи попередню таблицю, можна простежити цю невідповідність до втручання Єви. Що важливо, зауваж, що ми можемо проводити статистику відповідності між нашими бітовими рядками вже зараз, при налаштуванні ключа, задовго до того, як поділимося зашифрованим секретом. Аліса та Боб вільні використовувати стільки бітів свого одноразового блокнота, скільки захочуть, для перевірки безпеки свого каналу. Якщо один біт або дуже малий відсоток бітів не збігається, це може бути пов'язано з шумом або помилками. Але значна частка невідповідностей вказує на підслуховування. Що означає «значна» — залежить від рівня шуму в установці; те, що це означає для квантових комп'ютерів IBM®, обговорюється нижче при реалізації цього протоколу. Якщо виявлено надмірну кількість помилок, Аліса та Боб не передають секрет і можуть починати полювання на підслуховувача.

Застереження

Доведення безпеки надзвичайно складне. Насправді протокол, описаний тут у загальних рисах, був запропонований у 1984 році, і його безпека не була доведена аж до 16 років потому Shor & Preskill, 2000. Є багато тонкощів, що виходять за рамки цього введення. Але ми коротко перелічимо деякі з них, щоб показати, що тема складніша, ніж проілюстровано тут.

  • Безпечні канали: Коли Аліса надсилає свої кубіти через якесь квантове налаштування (канал), і зокрема коли вона отримує класичні відповіді від когось, ми припустили, що цим кимось є насправді Боб. Якби Єва проникла в це налаштування таким чином, що весь зв'язок Аліси насправді відбувався з Євою, і весь зв'язок Боба насправді здійснювався з Євою, то Єва фактично отримала б ключ і могла б дізнатися секрети. Спершу потрібно забезпечити «безпечні канали» — процес із іншим набором протоколів, який ми тут не розглядали.
  • Припущення про Єву: Щоб по-справжньому довести безпеку, ми не можемо робити припущень про поведінку Єви; вона завжди може спантеличити наші очікування. Тут, наводячи конкретні приклади, ми робимо припущення. Наприклад, ми можемо припустити, що стани, які Єва передає Бобу, завжди точно ті, які вона отримала при вимірюванні. Або ми можемо припустити, що вона випадково вибирає стан, експериментально сумісний із її вимірюванням. Більш принципово, мова тут передбачає, що Єва насправді робить вимірювання, а не зберігає стан на іншій квантовій системі та надсилає Бобу випадковий кубіт. Ці припущення є прийнятними для розуміння протоколу, але вони означають, що ми не доводимо нічого в повній загальності.
  • Посилення конфіденційності: Аліса та Боб не зобов'язані використовувати квантовий ключ саме так, як він був переданий. Вони можуть, наприклад, застосувати хеш-функцію до спільного ключа. Це дозволило б використати той факт, що підслуховувач має неповні знання про ключ, щоб отримати коротший, але безпечний спільний ключ.

Експеримент 1: QKD без підслуховувача

Давай реалізуємо наведений вище протокол за відсутності підслуховувача. Спочатку ми зробимо це за допомогою симулятора, просто щоб зрозуміти робочий процес.

Спочатку — зауваження про квантові симулятори: більшість квантових задач, що включають більше ніж ~30 кубітів, не можуть бути симульовані більшістю комп'ютерів. Жоден класичний комп'ютер, суперкомп'ютер або GPU не може симулювати весь спектр поведінки 127-кубітного квантового комп'ютера. Зазвичай мотивацією для використання реальних квантових комп'ютерів є те, що багато заплутаних кубітів не можна симулювати. У цьому випадку заплутаності кубітів немає, якщо тільки ми не використовуємо схему телепортації для переміщення інформації. Тут мотивація для використання реальних квантових комп'ютерів інша: теорема про заборону клонування. Класичний комп'ютер, симулюючи кубіт, міг би надсилати інформацію про квантовий стан від Аліси до Боба, але якби ця класична інформація була перехоплена, її можна було б легко продублювати, і Єва могла б зберегти ідеальну копію, надіславши іншу Бобу. Із реальними квантовими станами це неможливо.

IBM Quantum рекомендує вирішувати задачі квантових обчислень за допомогою фреймворку, який ми називаємо «шаблонами Qiskit». Він складається з таких кроків:

  • Крок 1: відобрази задачу на квантовий Circuit
  • Крок 2: оптимізуй свій Circuit для запуску на реальному квантовому залізі
  • Крок 3: виконай завдання на квантових комп'ютерах IBM за допомогою Runtime primitives
  • Крок 4: постобробка результатів

Крок 1 шаблонів Qiskit: відображення задачі на квантовий Circuit

У цьому випадку відображення нашої задачі на квантові Circuit зводиться просто до підготовки станів Аліси та подальшого включення вимірювань Боба. Починаємо з вибору випадкових бітів та випадкових базисів.

# Qiskit patterns step 1: Map your problem to quantum circuit
# Import some generic packages

import numpy as np
from qiskit import QuantumCircuit

# Set up a random number generator and a quantum circuit. We choose to start with 20 bits, though any number <30 should be fine.

rng = np.random.default_rng()
bit_num = 20
qc = QuantumCircuit(bit_num, bit_num)

# QKD step 1: Random bits and bases for Alice
# generate Alice's random bits

abits = np.round(rng.random(bit_num))

# generate Alice's random measurement bases. Here we will associate a "0" with the Z basis, and a "1" with the X basis.

abase = np.round(rng.random(bit_num))

# Alice's state preparation. Check that this creates states according to table 1

for n in range(bit_num):
if abits[n] == 0:
if abase[n] == 1:
qc.h(n)
if abits[n] == 1:
if abase[n] == 0:
qc.x(n)
if abase[n] == 1:
qc.x(n)
qc.h(n)

qc.barrier()

# QKD step 2: Random bases for Bob
# generate Bob's random measurement bases.

bbase = np.round(rng.random(bit_num))

# Note that if Bob measures in Z no gates are necessary, since IBM Quantum computers measure in Z by default.
# If Bob measures in the X basis, we implement a hadamard gate qc.h to facilitate the measurement.

for m in range(bit_num):
if bbase[m] == 1:
qc.h(m)
qc.measure(m, m)

Давай візуалізуємо біти, базиси та Circuit. Зауваж, що іноді базиси збігаються, а іноді ні.

print("Alice's bits are ", abits)
print("Alice's bases are ", abase)
print("Bob's bases are ", bbase)
qc.draw("mpl")
Alice's bits are  [1. 1. 0. 1. 0. 1. 1. 0. 0. 1. 0. 0. 1. 0. 0. 0. 1. 0. 0. 0.]
Alice's bases are [0. 0. 0. 1. 1. 0. 0. 0. 0. 1. 1. 1. 1. 1. 0. 1. 1. 0. 1. 0.]
Bob's bases are [0. 1. 1. 0. 1. 0. 1. 1. 0. 0. 1. 1. 0. 0. 1. 0. 1. 1. 0. 0.]

Результат попереднього блоку коду

Крок 2 шаблонів Qiskit: оптимізація задачі для квантового виконання

Цей крок бере операції, які ми хочемо виконати, і виражає їх у термінах функціональності конкретного квантового комп'ютера. Він також відображає нашу задачу на топологію квантового комп'ютера.

Ми почнемо з завантаження кількох пакетів, необхідних для зв'язку з квантовими комп'ютерами IBM. Нам також потрібно вибрати Backend для запуску. Ми можемо вибрати найменш завантажений Backend або вибрати конкретний Backend, властивості якого нам відомі. Хоча ми зараз використовуємо симулятор, важливо використовувати розумну модель шуму при симуляції, і добре тримати робочий процес якомога ближчим до того, що ми будемо використовувати пізніше для реальних квантових комп'ютерів.

Нижче наведено код для збереження облікових даних при першому використанні. Обов'язково видали цю інформацію з блокнота після збереження в своєму середовищі, щоб облікові дані не були випадково передані разом із блокнотом. Додаткові вказівки дивись у посібниках Налаштування облікового запису IBM Cloud та Ініціалізація сервісу в ненадійному середовищі.

# Load the Qiskit Runtime service
from qiskit_ibm_runtime import QiskitRuntimeService

# Load the Qiskit Runtime service

# Syntax for first saving your token. Delete these lines after saving your credentials.
# QiskitRuntimeService.save_account(channel='ibm_quantum_platform', instance = '<YOUR_IBM_INSTANCE_CRN>', token='<YOUR-API_KEY>', overwrite=True, set_as_default=True)
# service = QiskitRuntimeService(channel='ibm_quantum_platform')

# Load saved credentials
service = QiskitRuntimeService()

# Use the least busy backend, or uncomment the loading of a specific backend like "ibm_brisbane".
# backend = service.least_busy(operational=True, simulator=False, min_num_qubits = 127)
backend = service.backend("ibm_brisbane")
print(backend.name)
ibm_brisbane

Нижче ми вибираємо симулятор і модель шуму.

# Load the backend sampler
from qiskit.primitives import BackendSamplerV2

# Load the Aer simulator and generate a noise model based on the currently-selected backend.
from qiskit_aer import AerSimulator
from qiskit_aer.noise import NoiseModel

# Load the qiskit runtime sampler
from qiskit_ibm_runtime import SamplerV2 as Sampler

noise_model = NoiseModel.from_backend(backend)

# Define a simulator using Aer, and use it in Sampler.
backend_sim = AerSimulator(noise_model=noise_model)
sampler_sim = BackendSamplerV2(backend=backend_sim)
# Qiskit patterns step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)

Крок 3 у шаблонах Qiskit: Виконання

Використай sampler для запуску завдання, передавши Circuit як аргумент.

# This required 5 s to run on a Heron r2 processor on 10-28-24
sampler = Sampler(mode=backend)
job = sampler.run([qc_isa], shots=1)
# job = sampler_sim.run([qc], shots = 1)
counts = job.result()[0].data.c.get_counts()
countsint = job.result()[0].data.c.get_int_counts()

Крок 4 у шаблонах Qiskit: Постобробка

Тут ми інтерпретуємо результати та витягуємо корисну інформацію. Можна спробувати візуалізувати вивід sampler, але ми скористалися ним у нетиповий спосіб. Замість того, щоб робити багато вимірювань Circuit і накопичувати статистику станів, ми зробили лише одне вимірювання — вимірювання Боба. Будь-який qubit, стан якого підготовлено та виміряно в одному базисі, повинен мати детермінований результат, тому одного вимірювання достатньо. Ті qubits, стани яких підготовлено та виміряно в різних базисах (що давало б імовірнісні результати і вимагало б багатьох вимірювань для інтерпретації), не використовуватимуться для формування одноразового блокнота/ключа. Витягнемо список результатів вимірювань із цього бітового рядка. Зверни увагу на необхідність обернути порядок, якщо порівнюєш із масивом бітів Аліси, який ми використовували для генерації Circuit.

# Get an array of bits

keys = counts.keys()
key = list(keys)[0]
bmeas = list(key)
bmeas_ints = []
for n in range(bit_num):
bmeas_ints.append(int(bmeas[n]))

# Reverse the order to match our input. See "little endian" notation.

bbits = bmeas_ints[::-1]

print(bbits)
[1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0]

Порівняємо базиси вимірювань, які випадково обрали Аліса і Боб. Це був крок 3 у нашому протоколі QKD (публічне обговорення базисів). Щоразу, коли вони обирали однаковий базис для qubit, ми додаємо біти, пов'язані з цим qubit, до списку бітів для генерації чисел в одноразовому блокноті. Коли базиси не збігаються, результати відкидаються. Перевіримо також, чи два списки бітів збігаються або чи були якісь втрати через шум чи інші чинники.

# QKD step 3: Public discussion of bases

agoodbits = []
bgoodbits = []
match_count = 0
for n in range(bit_num):
# Check whether bases matched.
if abase[n] == bbase[n]:
agoodbits.append(int(abits[n]))
bgoodbits.append(bbits[n])
# If bits match when bases matched, increase count of matching bits
if int(abits[n]) == bbits[n]:
match_count += 1

print(agoodbits)
print(bgoodbits)
print("fidelity = ", match_count / len(agoodbits))
print("loss = ", 1 - match_count / len(agoodbits))
[1, 0, 1, 0, 0, 0, 1, 0]
[1, 0, 1, 0, 0, 0, 1, 0]
fidelity = 1.0
loss = 0.0

У Аліси і Боба є список бітів, і вони збігаються зі 100% вірністю. Вони можуть використати ці біти для генерації чисел в одноразовому блокноті. Потім цей блокнот можна застосувати на кроці 4 QKD: надсилання та розшифрування секрету. Наявний масив бітів надто короткий, щоб розшифрувати що-небудь суттєве. Ми повернемося до цього після того, як розглянемо підслуховування.

Перевір своє розуміння

Прочитай питання нижче, подумай над відповіддю, а потім клікни на трикутник, щоб побачити рішення.

Припусти, що тобі потрібні цифри, достатньо великі для зміщення літер англійського алфавіту на його повну довжину або більше, хоча існують і інші схеми кодування. (a) Яку довжину в літерах може мати повідомлення, що розшифровується за допомогою бітів ключа вище? (b) Чи обов'язково твоя відповідь збігатиметься з відповідями однокласників? Чому так чи ні?

Відповідь:

(a) Відповідь залежить від того, скільки випадково обраних базисів збіглося у Аліси і Боба. Оскільки ймовірність збігу базисів для кожного qubit приблизно 50 на 50, очікуємо, що корисними виявляться приблизно 10 бітів. 9 або 11 — цілком звичайний результат. Навіть 4 або 15 не виходять за межі можливого. Для зміщення на число, більше або рівне довжині англійського алфавіту, потрібно 5 бітів, тобто можна застосувати зміщення до однієї літери на кожні 5 наявних бітів. Якщо у Аліси і Боба є хоча б 5 спільних бітів, можна закодувати одну літеру. Якщо хоча б 10 — дві літери, і так далі. (b) Відповідь не обов'язково збігатиметься, з причин, зазначених у пункті (a).

Експеримент 2: QKD з підслуховувачем

Ми реалізуємо той самий протокол, що й раніше. Цього разу ми вставимо ще один набір вимірювань — від Єви — між Алісою та Бобом.

from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister

# Qiskit patterns step 1: Mapping your problem to a quantum circuit
# QKD step 1: Random bits and bases for Alice

bit_num = 20
qr = QuantumRegister(bit_num, "q")
cr = ClassicalRegister(bit_num, "c")
qc = QuantumCircuit(qr, cr)

# Alice's random bits and bases, as before

abits = np.round(rng.random(bit_num))
abase = np.round(rng.random(bit_num))

# Alice's state preparation, as before

for n in range(bit_num):
if abits[n] == 0:
if abase[n] == 1:
qc.h(n)
if abits[n] == 1:
if abase[n] == 0:
qc.x(n)
if abase[n] == 1:
qc.x(n)
qc.h(n)

qc.barrier()

# Eavesdropping happens here!
# Generate Eve's random measurement bases

ebase = np.round(rng.random(bit_num))

for m in range(bit_num):
if ebase[m] == 1:
qc.h(m)
qc.measure(qr[m], cr[m])
# Qiskit patterns step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)
# Qiskit patterns step 3: Execute
job = sampler_sim.run([qc_isa], shots=1)
counts = job.result()[0].data.c.get_counts()
countsint = job.result()[0].data.c.get_int_counts()

Крок 4 у шаблонах Qiskit (постобробка) у цьому випадку простий. Візуалізувати розподіл вимірювань не потрібно, оскільки ми зробили лише одне вимірювання. Єва отримує такі біти:

keys = counts.keys()
key = list(keys)[0]
emeas = list(key)
emeas_ints = []
for n in range(bit_num):
emeas_ints.append(int(emeas[n]))
ebits = emeas_ints[::-1]

print(ebits)
[0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1]

Тепер Єва повинна відновити стани, щоб передати їх далі Бобу. Як описано у вступі, вона не має способу дізнатися, чи правильно вгадала базиси кодування, тому не може підготувати точно такі самі стани, що були надіслані. Вона може припустити, що кожен вибір базису був правильним, і кодувати саме те, що виміряла, або припустити, що помилилась із базисом, і обрати будь-який власний стан протилежного базису. Тут, для простоти, ми припускаємо перше. Для цього ми будуємо цілком новий квантовий Circuit і повторюємо кроки шаблонів Qiskit, як і раніше.

from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

# Qiskit patterns step 1: Mapping your problem onto a quantum circuit
# QKD step 1: Eve uses her measurements to prepare best guess states to send on to Bob

qr = QuantumRegister(bit_num, "q")
cr = ClassicalRegister(bit_num, "c")
qc = QuantumCircuit(qr, cr)

# Eve's state preparation

for n in range(bit_num):
if ebits[n] == 0:
if ebase[n] == 1:
qc.h(n)
if ebits[n] == 1:
if ebase[n] == 0:
qc.x(n)
if ebase[n] == 1:
qc.x(n)
qc.h(n)

qc.barrier()

# QKD step 2: Random bases for Bob

bbase = np.round(rng.random(bit_num))

for m in range(bit_num):
if bbase[m] == 1:
qc.h(m)
qc.measure(qr[m], cr[m])

# Qiskit patterns step 2: Transpile

target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)

# Qiskit patterns step 3: Execute

job = sampler_sim.run([qc_isa], shots=1)
counts = job.result()[0].data.c.get_counts()
countsint = job.result()[0].data.c.get_int_counts()

# Qiskit patterns step 4: Post-processing

keys = counts.keys()
key = list(keys)[0]
bmeas = list(key)
bmeas_ints = []
for n in range(bit_num):
bmeas_ints.append(int(bmeas[n]))
bbits = bmeas_ints[::-1]

print(bbits)
[0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1]

Порівняємо тепер біти Аліси та Боба:

agoodbits = []
bgoodbits = []
match_count = 0
for n in range(bit_num):
if abase[n] == bbase[n]:
agoodbits.append(int(abits[n]))
bgoodbits.append(bbits[n])
if int(abits[n]) == bbits[n]:
match_count += 1
print(agoodbits)
print(bgoodbits)
print("fidelity = ", match_count / len(agoodbits))
print("loss = ", 1 - match_count / len(agoodbits))
[1, 1, 0, 0, 0, 1, 1]
[1, 1, 0, 0, 0, 0, 1]
fidelity = 0.8571428571428571
loss = 0.1428571428571429

Раніше між бітами ключів Аліси і Боба був ідеальний збіг. Тепер, через втручання Єви, біти Аліси і Боба відрізняються у 14% випадків, коли вони мали збігатися через вибір однакових базисів. Це повинно бути легко помітити для Аліси і Боба. Однак покладатися на такий відсоток помилок означає, що є межа допустимого рівня шуму в квантовому каналі.

Експеримент 3: Порівняння QKD з підслуховуванням і без нього на реальному квантовому комп'ютері

Запустимо це на реальному квантовому комп'ютері. Так ми зможемо скористатися теоремою про заборону клонування. Водночас реальні квантові комп'ютери мають шум і вищі рівні помилок, ніж класичні. Тому порівняємо втрати вірності ключових бітів з підслуховуванням і без нього, щоб переконатися, що різниця є помітною при використанні реального квантового комп'ютера. Почнемо без підслуховування:

from qiskit_ibm_runtime import SamplerV2 as Sampler

# This calculation was run on an Eagle r3 processor on 11-7-24 and required 3 sec to run, with 127 qubits.
# Qiskit patterns step 1: Mapping your problem to a quantum circuit

bit_num = 127
qc = QuantumCircuit(bit_num, bit_num)

# QKD step 1: Generate Alice's random bits and bases

abits = np.round(rng.random(bit_num))
abase = np.round(rng.random(bit_num))

# Alice's state preparation

for n in range(bit_num):
if abits[n] == 0:
if abase[n] == 1:
qc.h(n)
if abits[n] == 1:
if abase[n] == 0:
qc.x(n)
if abase[n] == 1:
qc.x(n)
qc.h(n)

# QKD step 2: Random bases for Bob

bbase = np.round(rng.random(bit_num))

for m in range(bit_num):
if bbase[m] == 1:
qc.h(m)
qc.measure(m, m)

# Qiskit patterns step 2: Transpilation

target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)

# Load the Runtime primitive and session
sampler = Sampler(mode=backend)

# Qiskit patterns step 3: Execute

job = sampler.run([qc_isa], shots=1)
counts = job.result()[0].data.c.get_counts()
countsint = job.result()[0].data.c.get_int_counts()

# Qiskit patterns step 4: Post-processing
# Extract Bob's bits

keys = counts.keys()
key = list(keys)[0]
bmeas = list(key)
bmeas_ints = []
for n in range(bit_num):
bmeas_ints.append(int(bmeas[n]))
bbits = bmeas_ints[::-1]

# Compare Alice's and Bob's measurement bases and collect usable bits

agoodbits = []
bgoodbits = []
match_count = 0
for n in range(bit_num):
if abase[n] == bbase[n]:
agoodbits.append(int(abits[n]))
bgoodbits.append(bbits[n])
if int(abits[n]) == bbits[n]:
match_count += 1

# Print some results

print("Alice's bits = ", agoodbits)
print("Bob's bits = ", bgoodbits)
print("fidelity = ", match_count / len(agoodbits))
print("loss = ", 1 - match_count / len(agoodbits))
Alice's bits =  [0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]
Bob's bits = [0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1]
fidelity = 0.9682539682539683
loss = 0.031746031746031744

Без підслуховування ми отримали 100% вірність на цьому наборі з 127 пробних бітів, що дало 55 збіжних базисів і придатних ключових бітів. Тепер повторимо цей експеримент із підслуховуванням від Єви:

from qiskit_ibm_runtime import SamplerV2 as Sampler

# This calculation was run on an Eagle r3 processor on 11-7-24 and required 2 s to run, with 127 qubits.
# Qiskit patterns step 1: Mapping your problem to a quantum circuit

bit_num = 127
qr = QuantumRegister(bit_num, "q")
cr = ClassicalRegister(bit_num, "c")
qc = QuantumCircuit(qr, cr)

# QKD step 1: Generate Alice's random bits and bases

abits = np.round(rng.random(bit_num))
abase = np.round(rng.random(bit_num))

# Alice's state preparation

for n in range(bit_num):
if abits[n] == 0:
if abase[n] == 1:
qc.h(n)
if abits[n] == 1:
if abase[n] == 0:
qc.x(n)
if abase[n] == 1:
qc.x(n)
qc.h(n)

# Eavesdropping happens here!
# Generate Eve's random measurement bases

ebase = np.round(rng.random(bit_num))

for m in range(bit_num):
if ebase[m] == 1:
qc.h(m)
qc.measure(qr[m], cr[m])

# Qiskit patterns step 2: Transpile

target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)

sampler = Sampler(mode=backend)

# Qiskit patterns step 3: Execute

job = sampler.run([qc_isa], shots=1)
counts = job.result()[0].data.c.get_counts()
countsint = job.result()[0].data.c.get_int_counts()

# Qiskit patterns step 4: Post-processing
# Extract Eve's bits

keys = counts.keys()
key = list(keys)[0]
emeas = list(key)
emeas_ints = []
for n in range(bit_num):
emeas_ints.append(int(emeas[n]))
ebits = emeas_ints[::-1]

# print(ebits)

# Restart process
# Qiskit patterns step 1: Mapping your problem to a quantum circuit

# QKD step 1: Eve uses her measurements above to prepare best guess states to send on to Bob

qr = QuantumRegister(bit_num, "q")
cr = ClassicalRegister(bit_num, "c")
qc = QuantumCircuit(qr, cr)

# Eve's state preparation

for n in range(bit_num):
if ebits[n] == 0:
if ebase[n] == 1:
qc.h(n)
if ebits[n] == 1:
if ebase[n] == 0:
qc.x(n)
if ebase[n] == 1:
qc.x(n)
qc.h(n)

# QKD step 2: Random bases for Bob

bbase = np.round(rng.random(bit_num))

for m in range(bit_num):
if bbase[m] == 1:
qc.h(m)
qc.measure(qr[m], cr[m])

# Qiskit patterns step 2: Transpile

target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)

# Qiskit patterns step 3: Execute

job = sampler.run([qc_isa], shots=1)
counts = job.result()[0].data.c.get_counts()
countsint = job.result()[0].data.c.get_int_counts()

# Qiskit Patterns step 4: Post-processing
# Extract Bob's bits

keys = counts.keys()
key = list(keys)[0]
bmeas = list(key)
bmeas_ints = []
for n in range(bit_num):
bmeas_ints.append(int(bmeas[n]))
bbits = bmeas_ints[::-1]

# Compare Alice's and Bob's bases, when they are the same, keep the bits.

agoodbits = []
bgoodbits = []
match_count = 0
for n in range(bit_num):
if abase[n] == bbase[n]:
agoodbits.append(int(abits[n]))
bgoodbits.append(bbits[n])
if int(abits[n]) == bbits[n]:
match_count += 1

# Print some results

print("Alice's bits = ", agoodbits)
print("Bob's bits = ", bgoodbits)
print("fidelity = ", match_count / len(agoodbits))
print("loss = ", 1 - match_count / len(agoodbits))
Alice's bits =  [1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1]
Bob's bits = [1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1]
fidelity = 0.7619047619047619
loss = 0.23809523809523814

Тут ми виявили майже 23% втрат вірності спільних бітів через підслуховування! Це дуже легко виявити! Зверни увагу, що передача квантової інформації на великі відстані може додатково вносити шум і помилки. Забезпечення того, щоб підслуховування можна було виявити навіть у присутності шуму і навіть коли Єва використовує всі наявні у неї трюки, — це складна область, яка виходить за межі цього введення.

Запитання

Викладачі можуть отримати версії цих ноутбуків із відповідями та рекомендаціями щодо використання в типових навчальних програмах, заповнивши це коротке опитування про те, як ці ноутбуки використовуються.

Ключові концепції

  • Квантову інформацію не можна скопіювати або «клонувати».
  • Ти можеш повторити той самий процес підготовки, щоб отримати ансамбль квантових станів, які всі однакові або майже однакові.
  • Ключ шифрування/дешифрування (одноразовий блокнот) можна передати між двома друзями за допомогою квантових станів.
  • Якщо двоє друзів випадково обирають базис вимірювання, вони вибиратимуть по-різному в половині випадків і матимуть відкидати інформацію про ці кубіти.
  • Випадковий вибір базису вимірювання також гарантує, що підслуховувач не зможе знати початковий підготовлений стан і, отже, не зможе відтворити переданий стан. Це забезпечує виявлення підслуховування.

Питання «Правда/Хибність»

  1. П/Х У квантовому розподілі ключів обидва учасники комунікації вимірюють кожен Qubit в одному і тому самому базисі.
  2. П/Х Закони природи не дозволяють підслуховувачу, який перехоплює квантову інформацію в QKD, скопіювати перехоплений квантовий стан.
  3. П/Х Одноразовий блокнот — це ключ для шифрування/дешифрування захищених повідомлень, у якому певна схема кодування використовується лише один раз для окремої одиниці інформації (наприклад, однієї літери алфавіту).

Питання з вибором відповіді

  1. Обери варіант, що найкраще доповнює твердження. Як описано в цьому модулі, одноразовий блокнот — це набір ключів шифрування/дешифрування, який використовується...
  • a. Лише один раз для однієї одиниці інформації, наприклад однієї літери.
  • b. Лише один раз для одного повідомлення.
  • c. Лише один раз протягом певного проміжку часу, наприклад одного дня.
  • d. До появи ознак підслуховування.
  1. Припустимо, що Аліса і Боб обирають базиси вимірювання випадково. Вони вимірюють. Потім обмінюються інформацією про свої базиси та залишають лише ті біти, де використовували однаковий базис. З урахуванням випадкових відхилень, приблизно який відсоток їхніх кубітів дасть придатні для використання біти інформації?
  • a. 100%
  • b. 50%
  • c. 25%
  • d. 12,5%
  • e. 0%
  1. Після того як Аліса і Боб відібрали випадки, де вони використовували однакові базиси вимірювання, який відсоток цих бітів має збігатися, якщо квантовим шумом і помилками можна знехтувати?
  • a. 100%
  • b. 50%
  • c. 25%
  • d. 12,5%
  • e. 0%
  1. Припустимо, що Аліса обирає базиси вимірювання випадково. Єва теж обирає базиси випадково і підслуховує (вимірює). Вона передає Бобу стани, що відповідають її вимірюванням. Аліса і Боб порівнюють вибір базисів та залишають лише ті кубіти, які вони обоє виміряли/підготували в однакових базисах. З урахуванням випадкових відхилень, приблизно який відсоток цих збережених вимірювань збігатиметься, на думку Аліси і Боба?
  • a. 100%
  • b. 75%
  • c. 50%
  • d. 25%
  • e. 12,5%
  • f. 0%

Питання для обговорення

  1. Припустимо, що всі учасники — Аліса, Боб і Єва — обирають базиси випадково. Припустимо, що після підслуховування Єва надсилає Бобу стан, підготовлений у тому базисі, в якому вона проводила вимірювання, і який відповідає результату цього вимірювання. Переконай своїх партнерів у тому, що 12,5% усіх кубітів, ініціалізованих Алісою, дадуть невідповідності вимірювань між Алісою і Бобом, що свідчить про підслуховування (ігноруючи квантові помилки та шум). Підказка 1: Оскільки немає привілейованого базису, якщо розглянути лише один початковий вибір Аліси, співвідношення для цього одного вибору має бути таким самим, як і для суми всіх виборів. Підказка 2: Може бути недостатньо підрахувати кількість способів, якими щось може статися, оскільки деякі результати можуть траплятися з різною імовірністю.