Vai al contenuto principale

Distribuzione quantistica delle chiavi

Per questo modulo di Qiskit in Classrooms, gli studenti devono avere un ambiente Python funzionante con i seguenti pacchetti installati:

  • qiskit v2.1.0 o più recente
  • qiskit-ibm-runtime v0.40.1 o più recente
  • qiskit-aer v0.17.0 o più recente
  • qiskit.visualization
  • numpy
  • pylatexenc

Per configurare e installare i pacchetti sopra indicati, consulta la guida Installare Qiskit. Per eseguire job su veri computer quantistici, gli studenti dovranno creare un account con IBM Quantum® seguendo i passaggi nella guida Configura il tuo account IBM Cloud.

Questo modulo è stato testato e ha utilizzato 5 secondi di tempo QPU. Si tratta solo di una stima. Il tuo utilizzo effettivo potrebbe variare.

# 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'

Guarda la presentazione del modulo della dott.ssa Katie McCormick qui sotto, oppure clicca qui per vederla su YouTube.


Introduzione e motivazione​

Esistono infiniti modi di cifrare e decifrare informazioni, e letteralmente migliaia di metodi sono stati ben studiati. Qui ci limiteremo a un metodo di cifratura molto antico e molto semplice, chiamato "sostituzione semplice", per concentrarci sulla parte quantistica di questo protocollo. La parte quantistica potrebbe essere adattata a molti altri protocolli con modifiche relativamente poche.

Sostituzione semplice​

Una cifratura a sostituzione semplice è quella in cui una lettera o un numero viene sostituito con un altro, in modo tale che esista una corrispondenza 1:1 tra le lettere e i numeri in un messaggio e le lettere e i numeri utilizzati in una sequenza cifrata. Un esempio di cultura pop sono i puzzle crittografici (cryptoquote o cryptogram), in cui una citazione o una frase è cifrata usando la sostituzione semplice, e il giocatore deve decifrarla. Questi sono facili da risolvere se sono abbastanza lunghi. Considera l'esempio:

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.

Le persone che risolvono questi puzzle a mano usano principalmente trucchi legati alla familiarità con la struttura della lingua del messaggio originale. Per esempio, in inglese, le uniche parole di una lettera come la "R" cifrata sono "a" e "I". Le doppie lettere cifrate in, per esempio, "KIVGGB" possono assumere solo certi valori. Ci sono cose più sottili che danno indizi, come il fatto che la parola più comune che corrisponde al pattern "GSZG" è "that". Le persone che usano codice per risolvere questi puzzle hanno molte più opzioni, tra cui semplicemente scorrere le possibilità finché non viene recuperata una parola in inglese, e aggiornare preservando quella parola. Un metodo semplice ma potente è l'utilizzo della frequenza delle lettere, specialmente quando il messaggio è abbastanza lungo da costituire un campione rappresentativo dell'inglese.

Domanda di verifica​

Prova a decifrare questo se vuoi, anche se non è necessario per il resto del modulo. Clicca sul triangolo qui sotto per vedere il messaggio.

Risposta:

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.

L'esempio sopra è associato a una "chiave", una mappatura dalle lettere cifrate a quelle decifrate. In questo caso, la chiave è:

  • A (non usata, diciamo Z)
  • B->Y
  • C (non usata, diciamo X)
  • D->W
  • E->V
  • F->U
  • ...

E così via. Per dirla con delicatezza, questa non è una buona chiave. Le chiavi in cui le lettere cifrate e quelle decifrate sono semplicemente versioni spostate dell'alfabeto (come A->B e B->C) sono chiamate cifrari a "spostamento di Cesare".

Nota che questi sono molto difficili se sono brevi. In effetti, se sono molto brevi, sono indeterminati. Considera:

URYYP

Esistono molte possibili decifrature, usando chiavi diverse: HELLO, PETTY, HAPPY, JIGGY, STOOL. Riesci a pensarne altre?

Ma se invii molti messaggi così, alla fine la cifratura verrà decifrata. Quindi non dovresti usare la stessa "chiave" troppo spesso. In effetti, la cosa migliore è usare una certa sostituzione solo una volta. Non in un solo messaggio, ma solo per un singolo carattere! Con questo intendiamo che avrai uno schema di cifratura o chiave per ogni carattere usato nel messaggio, in ordine. Se vuoi inviare un messaggio a un amico usando questo sistema, tu e il tuo amico avreste bisogno di un blocco di carta (nei tempi antichi) su cui è scritta questa chiave sempre mutevole. Lo userete una sola volta. Questo si chiama "one-time pad".

Il one-time pad​

Vediamo come funziona con un esempio. Si potrebbe fare tutto con lettere, ma è comune convertire le lettere in numeri, ad esempio assegnando A=0, B=1, C=2…. Supponiamo di essere amici coinvolti in attività clandestine e di aver condiviso un blocco. Idealmente, condivideremmo molti blocchi, ma quello di oggi è:

EDGRPOJNCUWQZVMK…

Oppure, convertendo in numeri per posizione nell'alfabeto:

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

Supponiamo che io voglia condividere con te il messaggio:

"I love quantum!"

Oppure, equivalentemente:

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

