Quantenschlüsselverteilung
Für dieses Qiskit-in-Classrooms-Modul benötigst du eine funktionierende Python-Umgebung mit folgenden installierten Paketen:
qiskitv2.1.0 oder neuerqiskit-ibm-runtimev0.40.1 oder neuerqiskit-aerv0.17.0 oder neuerqiskit.visualizationnumpypylatexenc
Anleitungen zur Einrichtung und Installation der oben genannten Pakete findest du im Qiskit installieren-Leitfaden. Um Jobs auf echten Quantencomputern auszuführen, müssen Studierende ein Konto bei IBM Quantum® einrichten. Die notwendigen Schritte dazu sind im Leitfaden IBM Cloud-Konto einrichten beschrieben.
Dieses Modul wurde getestet und hat 5 Sekunden QPU-Zeit verbraucht. Dies ist nur eine Schätzung. Dein tatsächlicher Verbrauch kann abweichen.
# 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'
Sieh dir unten die Modul-Einführung von Dr. Katie McCormick an, oder klicke hier, um sie auf YouTube anzuschauen.
Einführung und Motivation
Es gibt unendlich viele Wege, Informationen zu ver- und entschlüsseln, und buchstäblich Tausende davon wurden eingehend erforscht. Hier beschränken wir uns auf eine sehr frühe und sehr einfache Verschlüsselungsmethode, die sogenannte „einfache Substitution", um uns auf den Quantenteil dieses Protokolls konzentrieren zu können. Der Quantenteil ließe sich mit relativ wenigen Änderungen auf viele andere Protokolle übertragen.
Einfache Substitution
Bei einer einfachen Substitutionsverschlüsselung wird ein Buchstabe oder eine Zahl durch einen anderen ersetzt, sodass eine 1:1-Zuordnung zwischen den Buchstaben und Zahlen einer Nachricht und den Buchstaben und Zahlen der verschlüsselten Sequenz besteht. Ein bekanntes Beispiel aus der Popkultur ist das Kryptogramm-Rätsel, bei dem ein Zitat oder eine Phrase mit einfacher Substitution verschlüsselt wird und die Spielerin oder der Spieler die Aufgabe hat, es zu entschlüsseln. Wenn sie lang genug sind, lassen sich solche Rätsel relativ leicht lösen. Betrachte das folgende Beispiel:
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.
Menschen, die solche Rätsel von Hand lösen, nutzen meist Tricks, die auf ihrer Vertrautheit mit der Struktur der Originalsprache beruhen. Im Englischen etwa sind die einzigen einbuchstabigen Wörter wie das verschlüsselte „R" die Buchstaben „a" und „I". Die Doppelbuchstaben, die beispielsweise in „KIVGGB" verschlüsselt sind, können nur bestimmte Werte annehmen. Subtilere Hinweise liefern etwa die Tatsache, dass das häufigste Wort, das dem Muster „GSZG" entspricht, „that" ist. Wer Code zum Lösen einsetzt, hat noch mehr Möglichkeiten, zum Beispiel das einfache Durchprobieren von Möglichkeiten, bis ein englisches Wort erkannt wird, mit anschließender Aktualisierung unter Beibehaltung dieses Wortes. Eine einfache, aber wirkungsvolle Methode ist die Buchstabenhäufigkeitsanalyse, insbesondere wenn die Nachricht lang genug ist, um ein repräsentatives Muster des Englischen darzustellen.
Verständnisfrage
Versuche das Rätsel zu entschlüsseln, wenn du möchtest – es ist für den Rest des Moduls jedoch nicht erforderlich. Klicke auf das Dreieck unten, um die Lösung zu sehen.
Antwort:
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.
Das obige Beispiel ist mit einem „Schlüssel" verknüpft – einer Zuordnung von den verschlüsselten zu den entschlüsselten Buchstaben. In diesem Fall lautet der Schlüssel:
- A (nicht verwendet, nennen wir ihn Z)
- B->Y
- C (nicht verwendet, nennen wir ihn X)
- D->W
- E->V
- F->U
- ...
Und so weiter. Gelinde gesagt ist das kein guter Schlüssel. Schlüssel, bei denen die verschlüsselten und entschlüsselten Buchstaben einfach verschobene Versionen des Alphabets sind (wie A->B und B->C), werden als „Caesar-Verschiebungs-Chiffren" bezeichnet.
Beachte, dass diese sehr schwer zu knacken sind, wenn sie kurz sind. Wenn sie sehr kurz sind, sind sie sogar unbestimmt. Betrachte:
URYYP
Es gibt viele mögliche Entschlüsselungen mit verschiedenen Schlüsseln: HELLO, PETTY, HAPPY, JIGGY, STOOL. Fallen dir noch weitere ein?
Wenn du jedoch viele solcher Nachrichten sendest, wird die Verschlüsselung irgendwann geknackt. Du solltest also denselben „Schlüssel" nicht zu oft verwenden. Am besten ist es, eine bestimmte Substitution nur einmal zu verwenden – nicht nur in einer einzigen Nachricht, sondern nur für ein einziges Zeichen! Das bedeutet: Du hast für jedes Zeichen der Nachricht ein eigenes Verschlüsselungsschema oder einen eigenen Schlüssel, der in der Reihenfolge der Nachricht angewendet wird. Wenn du deiner Freundin oder deinem Freund eine Nachricht schicken möchtest, bräuchtet ihr beide einen Notizzettel (in alten Zeiten), auf dem dieser sich ständig ändernde Schlüssel steht. Du verwendest ihn nur einmal. Das nennt man einen „Einmalschlüssel" (engl. „one-time pad").
Der Einmalschlüssel
Schauen wir uns anhand eines Beispiels an, wie das funktioniert. Man könnte das vollständig mit Buchstaben durchführen, aber es ist üblich, Buchstaben in Zahlen umzuwandeln, etwa indem man A=0, B=1, C=2… zuweist. Angenommen, wir sind befreundet und in geheimnisvollen Aktivitäten verwickelt, und wir haben einen gemeinsamen Notizzettel. Idealerweise hätten wir viele solcher Zettel, aber der für heute lautet:
EDGRPOJNCUWQZVMK…
Oder, in Zahlen umgerechnet nach Position im Alphabet:
4,3,6,17,15, 14, 9, 13, 2, 20, 22, 16, 25, 21, 12, 10…
Angenommen, ich möchte dir folgende Nachricht mitteilen:
„I love quantum!"
Oder gleichwertig:
8, 11, 14, 21, 4, 16, 20, 0, 13, 19, 20, 12
Wir wollen den obigen Code nicht direkt senden; das wäre eine einfache Substitution, die überhaupt nicht sicher ist. Wir wollen ihn auf irgendeine Weise mit unserem Schlüssel kombinieren. Eine gängige Methode ist die Addition modulo 26. Wir addieren den Wert der Nachricht zum Wert des Schlüssels, mod 26, bis wir das Ende der Nachricht erreichen. Wir würden also senden:
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
Beachte: Wenn jemand das abfängt und den Schlüssel NICHT hat, ist eine Entschlüsselung völlig hoffnungslos! Nicht einmal die beiden „u"s in „quantum" werden mit derselben Zahl codiert! Das erste ist eine 3, das zweite eine 16 – im selben Wort!
Ich sende dir das also, und du hast denselben Schlüssel wie ich. Du machst die Addition modulo 26 rückgängig, von der du weißt, dass ich sie durchgeführt habe:
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),…
Sodass die Nachricht x1, x2, x3, x4… lauten muss:
8, 11, 14, 21…
Und nach Umwandlung in Text ergibt das:
„I love quantum".
Das ist ein Einmalschlüssel.
Beachte: Wenn der Schlüssel kürzer als die Nachricht ist, beginnen wir unsere Codierung zu wiederholen. Das wäre immer noch ein schwer zu lösendes Entschlüsselungsproblem, aber nicht unmöglich, wenn es oft genug wiederholt wird. Du benötigst also einen langen Schlüssel (oder „Zettel").
In vielen Kontexten sind Studierende mit dieser Verschlüsselung bereits vertraut, sodass diese Aktivität übersprungen werden kann. Sie ist jedoch eine relativ schnelle und einfache Auffrischung.
Schritt 1: Such dir eine Partnerin oder einen Partner und teile eine Folge von 4 Buchstaben als Schlüssel. Jede schulisch angemessene 4-Buchstaben-Folge ist geeignet.
Schritt 2: Wähle ein geheimes 4-Buchstaben-Wort, das du deiner Partnerin oder deinem Partner schicken möchtest (beide machen das, sodass ihr euch gegenseitig unterschiedliche Geheimwörter schickt).
Schritt 3: Wandle den 4-Buchstaben-Schlüssel/Zettel und die jeweiligen 4-Buchstaben-Geheimwörter mit A = 1, B = 2 usw. in Zahlen um.
Schritt 4: Kombiniere dein 4-Buchstaben-Wort mit dem Einmalschlüssel mittels Addition modulo 26.
Schritt 5: Übergib deiner Partnerin oder deinem Partner die Zahlenfolge, die dein Geheimwort codiert, und erhalte im Gegenzug deren oder dessen Folge.
Schritt 6: Entschlüsselt gegenseitig eure Wörter mit Subtraktion modulo 26.
Schritt 7: Überprüft das Ergebnis. Hat es funktioniert?
Nachbereitung
Tauscht verschlüsselte Wörter mit einer anderen Gruppe aus, die keinen Zugang zu eurem Einmalschlüssel hat. Könnt ihr diese entschlüsseln? Erkläre, warum oder warum nicht.
Die obige Aktivität macht hoffentlich deutlich, dass ein Einmalschlüssel eine unknackbare Verschlüsselungsform ist – unter bestimmten Voraussetzungen:
- Der Schlüssel ist genauso lang wie die zu sendende Nachricht oder länger
- Der Schlüssel ist wirklich zufällig
- Der Schlüssel wird nur einmal verwendet und danach verworfen
Das ist also großartig. Wir haben eine unknackbare Verschlüsselung… es sei denn, jemand erhält unseren Schlüssel. Wenn jemand unseren Schlüssel bekommt, ist alles entschlüsselt. Dieser Unterschied zwischen unknackbarer Verschlüsselung und der vollständigen Preisgabe aller Geheimnisse macht den Austausch eines sicheren Schlüssels äußerst wichtig. Das Ziel der Quantenschlüsselverteilung (Quantum Key Distribution) ist es, die Einschränkungen, die die Natur quantenmechanischer Information auferlegt, zur Absicherung eines gemeinsamen Schlüssels bzw. Einmalzettels zu nutzen.
Quantenzustände als Schlüssel verwenden
Gehen wir davon aus, dass wir mit Qubits arbeiten (wobei zu betonen ist, dass Qubits zwei Eigenzustände haben). Man könnte Quantensysteme mit einer höheren Anzahl von Quantenzuständen verwenden, aber die modernsten Quantencomputer von IBM® nutzen Qubits. Unsere Buchstaben A, B, C lassen sich problemlos in Folgen von 0en und 1en codieren. Es reicht also aus, einen Schlüssel aus 0en und 1en auszutauschen und für jedes Bit, das einen Buchstaben speichert, die Addition modulo 2 durchzuführen.
Verständnischeck
Lies die folgende Frage, überlege dir deine Antwort und klicke dann auf das Dreieck, um die Lösung zu sehen.
Wie viele Bits brauchen wir, wenn uns nur englische Buchstaben interessieren?
Antwort:
Unsere Freunde Alice und Bob möchten einen Quantenschlüssel so austauschen, dass niemand sonst ihn abfangen kann (zumindest nicht ohne ihr Wissen). Sie benötigen eine Möglichkeit, Quantenzustände aneinander zu senden. Das mit hoher Treue und ohne Rauschen/Fehler zu tun, ist alles andere als trivial. Aber es gibt zwei Ansätze, die wir an diesem Punkt verstehen können sollten:
- Ein Glasfaserkabel ermöglicht die Übertragung von Licht – das sehr quantenmechanisch ist. Einzelne Photonen können über viele Kilometer Glasfaserkabel mit hoher Treue detektiert werden. Das ist kein perfekter, fehlerfreier Quantenkanal, aber er kann sehr gut sein.
- Wir könnten Quantenteleportation verwenden, wie in einem vorherigen Modul beschrieben. Das heißt, Alice und Bob könnten verschränkte Qubits teilen, und ein Zustand könnte mithilfe des Teleportationsprotokolls von Alice zu Bob übertragen werden.
Für dieses Modul wollen wir nicht voraussetzen, dass du hochpräzise optische Aufbauten zum Austauschen von Photonen hast, deshalb nutzen wir die zweite Methode zum Austauschen von Quantenzuständen. Das bedeutet aber nicht, dass sie für den Austausch von Quantenschlüsseln über große Entfernungen am realistischsten ist.
Wir werden nun ein Protokoll erkunden, das erstmals von Charles Bennett und Gilles Brassard im Jahr 1984 beschrieben wurde und den Austausch von Zuständen beinhaltet, die in verschiedenen Basen von Alice zu Bob gemessen werden. Wir verwenden ein cleveres Messverfahren, um schrittweise einen Schlüssel für die spätere Verschlüsselung aufzubauen. Mit anderen Worten: Wir verteilen einen Quantenschlüssel zwischen zwei Parteien, die kommunizieren möchten – daher der Begriff „Quantum Key Distribution" (QKD).
QKD-Schritt 1: Alices zufällige Bits und zufällige Basen
Alice beginnt damit, eine zufällige Folge von 0en und 1en zu erzeugen. Anschließend wählt sie zufällig eine Basis aus, in der sie einen Quantenzustand vorbereitet – basierend auf jedem zufälligen Bit und unter Verwendung der folgenden Tabelle (die auch Bob kennt):
| Basis | bit = 0 | bit = 1 |
|---|---|---|
| Z | ||
| X |
Angenommen, Alice hat zufällig eine 0 erzeugt und zufällig die X-Basis ausgewählt. Dann würde sie den Quantenzustand vorbereiten. Man kann durchaus Quantenzufälligkeit nutzen, um eine zufällige Folge von 0en und 1en sowie eine zufällige Basiswahl zu erzeugen. Nehmen wir zunächst einfach an, dass eine zufällige Folge wie folgt erzeugt wurde:
| Alices Bits | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | ... |
|---|---|---|---|---|---|---|---|---|---|---|
| Alices Basen | X | X | Z | Z | Z | X | Z | Z | X | ... |
| Alices Zustände | ... |
Diese Folge zufälliger Bits, Basen und resultierender Zustände würde in einer langen Sequenz fortgesetzt werden, um einen ausreichend langen Schlüssel zu erzeugen.
QKD-Schritt 2: Bobs zufällige Basen
Bob trifft ebenfalls eine zufällige Basiswahl. Während Alice die Basiswahl jedoch zur Vorbereitung ihres Zustands nutzte, wird Bob in diesen Basen tatsächlich Messungen durchführen. Wählt Bob dieselbe Basis, in der Alice ihren Zustand vorbereitet hat, so lässt sich das Ergebnis von Bobs Messung vorhersagen. Wenn Bob zufällig eine andere Basis als die von Alice verwendete wählt, können wir das Ergebnis von Bobs Messung nicht vorhersagen.
| Alices Bits | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | ... |
|---|---|---|---|---|---|---|---|---|---|---|
| Alices Basen | X | X | Z | Z | Z | X | Z | Z | X | ... |
| Alices Zustände | ... | |||||||||
| Bobs Basen | X | Z | X | Z | X | X | Z | X | X | ... |
| Bobs Zustände (a priori) | ? | ? | ? | ? | ... | |||||
| Bobs Zustände (gemessen) | ... | |||||||||
| Betrachte in der folgenden Tabelle die erste Spalte. Alice hat den Zustand vorbereitet, der ein Eigenzustand von X ist. Da Bob zufällig ebenfalls entschieden hat, in der X-Basis zu messen, gibt es für Bobs gemessenen Zustand nur ein mögliches Ergebnis: In der zweiten Spalte haben sie jedoch unterschiedliche Basen gewählt. Der von Alice gesendete Zustand ist Dieser hat eine 50%ige Chance, von Bob im Zustand gemessen zu werden, und eine 50%ige Chance, im Zustand gemessen zu werden. Die Zeile, die zeigt, was wir a priori über Bobs Messungen wissen, kann daher für Spalte 2 nicht ausgefüllt werden. Bob wird jedoch eine Messung durchführen und einen Eigenzustand von (in dieser Spalte) Z erhalten. In der untersten Zeile tragen wir ein, was diese Messungen tatsächlich ergaben. |
QKD-Schritt 3: Öffentliche Diskussion der Basen
Alice und Bob können nun gegenseitig mitteilen, welche Basis sie jeweils gewählt haben. Für alle Spalten, in denen sie zufällig dieselbe Basis gewählt haben, weiß jeweils die andere Person mit Sicherheit, welchen Zustand die andere hatte. Bob kann den Zustand und die Basis gemäß der gemeinsam vereinbarten Konvention in eine 0 oder 1 umwandeln. Wir können die obige Tabelle neu schreiben, sodass sie nur die Fälle zeigt, in denen Alices und Bobs Basen übereinstimmten:
| Alices Bits | 0 | 0 | 1 | 0 | 0 | ... |
|---|---|---|---|---|---|---|
| Alices Basen | X | Z | X | Z | X | ... |
| Alices Zustände | ... | |||||
| Bobs Basen | X | Z | X | Z | X | X |
| Bobs Zustände (a priori) | ... | |||||
| Bobs Zustände (gemessen) | ... | |||||
| Bobs Bits | 0 | 0 | 1 | 0 | 0 | ... |
Alice hat die Bitfolge 00100… erfolgreich an Bob übermittelt. Wenn die Freunde im Voraus vereinbart haben, 5-Bit-Zeichenketten als Zahlen in ihrem Einmalschlüssel zu verwenden, würden diese ersten fünf Bits die Zahl ergeben.
QKD-Schritt 4: Verifizierung und Übermittlung des Geheimnisses
Bevor Alice und Bob weitermachen, sollten sie eine Teilmenge ihrer klassischen Bits vergleichen. Da sie nur Messungen von Qubits beibehalten haben, die mit derselben Basis vorbereitet und gemessen wurden, sollten alle gemessenen Werte übereinstimmen. Wenn ein sehr kleiner Prozentsatz nicht übereinstimmt, könnte dies auf Quantenrauschen oder Fehler zurückzuführen sein. Wenn jedoch viele nicht übereinstimmen, ist etwas schiefgelaufen!
Wir werden hier nicht darauf eingehen, welcher Anteil des Schlüssels zur Verifizierung genutzt werden sollte. Für jetzt nehmen wir an, dass diese Prüfung gut verläuft; wir werden darauf im Abschnitt über Lauschangriffe weiter unten zurückkommen.
Die Freunde würden dann über klassische Kanäle eine verschlüsselte Nachricht aneinander senden. Sie würden die Zahlen in ihrem Einmalschlüssel verwenden, um geheime Nachrichten zu ver- und entschlüsseln, ohne den Einmalschlüssel jemals von einem Ort zum anderen zu übertragen. Für den nächsten Abschnitt über Lauschangriffe ist zu beachten, dass das gesamte Teilen des Schlüssels stattfindet, bevor das verschlüsselte Geheimnis über klassische Kanäle offenbart wird.
Alice und Bob haben ihre Basiswahl über klassische Kanäle mitgeteilt – könnte das also nicht abgefangen werden? Ja! Aber das Wissen um die verwendete Basis verrät einem nicht, welches Bit gesendet oder empfangen wurde. Das ist nur möglich, wenn man auch Alices Ausgangsbits kennt. Dann wäre man jedoch in Alices Computer, wo die Geheimnisse gespeichert sind, und eine geheime Kommunikation der Geheimnisse wäre ohnehin hinfällig. Das Abfangen der klassischen Kommunikation bricht also die Verschlüsselung nicht. Aber was ist mit dem Abfangen von Informationen im Quantenkanal?
Widerstandsfähigkeit von QKD gegenüber Lauschangriffen
Alice und Bob haben eine Freundin namens Eve, die für ihr Lauschen bekannt ist. Eve möchte Alices und Bobs Quantenschlüssel abfangen, um damit zwischen den beiden ausgetauschte Nachrichten zu entschlüsseln. Dies müsste notwendigerweise zwischen Alices Vorbereitung der Zustände und Bobs Messung der Zustände erfolgen, da die Messung den Quantenzustand kollabiert. Insbesondere bedeutet das, dass der Lauschangriff stattfinden müsste, bevor irgendeine Weitergabe oder Überprüfung von Basen stattgefunden hat.
Eve muss raten, welche Basis zur Codierung jedes Bits verwendet wurde. Kann sie auf Alices Computer nicht zugreifen, hat sie keine Grundlage für diese Vermutung, und sie wird zufällig raten. Nehmen wir an, Alices Ausgangslage ist dieselbe wie zuvor, und nehmen wir weiterhin an, dass Bobs zufällige Wahl der Messbasis dieselbe ist wie zuvor. Füllen wir aus, was Eve erhält, wenn sie den Quantenkanal misst. Wie zuvor: Wenn Eve zufällig dieselbe Basis wie Alice wählt, wissen wir, was sie erhalten wird. Wenn nicht, kann sie eines von zwei Ergebnissen mit jeweils 50%iger Wahrscheinlichkeit erhalten.
| Alices Bits | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | ... |
|---|---|---|---|---|---|---|---|---|---|---|
| Alices Basen | X | X | Z | Z | Z | X | Z | Z | X | ... |
| Alices Zustände | ... | |||||||||
| Eves Ratebasis | Z | X | X | Z | X | Z | Z | X | X | ... |
| Eves Zustände (a priori) | ? | ? | ? | ? | ? | ... | ||||
| Eves Zustände (gemessen) | ... | |||||||||
| Bobs Basen | X | Z | X | Z | X | X | Z | X | X | ... |
Da Eve nun nicht weiß, ob sie mit Alices Basis übereinstimmt oder nicht, weiß sie nicht, was sie an Bob weitersenden soll, um Alices ursprüngliche Zustände zu entsprechen. Wenn Eve beispielsweise misst, weiß sie nur mit Sicherheit, dass Alice für dieses Qubit den Zustand nicht vorbereitet hat. Aber Alice könnte oder vorbereitet haben – alles wäre mit Eves Messung vereinbar. Eve muss also eine Wahl treffen. Sie könnte genau den gemessenen Zustand weitersenden oder versuchen, die Fälle zu erraten, in denen ihre Messung nicht der von Alice gesendete Eigenzustand war. Wir nehmen eine Mischung in unsere Tabelle auf:
| Alices Bits | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | ... |
|---|---|---|---|---|---|---|---|---|---|---|
| Alices Basen | X | X | Z | Z | Z | X | Z | Z | X | ... |
| Alices Zustände | ... | |||||||||
| Eves Ratebasis | Z | X | X | Z | X | Z | Z | X | X | ... |
| Eves Zustände (a priori) | ? | ? | ? | ? | ? | ... | ||||
| Eves Zustände (gemessen) | ... | |||||||||
| Eves Zustände (weitergeleitet) | ... | |||||||||
| Bobs Basen | X | Z | X | Z | X | X | Z | X | X | ... |
| Bobs Zustände (a priori) | ? | ? | ... | |||||||
| Bobs Zustände (gemessen) | ... | |||||||||
| Bobs Bits | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | ... |
An diesem Punkt ist es berechtigt zu fragen: „Warum kopiert Eve nicht einfach Alices Quantenzustand, behält eine Kopie zum Messen und leitet die andere an Bob weiter?" Die Antwort ist das „No-Cloning"-Theorem. Informell besagt es, dass keine unitäre (quantenmechanische) Operation eine zweite Kopie eines beliebigen Quantenzustands anfertigen kann, während die erste Kopie erhalten bleibt. Der Beweis ist relativ einfach und wird als angeleitete Übung überlassen. Aber verstehe zunächst: Das Kopieren von Quantenzuständen durch Eve ist durch fundamentale Naturgesetze verboten, und das ist eine grundlegende Stärke von QKD. Wie zuvor würden Alice und Bob einander anrufen und ihre Basen vergleichen. Sie werden diese Tabelle auf die Fälle reduzieren, in denen die beiden Freunde dieselbe Basis gewählt haben:
| Alices Bits | 0 | 0 | 1 | 0 | 0 | ... |
|---|---|---|---|---|---|---|
| Alices Basen | X | Z | X | Z | X | ... |
| Alices Zustände | ... | |||||
| Eves Ratebasis | Z | Z | Z | Z | X | ... |
| Eves Zustände (a priori) | ? | ? | ... | |||
| Eves Zustände (gemessen) | ... | |||||
| Eves Zustände (weitergeleitet) | ... | |||||
| Bobs Basen | X | Z | X | Z | X | ... |
| Bobs Zustände (a priori) | ? | ... | ||||
| Bobs Zustände (gemessen) | ... | |||||
| Bobs Bits | 1 | 0 | 0 | 0 | 0 | ... |
Alice und Bob haben erneut eine Bitfolge kommuniziert… aber die Folgen stimmen nicht überein. Das ganz linke und das mittlere Bit sind vertauscht. In der vorherigen Tabelle lässt sich diese Diskrepanz auf Eves Einmischung zurückführen. Wichtig ist: Wir können jetzt – während der Schlüsselaufbauphase, lange vor der Offenbarung des verschlüsselten Geheimnisses – Statistiken über die Übereinstimmung unserer Bitfolgen erheben. Alice und Bob können so viele ihrer Einmalschlüssel-Bits wie gewünscht verwenden, um die Sicherheit ihres Kanals zu prüfen. Wenn ein einziges Bit oder ein sehr kleiner Prozentsatz der Bits nicht übereinstimmte, könnte das auf Rauschen oder Fehler zurückzuführen sein. Ein erheblicher Anteil an Abweichungen deutet jedoch auf einen Lauschangriff hin. Was „erheblich" dabei bedeutet, hängt etwas vom Rauschen der verwendeten Anlage ab; was das für IBM® Quantencomputer bedeutet, wird weiter unten bei der Implementierung dieses Protokolls besprochen. Werden übermäßige Fehler festgestellt, teilen Alice und Bob das Geheimnis nicht, und sie können damit beginnen, nach dem Lauscher zu suchen.
Einschränkungen
Der Beweis der Sicherheit ist äußerst schwierig. Tatsächlich wurde das hier grob beschriebene Protokoll 1984 vorgeschlagen und erst 16 Jahre später als sicher bewiesen: Shor & Preskill, 2000. Es gibt viele Feinheiten, die den Rahmen dieser Einführung sprengen. Wir werden jedoch kurz einige davon aufführen, um zu zeigen, dass das Thema komplexer ist, als hier dargestellt.
- Sichere Kanäle: Wenn Alice ihre Qubits durch ein quantenmechanisches Setup (einen Kanal) sendet und insbesondere klassische Antworten von jemandem empfängt, haben wir angenommen, dass es sich dabei tatsächlich um Bob handelt. Wenn Eve dieses Setup so infiltriert hat, dass sämtliche Kommunikation von Alice tatsächlich mit Eve stattfindet und sämtliche Kommunikation von Bob ebenfalls mit Eve abgewickelt wird, hat Eve effektiv einen Schlüssel erhalten und kann Geheimnisse erfahren. Man muss zunächst „sichere Kanäle" gewährleisten – ein Prozess mit einem anderen Satz von Protokollen, den wir hier nicht behandelt haben.
- Annahmen über Eve: Um die Sicherheit wirklich zu beweisen, dürfen wir keine Annahmen über Eves Verhalten treffen; sie könnte unsere Erwartungen immer wieder unterlaufen. Hier treffen wir zur Veranschaulichung konkrete Annahmen. Wir könnten etwa annehmen, dass die Zustände, die Eve an Bob weiterleitet, immer genau jene sind, die sie bei der Messung erhalten hat. Oder wir könnten annehmen, dass sie zufällig einen Zustand wählt, der experimentell mit ihrer Messung vereinbar ist. Grundlegender noch: Die hier verwendete Sprache setzt voraus, dass Eve tatsächlich eine Messung durchführt, anstatt den Zustand auf einem anderen Quantensystem zu speichern und Bob ein zufälliges Qubit zu senden. Diese Annahmen sind sinnvoll, um das Protokoll zu verstehen, bedeuten aber auch, dass wir nichts in voller Allgemeinheit beweisen.
- Privacy Amplification: Alice und Bob müssen den Quantenschlüssel nicht genau so verwenden, wie er übertragen wurde. Sie können beispielsweise eine Hash-Funktion auf den gemeinsamen Schlüssel anwenden. Damit würde die Tatsache ausgenutzt, dass der Lauscher nur unvollständige Kenntnisse des Schlüssels hat, um einen kürzeren, aber sicheren gemeinsamen Schlüssel zu erzeugen.
Experiment 1: QKD ohne Lauschangriff
Lass uns das obige Protokoll ohne Lauschangriff implementieren. Wir tun dies zunächst mit einem Simulator, um den Arbeitsablauf zu verstehen.
Zunächst ein Hinweis zu Quantensimulatoren: Die meisten Quantenprobleme mit mehr als ~30 Qubits können von den meisten Computern nicht simuliert werden. Kein klassischer Computer, kein Supercomputer und keine GPU kann das volle Verhaltsspektrum eines 127-Qubit-Quantencomputers simulieren. Normalerweise ist die Motivation für den Einsatz echter Quantencomputer, dass die vielen verschränkten Qubits nicht simuliert werden können. In diesem Fall gibt es keine Verschränkung von Qubits, es sei denn, wir nutzen das Teleportationsschema zur Informationsübertragung. Hier liegt die Motivation für den Einsatz echter Quantencomputer anders: Es ist das No-Cloning-Theorem. Ein klassischer Computer, der ein Qubit simuliert, könnte Informationen über einen Quantenzustand von Alice zu Bob senden, aber wenn diese klassischen Informationen abgefangen würden, könnten sie leicht dupliziert werden, und Eve könnte eine perfekte Kopie behalten, während sie eine andere an Bob sendet. Das ist mit echten Quantenzuständen nicht möglich.
IBM Quantum empfiehlt, Quantencomputingprobleme mit einem Framework anzugehen, das wir „Qiskit Patterns" nennen. Es besteht aus folgenden Schritten:
- Schritt 1: Bilde dein Problem auf einen Quantencircuit ab
- Schritt 2: Optimiere deinen Circuit für die Ausführung auf echter Quantenhardware
- Schritt 3: Führe deinen Job auf IBM-Quantencomputern mithilfe von Runtime-Primitiven aus
- Schritt 4: Verarbeite die Ergebnisse nach
Qiskit Patterns – Schritt 1: Problem auf einen Quantencircuit abbilden
Die Abbildung unseres Problems auf Quantencircuits reduziert sich in diesem Fall auf die bloße Vorbereitung von Alices Zuständen und das anschließende Einbeziehen von Bobs Messungen. Wir beginnen mit der Erzeugung zufälliger Bits und zufälliger Basen.
# 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)
Visualisieren wir die Bits, Basen und den Circuit. Beachte, dass die Basen manchmal übereinstimmen und manchmal nicht.
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.]
Qiskit Patterns Schritt 2: Problem für die Quantenausführung optimieren
Dieser Schritt übersetzt die gewünschten Operationen in die Funktionalität eines bestimmten Quantencomputers und ordnet unser Problem dem Layout des Quantencomputers zu.
Wir beginnen damit, mehrere Pakete zu laden, die für die Kommunikation mit IBM-Quantencomputern erforderlich sind. Außerdem müssen wir ein Backend auswählen, auf dem wir ausführen wollen. Wir können entweder das am wenigsten ausgelastete Backend wählen oder ein bestimmtes Backend mit bekannten Eigenschaften auswählen. Obwohl wir zunächst einen Simulator verwenden, ist es wichtig, ein realistisches Rauschmodell bei der Simulation zu nutzen, und es empfiehlt sich, den Arbeitsablauf so nah wie möglich an dem zu halten, was wir später für echte Quantencomputer verwenden werden.
Im folgenden Code findest du Anweisungen zum Speichern deiner Zugangsdaten bei der ersten Verwendung. Achte darauf, diese Informationen aus dem Notebook zu löschen, nachdem du sie in deiner Umgebung gespeichert hast, damit deine Zugangsdaten beim Teilen des Notebooks nicht versehentlich weitergegeben werden. Weitere Hinweise findest du unter IBM Cloud-Konto einrichten und Dienst in einer nicht vertrauenswürdigen Umgebung initialisieren.
# 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
Im Folgenden wählen wir einen Simulator und ein Rauschmodell aus.
# 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)
Qiskit Patterns Schritt 3: Ausführen
Verwende den Sampler, um deinen Job mit dem Circuit als Argument auszuführen.
# 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()
Qiskit Patterns Schritt 4: Nachverarbeitung
Hier interpretieren wir unsere Ergebnisse und extrahieren nützliche Informationen. Wir könnten versuchen, die Ausgabe unseres Samplers zu visualisieren, aber wir haben den Sampler auf unkonventionelle Weise eingesetzt. Anstatt viele Messungen unseres Circuits durchzuführen und Statistiken über die Zustände zu erstellen, haben wir nur eine einzige Messung (die von Bob) vorgenommen. Jedes Qubit, dessen Zustand in der gleichen Basis vorbereitet und gemessen wurde, sollte ein deterministisches Ergebnis liefern, sodass nur eine Messung erforderlich ist. Diejenigen Qubits, deren Zustände in unterschiedlichen Basen vorbereitet und gemessen wurden (die probabilistische Ergebnisse hätten und viele Messungen zur Interpretation erfordern würden), werden nicht verwendet, um unseren Einmalblock/Schlüssel aufzubauen. Lass uns eine Liste der Messergebnisse aus diesem Bitstring extrahieren. Achte darauf, die Reihenfolge umzukehren, wenn du mit Alices Bit-Array vergleichst, das wir zur Erzeugung des Circuits verwendet haben.
# 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]
Lass uns die von Alice und Bob zufällig gewählten Messbasen vergleichen. Dies war Schritt 3 in unserem QKD-Protokoll (öffentliche Diskussion der Basen). Jedes Mal, wenn sie die gleiche Basis für ein Qubit gewählt haben, fügen wir die mit diesem Qubit verbundenen Bits einer Liste von Bits hinzu, um Zahlen für einen Einmalblock zu erzeugen. Wenn die Basen nicht übereinstimmen, werden die Ergebnisse verworfen. Lass uns auch überprüfen, ob die beiden Bitlisten übereinstimmen oder ob es Verluste durch Rauschen oder andere Faktoren gab.
# 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
Alice und Bob haben jeweils eine Liste von Bits, die zu 100% übereinstimmen. Sie können diese verwenden, um Zahlen für einen Einmalblock zu erzeugen und anschließend QKD-Schritt 4 durchzuführen: ein Geheimnis senden und entschlüsseln. Die aktuelle Bit-Liste ist zu kurz, um irgendetwas Nennenswertes zu entschlüsseln. Wir werden darauf zurückkommen, nachdem wir das Abhören eingebaut haben.
Überprüfe dein Verständnis
Lies die folgende Frage, denk über deine Antwort nach und klicke dann auf das Dreieck, um die Lösung anzuzeigen.
Angenommen, du benötigst Ziffern, die groß genug sind, um Buchstaben im englischen Alphabet um dessen volle Länge oder mehr zu verschieben, obwohl es natürlich auch andere Kodierungsschemata gibt.
(a) Wie viele Buchstaben lang könnte eine Nachricht sein, die mit den Bits des obigen Schlüssels entschlüsselt werden kann? (b) Muss deine Antwort mit der deiner Kommilitonen übereinstimmen? Warum oder warum nicht?
Antwort:
(a) Die Antwort hängt davon ab, wie viele zufällig gewählte Basen zwischen Alice und Bob übereinstimmen. Da die Wahrscheinlichkeit einer Basisübereinstimmung für jedes Qubit ungefähr 50:50 beträgt, erwarten wir, dass rund 10 unserer Bits brauchbar sind. 9 oder 11 sind völlig normal. Auch 4 oder 15 liegen nicht außerhalb des Möglichen. Für eine Verschiebung um mindestens die Länge des englischen Alphabets werden 5 Bits benötigt, das bedeutet, du kannst die Verschiebung auf einen Buchstaben pro 5 Bits anwenden. Wenn Alice und Bob mindestens 5 gemeinsame Bits haben, können sie einen einzelnen Buchstaben verschlüsseln. Mit mindestens 10 Bits können sie 2 Buchstaben verschlüsseln usw. (b) Die Antwort muss nicht übereinstimmen, aus den in (a) genannten Gründen.
Experiment 2: QKD mit Lauschangriff
Wir implementieren exakt dasselbe Protokoll wie zuvor. Dieses Mal fügen wir jedoch eine weitere Messreihe durch Eve zwischen Alice und Bob ein.
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()
Qiskit Patterns Schritt 4 (Nachverarbeitung) ist in diesem Fall einfach. Da wir nur eine einzige Messung durchgeführt haben, muss die Verteilung der Messungen nicht visualisiert werden. Eve hat die folgenden 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)
[0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1]
Jetzt muss Eve Zustände rekonstruieren, die sie an Bob weiterschickt. Wie in der Einführung beschrieben, hat sie keine Möglichkeit zu wissen, ob sie die Kodierungsbasen richtig geraten hat, und kann daher nicht exakt die gleichen Zustände vorbereiten, die gesendet wurden. Sie könnte annehmen, dass jede Basiswahl korrekt war und genau das kodieren, was sie gemessen hat, oder sie könnte annehmen, dass sie die Basis falsch gewählt hat, und einen der Eigenzustände der entgegengesetzten Basis wählen. Der Einfachheit halber nehmen wir hier ersteres an. Wir erreichen dies, indem wir einen völlig neuen Quantencircuit aufbauen und die Qiskit-Patterns-Schritte wie zuvor wiederholen.
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]
Lass uns nun Alices und Bobs Bits vergleichen:
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
Zuvor stimmten die Bits in Alices und Bobs Schlüsseln perfekt überein. Nun sehen wir durch Eves Einmischung, dass die Bits von Alice und Bob in 14% der Fälle voneinander abweichen, die eigentlich übereinstimmen sollten, da Alice und Bob die gleichen Basen gewählt haben. Das sollte für Alice und Bob leicht zu erkennen sein. Allerdings bedeutet das Verlassen auf einen solchen Fehleranteil auch, dass es eine Grenze für das tolerierbare Rauschen im Quantenkanal gibt.
Experiment 3: QKD mit und ohne Lauschangriff auf einem echten Quantencomputer vergleichen
Lass uns das auf einem echten Quantencomputer ausführen. So können wir das No-Cloning-Theorem ausnutzen. Gleichzeitig haben echte Quantencomputer Rauschen und höhere Fehlerraten als klassische Computer. Lass uns daher den Fidelitätsverlust unserer Schlüsselbits mit und ohne Lauschangriff vergleichen, um sicherzustellen, dass der Unterschied bei der Verwendung eines echten Quantencomputers erkennbar ist. Wir beginnen ohne Lauschangriff:
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
Ohne Lauschangriff erzielten wir über diesen Satz von 127 Testbits eine Fidelität von 100%, was 55 übereinstimmende Basen und brauchbare Schlüsselbits ergab. Lass uns dieses Experiment nun mit Eve als Lauscherin wiederholen:
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
Hier haben wir einen Fidelitätsverlust von fast 23% bei den gemeinsamen Bits durch den Lauschangriff festgestellt! Das ist sehr gut erkennbar! Beachte, dass die Übertragung von Quanteninformationen über große Entfernungen zusätzliches Rauschen und Fehler einführen kann. Sicherzustellen, dass ein Lauschangriff auch bei Rauschen erkennbar ist, selbst wenn Eve alle ihr zur Verfügung stehenden Tricks einsetzt, ist ein komplexes Thema, das über diese Einführung hinausgeht.
Fragen
Lehrkräfte können Versionen dieser Notebooks mit Lösungsschlüsseln und Hinweisen zur Einbettung in gängige Lehrpläne anfordern, indem sie diese kurze Umfrage ausfüllen und angeben, wie die Notebooks verwendet werden.
Kernkonzepte
- Quanteninformationen können nicht kopiert oder „geklont" werden.
- Du kannst denselben Vorbereitungsprozess wiederholen, um ein Ensemble von Quantenzuständen herzustellen, die alle gleich oder nahezu gleich sind.
- Ein Ver-/Entschlüsselungsschlüssel (ein Einmalblock) kann zwischen zwei Personen mithilfe von Quantenzuständen ausgetauscht werden.
- Wenn zwei Personen zufällig eine Messbasis wählen, werden sie in der Hälfte der Fälle unterschiedliche Basen wählen und müssen die Informationen zu diesen Qubits verwerfen.
- Die zufällige Wahl der Messbasis stellt außerdem sicher, dass eine lauschende Person den vorbereiteten Ausgangszustand nicht kennen kann und daher den gesendeten Zustand nicht rekonstruieren kann. Dies gewährleistet, dass der Lauschangriff erkannt wird.
Wahr/Falsch-Fragen
- W/F Bei der Quantenschlüsselverteilung messen die beiden kommunizierenden Parteien jedes Qubit in der gleichen Basis.
- W/F Eine lauschende Person, die bei QKD Quanteninformationen abfängt, wird durch die Naturgesetze daran gehindert, den abgefangenen Quantenzustand zu kopieren.
- W/F Ein Einmalblock ist ein Schlüssel zur Ver-/Entschlüsselung gesicherter Nachrichten, bei dem ein bestimmtes Kodierungsschema nur einmal für eine einzige Information (z. B. einen Buchstaben des Alphabets) verwendet wird.
Multiple-Choice-Fragen
- Wähle die Option, die die Aussage am besten vervollständigt. Wie in diesem Modul beschrieben, ist ein Einmalblock ein Satz von Ver-/Entschlüsselungsschlüsseln, der verwendet wird...
- a. Nur einmal für eine einzelne Information, wie einen einzelnen Buchstaben.
- b. Nur einmal für eine einzelne Nachricht.
- c. Nur einmal für einen bestimmten Zeitraum, z. B. einen Tag.
- d. Bis es Hinweise auf einen Lauschangriff gibt.
- Angenommen, Alice und Bob wählen ihre Messbasen zufällig. Sie messen. Dann teilen sie ihre Messbasen und behalten nur die Informationsbits aus den Fällen, in denen sie die gleiche Basis verwendet haben. Bei zufälligen Schwankungen: Ungefähr wie viel Prozent ihrer Qubits sollten brauchbare Informationsbits liefern?
- a. 100%
- b. 50%
- c. 25%
- d. 12,5%
- e. 0%
- Nachdem Alice und Bob die Fälle ausgewählt haben, in denen sie die gleichen Messbasen verwendet haben: Wie viel Prozent dieser Informationsbits sollten übereinstimmen, wenn Quantenrauschen und -fehler vernachlässigbar wären?
- a. 100%
- b. 50%
- c. 25%
- d. 12,5%
- e. 0%
- Angenommen, Alice hat ihre Messbasen zufällig gewählt. Eve wählt ihre Basen ebenfalls zufällig und lauscht (misst). Sie sendet an Bob Zustände, die mit ihren Messungen übereinstimmen. Alice und Bob vergleichen ihre Basiswahlen und behalten nur die Qubits, die von ihnen in den gleichen Basen gemessen/vorbereitet wurden. Bei zufälligen Schwankungen: Ungefähr wie viel Prozent der behaltenen Qubit-Messungen werden laut Alice und Bob übereinstimmen?
- a. 100%
- b. 75%
- c. 50%
- d. 25%
- e. 12,5%
- f. 0%
Diskussionsfragen
-
Angenommen, alle Basiswahlen sind zufällig für alle Beteiligten – Alice, Bob und Eve. Angenommen, nachdem Eve gelauscht hat, sendet sie Bob einen Zustand, der in der gleichen Basis vorbereitet ist, in der sie gemessen hat, und der mit dieser Messung übereinstimmt. Überzeuge deine Lernpartner davon, dass 12,5% aller von Alice initialisierten Qubits Messabweichungen zwischen Alice und Bob liefern werden, die auf einen Lauschangriff hinweisen (Quantenfehler und Rauschen werden dabei ignoriert). Hinweis 1: Da es keine bevorzugte Basis gibt, sollte das Verhältnis für eine einzelne Anfangswahl von Alice gleich sein wie das Verhältnis für die Summe aller Wahlen. Hinweis 2: Es reicht möglicherweise nicht aus, die Anzahl der Möglichkeiten zu zählen, da manche Ergebnisse mit unterschiedlichen Wahrscheinlichkeiten auftreten können.
-
Angenommen, alle Basiswahlen sind wieder zufällig für alle Beteiligten – Alice, Bob und Eve. Aber jetzt bedenke, dass Eve nach ihrer Messung frei wählen kann, welchen Zustand sie weitersendet. Sie könnte sogar versuchen, Zustände zu senden, die mit ihren eigenen Messungen nicht übereinstimmen. Diskutiere mit deinen Lernpartnern, ob du denkst, dass es eine Basiswahl gibt, die den durchschnittlichen Anteil der Qubits, die Alice und Bob auf einen Lauschangriff hinweisen, unter den Mittelwert senken könnte.