Non vogliamo inviare il codice sopra; è una sostituzione semplice, che non è affatto sicura. Vogliamo combinarlo con la nostra chiave in qualche modo. Un modo comune è l'addizione modulo 26. Aggiungiamo il valore del messaggio al valore della chiave, mod 26, fino alla fine del messaggio. Quindi invieremmo

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

Nota che se qualcuno intercetta questo e NON ha la chiave, decifrarlo è assolutamente impossibile! Nemmeno le due "u" in "quantum" sono codificate con lo stesso numero! La prima è un 3, e la seconda è un 16… nella stessa parola!

Quindi, ti invio questo, e tu hai la stessa chiave che ho io. Annulli l'addizione modulo 26 che sai che ho eseguito:

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),…

In modo tale che il messaggio x1, x2, x3, x4… deve essere

8, 11, 14, 21…

Infine, convertendo in testo, otteniamo

"I love quantum".

Questo è un one-time pad.

Nota che se la chiave è più corta del messaggio, iniziamo a ripetere la nostra codifica. Sarebbe ancora un problema di decifratura difficile da risolvere, ma non impossibile se viene ripetuta abbastanza volte. Quindi, hai bisogno di una chiave (o "blocco") lunga.

nota

In molti contesti, gli studenti avranno già familiarità con questa cifratura, tale che questa attività può essere saltata. Ma è un ripasso relativamente rapido e semplice.

Passo 1: Trova un partner e condividete una sequenza di 4 lettere da usare come chiave. Qualsiasi sequenza di 4 lettere adatta alla classe andrà bene.
Passo 2: Scegli una parola segreta di 4 lettere che vuoi inviare al tuo partner (entrambi i partner lo fanno, così vi inviate parole segrete diverse)
Passo 3: Converti la chiave/blocco di 4 lettere e ciascuna delle parole segrete di 4 lettere in numeri usando A = 1, B = 2, e così via.
Passo 4: Combina la tua parola di 4 lettere con il one-time pad usando l'addizione modulo 26.
Passo 5: Consegna al tuo partner la sequenza di numeri che codifica la tua parola segreta, e il tuo partner ti consegnerà la sua.
Passo 6: Decodificate le parole reciproche usando la sottrazione modulo 26.
Passo 7: Verifica. Ha funzionato?

Domanda di approfondimento​

Scambia le parole cifrate con un altro gruppo che non ha accesso al tuo one-time pad. Riesci a decifrarle? Spiega perché sì o perché no?

Si spera che l'attività sopra renda chiaro che un one-time pad è una forma di cifratura inviolabile, date alcune assunzioni, come:

  • La chiave è della stessa lunghezza del messaggio da inviare, o più lunga
  • La chiave è veramente casuale
  • La chiave viene utilizzata una sola volta e poi scartata

Quindi questo è ottimo. Abbiamo una cifratura inviolabile... a meno che qualcuno non ottenga la nostra chiave. Se qualcuno ottiene la nostra chiave, tutto viene decifrato. Questa differenza tra una cifratura inviolabile e l'avere tutti i nostri segreti esposti rende la condivisione di una chiave sicura estremamente importante. L'obiettivo della distribuzione quantistica delle chiavi è sfruttare i vincoli che la natura ha imposto sull'informazione quantistica per proteggere una chiave condivisa/one-time pad.

Utilizzo degli stati quantistici come chiave​

Assumiamo di lavorare con i qubit (sottolineando che i qubit hanno due autostati). Si potrebbero usare sistemi quantistici con un numero maggiore di stati quantistici, ma i computer quantistici all'avanguardia di IBM® usano i qubit. Non è un problema codificare le nostre A, B, C in sequenze di 0 e 1. Quindi è sufficiente per noi condividere una chiave di 0 e 1 ed eseguire l'addizione modulo 2 su ogni bit che memorizza una lettera.

Verifica della comprensione​

Leggi la domanda qui sotto, pensa alla tua risposta, poi clicca sul triangolo per rivelare la soluzione.

Se ci interessano solo le lettere inglesi, di quanti bit abbiamo bisogno?

Risposta:

24=1625=32→5 bit2^4=16\\ 2^5 = 32 \rightarrow 5 \text{ bit}

I nostri amici, Alice e Bob, vorrebbero condividere una chiave quantistica in modo tale che nessun altro possa intercettarla (almeno non senza che loro lo sappiano). Hanno bisogno di un modo per inviarsi stati quantistici. Farlo con alta fedeltà e senza rumore/errori NON è banale. Ma ci sono due approcci che dovremmo essere in grado di comprendere a questo punto:

  1. Un cavo a fibra ottica ti permette di inviare luce… che è molto quantomeccanica. Singoli fotoni possono essere rilevati con alta fedeltà su molti chilometri di cavo a fibra ottica. Questo non è un canale quantistico perfetto e privo di errori, ma potrebbe essere molto buono.
  2. Potremmo usare la teleportazione quantistica, come descritto in un modulo precedente. Cioè, Alice e Bob potrebbero condividere qubit entangled e uno stato potrebbe essere inviato da Alice a Bob usando il protocollo di teleportazione.

Per questo modulo, non vogliamo richiedere di avere configurazioni ottiche ad alta fedeltà per la condivisione di fotoni, quindi useremo il secondo metodo per condividere stati quantistici. Ma questo non vuol dire che sia il più realistico per la condivisione a lunga distanza di chiavi quantistiche.

Esploreremo ora un protocollo descritto per la prima volta da Charles Bennett e Gilles Brassard nel 1984 per la condivisione di stati misurati in basi diverse tra Alice e Bob. Useremo un intelligente regime di misurazione per costruire una chiave da utilizzare nelle successive cifrature. In altre parole, stiamo distribuendo una chiave quantistica tra due parti che desiderano comunicare, da cui "distribuzione quantistica delle chiavi" (QKD).

QKD passo 1: i bit casuali e le basi casuali di Alice​

Alice inizierà generando una sequenza casuale di 0 e 1. Sceglierà poi casualmente una base in cui preparare uno stato quantistico, basandosi su ogni bit casuale, usando la tabella seguente (una tabella che ha anche Bob):

Basebit = 0bit = 1
Z∣0⟩\vert 0\rangle∣1⟩\vert 1\rangle
X∣+⟩\vert +\rangle∣−⟩\vert -\rangle

Per esempio, supponiamo che Alice abbia generato casualmente uno 0, e abbia selezionato casualmente la base X. Allora preparerebbe uno stato quantistico ∣ψ⟩=∣+⟩x=12(∣0⟩+∣1⟩)|\psi\rangle = |+\rangle_x = \frac{1}{\sqrt{2}}(|0\rangle+|1\rangle). Si può certamente sfruttare la casualità quantistica per generare un insieme casuale di 0 e 1, e una scelta casuale di base. Per ora, assumiamo semplicemente che un insieme casuale sia stato generato, come segue:

Bit di Alice010011010...
Basi di AliceXXZZZXZZX...
Stati di Alice∣+⟩\vert +\rangle∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣0⟩\vert 0\rangle∣1⟩\vert 1\rangle∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣1⟩\vert 1\rangle∣+⟩\vert +\rangle...

Questo insieme di bit casuali, basi e stati risultanti continuerebbe in una lunga sequenza, per fornire una chiave di lunghezza sufficiente.

QKD passo 2: le basi casuali di Bob​

Anche Bob fa una scelta casuale di basi. Tuttavia, mentre Alice usava la scelta della base per preparare il suo stato, Bob effettuerà delle misurazioni in queste basi. Se Bob effettua una misurazione nella stessa base in cui Alice ha preparato lo stato, possiamo prevedere il risultato della misurazione di Bob. Quando Bob sceglie una base diversa da quella usata da Alice nella preparazione, non possiamo conoscere il risultato della misurazione di Bob.

Bit di Alice010011010...
Basi di AliceXXZZZXZZX...
Stati di Alice∣+⟩\vert +\rangle∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣0⟩\vert 0\rangle∣1⟩\vert 1\rangle∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣1⟩\vert 1\rangle∣+⟩\vert +\rangle...
Basi di BobXZXZXXZXX...
Stati di Bob (a priori)∣+⟩\vert +\rangle??∣0⟩\vert 0\rangle?∣−⟩\vert -\rangle∣0⟩\vert 0\rangle?∣+⟩\vert +\rangle...
Stati di Bob (misurati)∣+⟩\vert +\rangle∣0⟩\vert 0\rangle∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣+⟩\vert +\rangle∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣−⟩\vert -\rangle∣+⟩\vert +\rangle...
Nella tabella seguente, considera la prima colonna. Alice ha preparato lo stato ∣+⟩,\vert +\rangle, che è un autostato di X. Poiché anche Bob ha scelto casualmente di misurare nella base X, c'è un solo possibile risultato per lo stato misurato da Bob: ∣+⟩.\vert +\rangle. Nella seconda colonna, tuttavia, hanno scelto basi diverse. Lo stato che Alice ha inviato è ∣−⟩=12(∣0⟩−∣1⟩).\vert -\rangle = \frac{1}{\sqrt{2}}(\vert 0\rangle-\vert 1 \rangle). Questo ha il 50% di probabilità di essere misurato da Bob nello stato ∣0⟩\vert 0\rangle, e il 50% di probabilità di essere misurato in ∣1⟩.\vert 1\rangle. Quindi la riga che mostra ciò che sappiamo, a priori, sulle misurazioni di Bob non può essere compilata per la colonna 2. Ma Bob effettuerà una misurazione e otterrà un autostato di (in quella colonna) Z. Nella riga in basso, riportiamo ciò che queste misurazioni hanno effettivamente prodotto.

QKD passo 3: discussione pubblica delle basi​

Alice e Bob possono ora comunicarsi reciprocamente quale base hanno scelto in ogni caso. Per tutte le colonne in cui hanno scelto casualmente la stessa base, ognuno sa con certezza quale stato aveva l'altro. Bob può convertire lo stato e la base in uno 0 o 1 secondo la convenzione condivisa da entrambe le parti. Possiamo riscrivere la tabella sopra per mostrare solo i casi in cui le basi di Alice e Bob coincidono:

Bit di Alice00100...
Basi di AliceXZXZX...
Stati di Alice∣+⟩\vert +\rangle∣0⟩\vert 0\rangle∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣+⟩\vert +\rangle...
Basi di BobXZXZXX
Stati di Bob (a priori)∣+⟩\vert +\rangle∣0⟩\vert 0\rangle∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣+⟩\vert +\rangle...
Stati di Bob (misurati)∣+⟩\vert +\rangle∣0⟩\vert 0\rangle∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣+⟩\vert +\rangle...
Bit di Bob00100...

Alice ha trasmesso con successo la stringa di bit 00100... a Bob. Se gli amici avevano concordato in anticipo di usare stringhe di 5 bit come numeri nel loro one-time pad, questi primi cinque bit darebbero loro il numero 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.

QKD passo 4: verifica e invio del segreto​

Prima che Alice e Bob procedano oltre, dovrebbero scegliere un sottoinsieme dei loro bit classici da confrontare. Poiché hanno mantenuto solo le misurazioni dei qubit che sono stati preparati e misurati usando la stessa base, tutti i valori misurati dovrebbero concordare. Se una percentuale molto piccola non concordasse, questo potrebbe essere attribuibile al rumore quantistico o agli errori. Ma se molti non concordano, qualcosa è andato storto!

Qui non affronteremo quale frazione della chiave dovrebbe essere usata per la verifica. Per ora, assumeremo che questo controllo vada bene; ritorneremo su questo nella sezione seguente sull'intercettazione.

Gli amici invierebbero poi un messaggio cifrato tra loro usando canali classici. Userebbero quindi i numeri nel loro one-time pad per cifrare/decifrare messaggi segreti, senza mai trasmettere il one-time pad da un luogo all'altro. Per la prossima sezione sull'intercettazione, tieni presente che tutta questa condivisione della chiave avviene prima della rivelazione del segreto cifrato tramite canali classici.

Alice e Bob hanno comunicato la loro scelta di base tramite canali classici, quindi non potrebbe essere intercettata? Sì! Ma conoscere la base che hanno usato per la misurazione non ti dice quale bit hanno inviato o ottenuto. Questo è possibile solo se conosci anche i bit iniziali di Alice. Ma in quel caso saresti nel computer di Alice, dove i segreti sono memorizzati, e la comunicazione segreta dei segreti diventerebbe superflua. Quindi l'intercettazione della comunicazione classica non rompe la cifratura. Ma che dire dell'intercettazione delle informazioni nel canale quantistico?

Resistenza della QKD all'intercettazione​

Alice e Bob hanno un'amica di nome Eve, nota per le sue intercettazioni. Eve vuole intercettare la chiave quantistica di Alice e Bob, in modo da poterla usare per decifrare i messaggi inviati tra i due. Questo dovrebbe necessariamente accadere tra la preparazione degli stati da parte di Alice e la misurazione degli stati da parte di Bob, poiché la misurazione collassa lo stato quantistico. In particolare, ciò significa che l'intercettazione dovrebbe avvenire prima che ci sia stata qualsiasi condivisione o confronto delle basi.

Eve deve indovinare quale base è stata usata per codificare ogni bit. Ancora, se non riesce ad accedere al computer di Alice, non ha nulla su cui basare questo indovinello, e sarà casuale. Supponiamo che il punto di partenza di Alice sia lo stesso di prima, e supponiamo ulteriormente che la scelta casuale della base di misurazione di Bob sia la stessa di prima. Vediamo cosa ottiene Eve se effettua misurazioni del canale quantistico. Come prima, se Eve sceglie casualmente la stessa base di Alice, sappiamo cosa otterrà. In caso contrario, potrebbe ottenere uno dei due risultati, ciascuno con una probabilità del 50%.

Bit di Alice010011010...
Basi di AliceXXZZZXZZX...
Stati di Alice∣+⟩\vert +\rangle∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣0⟩\vert 0\rangle∣1⟩\vert 1\rangle∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣1⟩\vert 1\rangle∣+⟩\vert +\rangle...
Basi indovinate da EveZXXZXZZXX...
Stati di Eve (a priori)?∣−⟩\vert -\rangle?∣0⟩\vert 0\rangle??∣0⟩\vert 0\rangle?∣+⟩\vert +\rangle...
Stati di Eve (misurati)∣1⟩\vert 1\rangle∣−⟩\vert -\rangle∣+⟩\vert +\rangle∣0⟩\vert 0\rangle∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣0⟩\vert 0\rangle∣−⟩\vert -\rangle∣+⟩\vert +\rangle...
Basi di BobXZXZXXZXX...

Ora, poiché Eve non sa se ha abbinato o meno la base di Alice, non sa cosa trasmettere a Bob per corrispondere agli stati originali di Alice. Quando Eve misura, per esempio, ∣0⟩,|0\rangle, tutto ciò che sa con certezza è che Alice non ha preparato lo stato ∣1⟩|1\rangle per quel qubit. Ma Alice avrebbe potuto preparare ∣0⟩,|0\rangle, ∣+⟩,|+\rangle, o ∣−⟩.|-\rangle. Tutti potrebbero essere coerenti con la misurazione di Eve. Quindi Eve deve fare una scelta. Potrebbe trasmettere esattamente lo stato che ha misurato, oppure potrebbe cercare di indovinare i casi in cui la sua misurazione non era l'autostato inviato da Alice. Includeremo una combinazione nella nostra tabella:

Bit di Alice010011010...
Basi di AliceXXZZZXZZX...
Stati di Alice∣+⟩\vert +\rangle∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣0⟩\vert 0\rangle∣1⟩\vert 1\rangle∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣1⟩\vert 1\rangle∣+⟩\vert +\rangle...
Basi indovinate da EveZXXZXZZXX...
Stati di Eve (a priori)?∣−⟩\vert -\rangle?∣0⟩\vert 0\rangle??∣0⟩\vert 0\rangle?∣+⟩\vert +\rangle...
Stati di Eve (misurati)∣1⟩\vert 1\rangle∣−⟩\vert -\rangle∣+⟩\vert +\rangle∣0⟩\vert 0\rangle∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣0⟩\vert 0\rangle∣−⟩\vert -\rangle∣+⟩\vert +\rangle...
Stati di Eve (trasmessi)∣1⟩\vert 1\rangle∣0⟩\vert 0\rangle∣1⟩\vert 1\rangle∣0⟩\vert 0\rangle∣−⟩\vert -\rangle∣+⟩\vert +\rangle∣0⟩\vert 0\rangle∣−⟩\vert -\rangle∣0⟩\vert 0\rangle...
Basi di BobXZXZXXZXX...
Stati di Bob (a priori)?∣0⟩\vert 0\rangle?∣0⟩\vert 0\rangle∣−⟩\vert -\rangle∣+⟩\vert +\rangle∣0⟩\vert 0\rangle∣−⟩\vert -\rangle∣+⟩\vert +\rangle...
Stati di Bob (misurati)∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣+⟩\vert +\rangle∣0⟩\vert 0\rangle∣−⟩\vert -\rangle∣+⟩\vert +\rangle∣0⟩\vert 0\rangle∣−⟩\vert -\rangle∣+⟩\vert +\rangle...
Bit di Bob100010010...

A questo punto, è ragionevole chiedersi: "Perché Eve non fa semplicemente una copia dello stato quantistico di Alice, ne tiene una per misurarla e trasmette l'altra a Bob?" La risposta è il teorema del "no-cloning". In modo informale, afferma che non esiste alcuna operazione unitaria (quantomeccanica) che possa fare una seconda copia di un arbitrario stato quantistico, preservando al contempo la prima copia. La dimostrazione è relativamente semplice, ed è lasciata come esercizio guidato. Ma per ora, comprendi che Eve che fa copie dello stato quantistico è vietato dalle leggi fondamentali della natura, e questo è un punto di forza fondamentale della QKD. Come prima, Alice e Bob si chiamerebbero e confronterebbero le basi. Ridurrebbero questa tabella ai casi in cui i due amici hanno selezionato le stesse basi:

Bit di Alice00100...
Basi di AliceXZXZX...
Stati di Alice∣+⟩\vert +\rangle∣0⟩\vert 0\rangle∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣+⟩\vert +\rangle...
Basi indovinate da EveZZZZX...
Stati di Eve (a priori)?∣0⟩\vert 0\rangle?∣0⟩\vert 0\rangle∣+⟩\vert +\rangle...
Stati di Eve (misurati)∣1⟩\vert 1\rangle∣0⟩\vert 0\rangle∣0⟩\vert 0\rangle∣0⟩\vert 0\rangle∣+⟩\vert +\rangle...
Stati di Eve (trasmessi)∣1⟩\vert 1\rangle∣0⟩\vert 0\rangle∣+⟩\vert +\rangle∣0⟩\vert 0\rangle∣0⟩\vert 0\rangle...
Basi di BobXZXZX...
Stati di Bob (a priori)?∣0⟩\vert 0\rangle∣+⟩\vert +\rangle∣0⟩\vert 0\rangle∣+⟩\vert +\rangle...
Stati di Bob (misurati)∣−⟩\vert -\rangle∣0⟩\vert 0\rangle∣+⟩\vert +\rangle∣0⟩\vert 0\rangle∣+⟩\vert +\rangle...
Bit di Bob10000...

Alice e Bob hanno nuovamente comunicato una stringa di bit... ma le stringhe non corrispondono. I bit più a sinistra e quello centrale sono invertiti. Guardando la tabella precedente, puoi tracciare questa discrepanza all'interferenza di Eve. Fondamentalmente, nota che possiamo fare statistica sulla corrispondenza tra le nostre stringhe di bit ora, mentre stiamo configurando la chiave, molto prima di condividere il nostro segreto cifrato. Alice e Bob possono usare quanti bit del loro one-time pad desiderano per verificare la sicurezza del loro canale. Se un singolo bit, o una percentuale molto piccola di bit non corrispondesse, questo potrebbe essere attribuibile al rumore o agli errori. Ma una frazione sostanziale di discrepanze indica intercettazione. Il significato di "sostanziale" qui dipende un po' dal rumore nella configurazione utilizzata; il significato per i computer quantistici IBM® è discusso di seguito quando implementiamo questo protocollo. Se vengono rilevati errori eccessivi, Alice e Bob non condividono il segreto, e possono iniziare a cercare l'intercettatore.

Avvertenze​

Dimostrare la sicurezza è estremamente difficile. In effetti, il protocollo qui descritto in modo approssimativo fu proposto nel 1984, e non fu dimostrato sicuro fino a 16 anni dopo Shor & Preskill, 2000. Ci sono molte sottigliezze che vanno oltre lo scopo di questa introduzione. Ma elenchiamo brevemente alcune per dimostrare che l'argomento è più complesso di quanto illustrato qui.

  • Canali sicuri: Quando Alice invia i suoi qubit attraverso una certa configurazione quantistica (un canale), e in particolare quando riceve risposte classiche da qualcuno, abbiamo assunto che quel qualcuno sia effettivamente Bob. Se Eve si infiltrasse in questa configurazione in modo tale che tutta la comunicazione di Alice avvenisse effettivamente con Eve, e tutta la comunicazione di Bob avvenisse effettivamente con Eve, allora Eve ha di fatto ottenuto una chiave e può apprendere i segreti. Bisogna prima garantire "canali sicuri", un processo con un diverso insieme di protocolli che non abbiamo affrontato qui.
  • Assunzioni su Eve: Per dimostrare veramente la sicurezza, non possiamo fare assunzioni sul comportamento di Eve; potrebbe sempre vanificare le nostre aspettative. Qui, per fornire esempi concreti, stiamo facendo assunzioni. Per esempio, potremmo assumere che gli stati che Eve trasmette a Bob siano sempre esattamente quelli che ha ottenuto dalla misurazione. O potremmo assumere che scelga casualmente uno stato sperimentalmente coerente con la sua misurazione. Più fondamentalmente, il linguaggio qui assume che Eve effettui effettivamente una misurazione, al contrario di memorizzare lo stato su un altro sistema quantistico e trasmettere un qubit casuale a Bob. Queste assunzioni vanno bene per comprendere il protocollo, ma significano che non stiamo dimostrando nulla nella piena generalità.
  • Amplificazione della privacy: Alice e Bob non sono tenuti a usare la chiave quantistica esattamente come trasmessa. Possono, per esempio, applicare una funzione hash alla chiave condivisa. Questo sfrutterebbe il fatto che l'intercettatore ha una conoscenza incompleta della chiave per produrre una chiave condivisa più corta, ma sicura.

Esperimento 1: QKD senza intercettatore​

Implementiamo il protocollo descritto sopra in assenza di un intercettatore. Lo faremo prima con un simulatore, semplicemente per comprendere il flusso di lavoro.

Prima, una nota sui simulatori quantistici: la maggior parte dei problemi quantistici che coinvolgono più di ~30 qubit non può essere simulata dalla maggior parte dei computer. Nessun computer classico, supercomputer o GPU riesce a simulare l'intera gamma di comportamenti di un computer quantistico a 127 qubit. Di solito, la motivazione per usare computer quantistici reali è che i molti qubit entangled non possono essere simulati. In questo caso non vi è entanglement di qubit, a meno che non si utilizzi lo schema di teletrasporto per spostare informazioni. Qui la motivazione per usare computer quantistici reali è diversa: è il teorema di no-cloning. Un computer classico che simula un qubit potrebbe inviare informazioni su uno stato quantistico da Alice a Bob, ma se queste informazioni classiche venissero intercettate, potrebbero essere facilmente duplicate, ed Eve potrebbe conservare una copia perfetta inviandone un'altra a Bob. Questo non è possibile con stati quantistici reali.

IBM Quantum raccomanda di affrontare i problemi di quantum computing usando un framework che chiamiamo "Qiskit patterns". Esso consiste nei seguenti passi.

  • Passo 1: Mappa il tuo problema su un circuito quantistico
  • Passo 2: Ottimizza il tuo circuito per l'esecuzione su hardware quantistico reale
  • Passo 3: Esegui il tuo job su computer quantistici IBM usando le primitive Runtime
  • Passo 4: Post-elabora i risultati

Qiskit patterns passo 1: Mappa il problema su un circuito quantistico​

In questo caso, la mappatura del nostro problema sui circuiti quantistici si riduce semplicemente alla preparazione degli stati di Alice e all'inclusione delle misurazioni di Bob. Partiamo dalla selezione casuale dei bit e delle basi.

# 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)

Visualizziamo i bit, le basi e il circuito. Nota che a volte le basi coincidono e a volte no.

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.]

Output of the previous code cell

Qiskit patterns passo 2: Ottimizza il problema per l'esecuzione quantistica​

Questo passo prende le operazioni che vogliamo eseguire e le esprime in termini delle funzionalità di uno specifico computer quantistico. Mappa anche il nostro problema sul layout del computer quantistico.

Inizieremo caricando diversi pacchetti necessari per comunicare con i computer quantistici IBM. Dobbiamo anche selezionare un backend su cui eseguire. Possiamo scegliere il backend meno occupato, oppure selezionare un backend specifico di cui conosciamo le proprietà. Anche se utilizzeremo momentaneamente un simulatore, è importante usare un modello di rumore ragionevole nella simulazione, ed è buona pratica mantenere il flusso di lavoro il più vicino possibile a quello che useremo in seguito per i computer quantistici reali.

Di seguito c'è del codice per salvare le tue credenziali al primo utilizzo. Assicurati di eliminare queste informazioni dal notebook dopo averle salvate nel tuo ambiente, in modo che le credenziali non vengano accidentalmente condivise quando condividi il notebook. Consulta Configura il tuo account IBM Cloud e Inizializza il servizio in un ambiente non fidato per ulteriori indicazioni.

# 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

Di seguito selezioniamo un simulatore e un modello di rumore.

# 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 passo 3: Esegui​

Usa il sampler per eseguire il tuo job, passando il circuito come argomento.

# 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 passo 4: Post-elaborazione​

Qui interpretiamo i nostri risultati ed estraiamo informazioni utili. Potremmo provare a visualizzare l'output del nostro sampler, ma lo abbiamo usato in modo non convenzionale. Invece di effettuare molte misurazioni del circuito per sviluppare statistiche sugli stati, abbiamo effettuato una sola misurazione (quella di Bob). Qualsiasi qubit il cui stato è stato preparato e misurato nella stessa base dovrebbe avere un esito deterministico, tale che è necessaria una sola misurazione. I qubit con stati preparati e misurati in basi diverse (che avrebbero esiti probabilistici e richiederebbero molte misurazioni per essere interpretati) non verranno usati per costruire il nostro one-time pad/chiave. Estraiamo un elenco di esiti di misurazione da questa stringa di bit. Attenzione a invertire l'ordine se confrontate con l'array di bit di Alice usato per generare il circuito.

# 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]

Confrontiamo le basi di misurazione scelte casualmente da Alice e Bob. Questo era il passo 3 nel nostro protocollo QKD (discussione pubblica delle basi). Ogni volta che hanno scelto la stessa base per un qubit, aggiungiamo i bit associati a quel qubit a un elenco di bit per generare numeri in un one-time pad. Quando le basi non coincidono, i risultati vengono scartati. Verifichiamo anche se i due elenchi di bit concordano, oppure se ci sono state perdite dovute al rumore o ad altri fattori.

# 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 e Bob hanno ciascuno un elenco di bit, e coincidono con fedeltà del 100%. Possono usarli per generare numeri in un one-time pad. Possono poi utilizzarlo nel passo 4 del QKD: invio e decifrazione di un segreto. L'array di bit attuale è troppo corto per decifrare molto di qualsiasi cosa. Torneremo su questo dopo aver incluso l'intercettazione.

Verifica la tua comprensione​

Leggi la domanda qui sotto, rifletti sulla tua risposta, poi clicca sul triangolo per rivelare la soluzione.

Supponi di aver bisogno di cifre abbastanza grandi da permettere di spostare le lettere dell'alfabeto inglese per tutta la sua lunghezza, o più, sebbene esistano certamente altri schemi di codifica. (a) Quanto potrebbe essere lungo in lettere un messaggio da decifrare usando i bit nella chiave sopra? (b) La tua risposta deve coincidere con quella dei tuoi compagni? Perché sì o perché no?

Risposta:

(a) La risposta dipende da quante basi scelte casualmente da Alice e Bob coincidono. Poiché c'è circa una probabilità del 50-50 che le basi coincidano per qualsiasi qubit dato, ci aspettiamo che circa 10 dei nostri bit siano utili. 9 o 11 sono perfettamente comuni. Anche 4 o 15 non sono fuori dal campo delle possibilità. Sono necessari 5 bit per effettuare uno spostamento maggiore o uguale alla lunghezza dell'alfabeto inglese, il che significa che puoi applicare lo spostamento a una lettera per ogni 5 bit che hai. Se hai almeno 5 bit condivisi tra Alice e Bob, puoi codificare una singola lettera. Se ne hai almeno 10, puoi codificarne 2, e così via. (b) Non deve necessariamente coincidere, per le ragioni esposte in (a).

Esperimento 2: QKD con un intercettatore​

Implementeremo esattamente lo stesso protocollo di prima. Questa volta, inseriremo un altro insieme di misurazioni, da parte di Eve, tra Alice e Bob.

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()

Il passo 4 di Qiskit patterns (post-elaborazione) è semplice in questo caso. Non c'è bisogno di visualizzare la distribuzione delle misurazioni, poiché abbiamo effettuato una sola misurazione. Eve ha i seguenti bit:

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]

Ora Eve deve ricostruire gli stati da trasmettere a Bob. Come descritto nell'introduzione, non ha modo di sapere se ha indovinato correttamente le basi di codifica, quindi non è in grado di preparare esattamente gli stessi stati che erano stati inviati. Potrebbe supporre che ogni scelta di base fosse corretta e codificare esattamente ciò che ha misurato, oppure potrebbe supporre di aver scelto la base sbagliata e scegliere uno degli autostati della base opposta. Qui, per semplicità, assumiamo la prima opzione. Lo realizziamo costruendo un circuito quantistico completamente nuovo, ripetendo i passi di Qiskit patterns come prima.

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]

Confrontiamo ora i bit di Alice e Bob:

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

In precedenza, c'era una corrispondenza perfetta tra i bit nelle chiavi di Alice e Bob. Ora, a causa dell'interferenza di Eve, vediamo che i bit di Alice e Bob differiscono nel 14% dei casi che dovrebbero coincidere per via della scelta delle stesse basi da parte di Alice e Bob. Questo dovrebbe essere facile da rilevare per Alice e Bob. Tuttavia, affidarsi a una percentuale di errori come questa significa che esiste un limite alla quantità di rumore che possiamo tollerare nel canale quantistico.

Esperimento 3: Confronto tra QKD con e senza intercettazione su un vero computer quantistico​

Eseguiamo questo esperimento su un vero computer quantistico, così da sfruttare il teorema di non-clonazione. Allo stesso tempo, i computer quantistici reali sono soggetti a rumore e hanno tassi di errore più elevati rispetto ai computer classici. Confrontiamo quindi la perdita di fedeltà dei bit della chiave con e senza intercettazione, per assicurarci che la differenza sia rilevabile su un computer quantistico reale. Iniziamo in assenza di intercettazione:

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

Senza intercettazione, abbiamo ottenuto una fedeltà del 100% su questo insieme di 127 bit di prova, ottenendo 55 basi coincidenti e altrettanti bit della chiave utilizzabili. Ripetiamo ora l'esperimento con Eve in ascolto:

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

In questo caso abbiamo riscontrato una perdita di fedeltà di quasi il 23% nei bit condivisi a causa dell'intercettazione! Questo è molto facilmente rilevabile. Occorre notare che il trasferimento di informazioni quantistiche su lunghe distanze potrebbe comunque introdurre rumore ed errori aggiuntivi. Garantire che l'intercettazione sia rilevabile anche in presenza di rumore e anche quando Eve utilizza tutti i metodi a sua disposizione è un campo complesso che va al di là di questa introduzione.

Domande​

Gli insegnanti possono richiedere versioni di questi notebook con le chiavi delle risposte e indicazioni sul loro inserimento nei curricoli più comuni compilando questo breve sondaggio sull'utilizzo dei notebook.

Concetti fondamentali​

  • Le informazioni quantistiche non possono essere copiate o "clonate".
  • È possibile ripetere lo stesso processo di preparazione per creare un insieme di stati quantistici tutti uguali, o quasi uguali.
  • Una chiave di cifratura/decifratura (un one-time pad) può essere condivisa tra due amici usando stati quantistici.
  • La scelta casuale di una base di misura da parte dei due amici fa sì che, metà delle volte, sceglieranno basi diverse e dovranno scartare le informazioni su quei qubit.
  • La scelta casuale della base di misura garantisce anche che un intercettatore non possa conoscere lo stato iniziale preparato e quindi non possa ricreare lo stato inviato. Questo assicura che l'intercettazione verrà rilevata.

Domande V/F​

  1. V/F Nella distribuzione quantistica delle chiavi, i due partner comunicanti misurano ogni qubit nella stessa base.
  2. V/F Un intercettatore che rileva informazioni quantistiche nel QKD è impedito dalle leggi della natura dal copiare lo stato quantistico che intercetta.
  3. V/F Un one-time pad è una chiave per cifrare/decifrare messaggi sicuri in cui un particolare schema di codifica viene utilizzato una sola volta, per un singolo pezzo di informazione (come una singola lettera dell'alfabeto).

Domande a scelta multipla​

  1. Seleziona l'opzione che completa meglio la frase. Come descritto in questo modulo, un one-time pad è un insieme di chiavi di cifratura/decifratura che viene utilizzato...
  • a. Solo una volta per un singolo pezzo di informazione, come una singola lettera.
  • b. Solo una volta per un singolo messaggio.
  • c. Solo una volta per un determinato periodo di tempo, come un giorno.
  • d. Fino a quando non vi è evidenza di intercettazione.
  1. Supponi che Alice e Bob scelgano le loro basi di misura in modo casuale. Misurano. Poi condividono le loro basi di misura e conservano solo i bit di informazione nei casi in cui hanno usato la stessa base. A meno di fluttuazioni casuali, circa quale percentuale dei loro qubit dovrebbe produrre bit di informazione utilizzabili?
  • a. 100%
  • b. 50%
  • c. 25%
  • d. 12,5%
  • e. 0%
  1. Dopo che Alice e Bob hanno selezionato i casi in cui hanno utilizzato le stesse basi di misura, quale percentuale di quei bit di informazione dovrebbe coincidere, se il rumore e gli errori quantistici fossero trascurabili?
  • a. 100%
  • b. 50%
  • c. 25%
  • d. 12,5%
  • e. 0%
  1. Supponi che Alice abbia scelto le sue basi di misura in modo casuale. Eve sceglie anch'essa le sue basi in modo casuale e ascolta (misura). Invia a Bob degli stati coerenti con le sue misurazioni. Alice e Bob confrontano le scelte delle basi e conservano solo i qubit misurati/preparati da entrambi nelle stesse basi. A meno di fluttuazioni casuali, circa quale percentuale di quelle misurazioni di qubit conservate coinciderà, secondo Alice e Bob?
  • a. 100%
  • b. 75%
  • c. 50%
  • d. 25%
  • e. 12,5%
  • f. 0%

Domande di discussione​

  1. Supponi che tutte le scelte delle basi siano casuali per tutti i partecipanti: Alice, Bob ed Eve. Supponi che dopo che Eve ha ascoltato, invii a Bob uno stato preparato nella stessa base in cui ha misurato, coerente con quella misurazione. Convince i tuoi compagni che il 12,5% di tutti i qubit inizializzati da Alice produrrà discrepanze di misura tra Alice e Bob, indicando la presenza di un intercettatore (ignorando errori e rumore quantistici). Suggerimento 1: Poiché non esiste una base privilegiata, se consideri solo una scelta iniziale per Alice, il rapporto per quella scelta dovrebbe essere lo stesso del rapporto per la somma di tutte le scelte. Suggerimento 2: Potrebbe non essere sufficiente contare il numero di modi in cui qualcosa può accadere, poiché alcuni risultati possono verificarsi con probabilità diverse.