דלג לתוכן הראשי

הפצת מפתח קוונטי

למודול Qiskit in Classrooms זה, על התלמידים לקבוע סביבת Python תקינה עם החבילות הבאות:

  • qiskit v2.1.0 או חדש יותר
  • qiskit-ibm-runtime v0.40.1 או חדש יותר
  • qiskit-aer v0.17.0 או חדש יותר
  • qiskit.visualization
  • numpy
  • pylatexenc

להגדרה והתקנת החבילות הנ"ל, ראו את המדריך התקנת Qiskit. כדי להריץ עבודות על מחשבים קוונטיים אמיתיים, התלמידים יצטרכו להגדיר חשבון ב-IBM Quantum® לפי השלבים במדריך הגדרת חשבון IBM Cloud שלך.

מודול זה נבדק והשתמש ב-5 שניות של זמן QPU. זהו אומדן בלבד. השימוש בפועל עשוי להשתנות.

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

צפו בסיור המודול של ד"ר קייטי מקורמיק למטה, או לחצו כאן לצפייה ב-YouTube.


מבוא ומוטיבציה

יש אינסוף דרכים להצפין ולפענח מידע, ומילולית אלפי דרכים נחקרו היטב. כאן, נגביל את עצמנו לשיטת הצפנה מוקדמת ופשוטה מאוד, הנקראת "החלפה פשוטה", כדי להתמקד בחלק הקוונטי של הפרוטוקול. החלק הקוונטי ניתן להתאמה לפרוטוקולים רבים אחרים עם שינויים מועטים יחסית.

החלפה פשוטה

הצפנת החלפה פשוטה היא כזו שבה אות או מספר מוחלפים באחרים, כך שיש מיפוי 1:1 מהאותיות והמספרים בהודעה לאותיות והמספרים המשמשים ברצף מוצפן. דוגמה מתרבות הפופ לאלה היא חידת ה-cryptoquote או cryptogram, שבה ציטוט או ביטוי מוצפן באמצעות החלפה פשוטה, והמשתתף מוזמן לפענחו. אלה קלים לפתרון אם הם מספיק ארוכים. שקלו את הדוגמה:

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

אנשים הפותרים אלה ביד בדרך כלל משתמשים בטריקים הקשורים להיכרות עם מבנה השפה של ההודעה המקורית. לדוגמה, באנגלית, המילות בנות אות אחת כמו ה-"R" המוצפן הן רק "a" ו-"I". האותיות הכפולות המוצפנות ב-"KIVGGB" למשל יכולות לקחת ערכים מסוימים בלבד. יש דברים עדינים יותר שנותנים רמזים כמו שהמילה הנפוצה ביותר המתאימה לתבנית "GSZG" היא "that". לאנשים שמשתמשים בקוד לפתרון יש הרבה יותר אפשרויות, כולל סריקה פשוטה של אפשרויות עד שמתקבלת מילה באנגלית, ועדכון תוך שמירה על אותה מילה. שיטה פשוטה אך רבת עוצמה אחת היא שימוש בתדירות אותיות, במיוחד כאשר ההודעה ארוכה מספיק כדי להוות מדגם מייצג של האנגלית.

שאלת בדיקה

נסו את ידכם בפענוח זה אם תרצו, אם כי אין צורך בכך לשאר המודול. לחצו על החץ למטה כדי לראות את ההודעה.

תשובה:

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

הדוגמה לעיל קשורה ל"מפתח", מיפוי מהאותיות המוצפנות לאותיות המפוענחות. במקרה זה, המפתח הוא:

  • A (לא בשימוש, נקרא לו Z)
  • B->Y
  • C (לא בשימוש, נקרא לו X)
  • D->W
  • E->V
  • F->U
  • ...

וכן הלאה. בלשון המעטה, זה אינו מפתח טוב. מפתחות שבהם האותיות המוצפנות והמפוענחות הן פשוט גרסאות מוזזות של האלפבית (כמו A->B ו-B->C) נקראים צפנים "Caesar shift".

שימו לב שאלה מאוד קשים אם הם קצרים. למעשה, אם הם קצרים מאוד, הם בלתי קבועים. שקלו:

URYYP

יש הרבה פענוחים אפשריים, באמצעות מפתחות שונים: HELLO, PETTY, HAPPY, JIGGY, STOOL. האם אתם יכולים לחשוב על אחרים?

אך אם אתם שולחים הרבה הודעות כאלה, בסופו של דבר ההצפנה תפוצח. לכן, לא כדאי להשתמש באותו "מפתח" לעתים קרובות מדי. למעשה, הכי טוב הוא אם אתם משתמשים בהחלפה מסוימת רק פעם אחת. לא רק בהודעה אחת, אלא רק לתו אחד בודד! בכך אנו מתכוונים שיהיה לכם סכמת הצפנה או מפתח לכל תו בשימוש בהודעה, לפי הסדר. אם אתם רוצים לשלוח הודעה לחבר באמצעות הודעה זו, אתם וחברכם תצטרכו פנקס נייר (בימים הישנים) שעליו כתוב המפתח המשתנה תמיד. אתם תשתמשו בזה רק פעם אחת. זה נקרא "פנקס חד-פעמי".

הפנקס החד-פעמי

בואו נראה כיצד זה עובד עם דוגמה. אפשר לעשות זאת כולו עם אותיות, אך מקובל להמיר מאותיות למספרים, נניח, על ידי הקצאת A=0, B=1, C=2…. נניח שאנחנו חברים המעורבים בפעילויות חשאיות ושיתפנו פנקס. באופן אידיאלי, היינו משתפים פנקסים רבים, אך זה של היום הוא:

EDGRPOJNCUWQZVMK…

או, המרה למספרים לפי מיקום באלפבית:

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

נניח שאני רוצה לשתף איתך את ההודעה:

"I love quantum!"

או, בצורה שקולה:

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

אנחנו לא רוצים לשלוח את הקוד הנ"ל; זה החלפה פשוטה, שאינה מאובטחת כלל. אנחנו רוצים לשלב זאת עם המפתח שלנו בצורה כלשהי. דרך נפוצה היא חיבור מודולו 26. אנחנו מוסיפים את ערך ההודעה לערך המפתח, מודולו 26, עד שמגיעים לסוף ההודעה. לכן, נשלח

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

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

שימו לב שאם מישהו מיירט זאת ואין לו את המפתח, פענוח זה הוא חסר תקווה לחלוטין! אפילו שני ה-"u"ים ב-"quantum" לא מקודדים באותו מספר! הראשון הוא 3, והשני הוא 16… באותה מילה!

לכן, אני שולח זאת אליך, ויש לך את אותו המפתח שיש לי. אתה מבטל את החיבור מודולו 26 שאתה יודע שביצעתי:

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

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

כך שההודעה x1, x2, x3, x4… חייבת להיות

8, 11, 14, 21…

לבסוף, המרה לטקסט, יש לנו

"I love quantum".

זהו פנקס חד-פעמי.

שימו לב שאם המפתח קצר מההודעה, אנחנו מתחילים לחזור על הקידוד שלנו. זה עדיין יהיה בעיית פענוח קשה לפתרון, אך לא בלתי אפשרי אם הוא חוזר מספיק פעמים. לכן, אתם צריכים מפתח ארוך (או "פנקס").

הערה

בהקשרים רבים, התלמידים כבר יהיו מכירים עם הצפנה זו, כך שניתן לדלג על פעילות זו. אך מדובר בחזרה מהירה ופשוטה יחסית.

שלב 1: מצאו שותף, ושתפו רצף של 4 אותיות לשימוש כמפתח. כל רצף של 4 אותיות המתאים לכיתה יתאים.
שלב 2: בחרו מילת סוד בת 4 אותיות שאתם רוצים לשלוח לשותפכם (שני השותפים עושים זאת כך ששולחים זה לזה מילות סוד שונות)
שלב 3: המירו את המפתח/הפנקס בן 4 האותיות וכל אחת ממילות הסוד בנות 4 האותיות למספרים באמצעות A = 1, B = 2, וכן הלאה.
שלב 4: שלבו את המילה בת 4 האותיות שלכם עם הפנקס החד-פעמי באמצעות חיבור מודולו 26.
שלב 5: מסרו לשותפכם את רצף המספרים המקודד את מילת הסוד שלכם, ושותפכם ימסור לכם את שלו.
שלב 6: פענחו את המילות זה של זה באמצעות חיסור מודולו 26.
שלב 7: אמתו. האם זה עבד?

המשך

החליפו מילים מוצפנות עם קבוצה אחרת, שאין לה גישה לפנקס החד-פעמי שלכם. האם אתם יכולים לפענח אותו? הסבירו מדוע כן או לא?

בתקווה שהפעילות לעיל מבהירה שפנקס חד-פעמי הוא צורת הצפנה בלתי ניתנת לשבירה, בהינתן כמה הנחות, כמו:

  • המפתח הוא באותו אורך כמו ההודעה הנשלחת, או ארוך יותר
  • המפתח הוא אקראי באמת
  • המפתח משמש רק פעם אחת ואז נמחק

לכן זה נהדר. יש לנו הצפנה בלתי ניתנת לשבירה... אלא אם כן מישהו משיג את המפתח שלנו. אם מישהו משיג את המפתח שלנו, הכל מפוענח. ההבדל הזה בין הצפנה בלתי ניתנת לשבירה לבין חשיפת כל הסודות שלנו הופך את שיתוף מפתח מאובטח לחשוב ביותר. מטרת הפצת המפתח הקוונטי היא למנף את האילוצים שהטבע הטיל על מידע קוונטי כדי לאבטח מפתח משותף/פנקס חד-פעמי.

שימוש במצבים קוונטיים כמפתח

נניח שאנחנו עובדים עם Qubits (תוך הדגשה שלקיוביטים יש שני מצבי עצמי). ניתן להשתמש במערכות קוונטיות עם מספרים גבוהים יותר של מצבים קוונטיים, אך מחשבי הקוונטום החדישים ב-IBM® משתמשים בקיוביטים. אין שום בעיה לקודד את A, B, C שלנו לרצפים של 0 ו-1. לכן, מספיק לנו לשתף מפתח של 0 ו-1 ולבצע חיבור מודולו 2 על כל ביט המאחסן אות.

בדקו את ההבנה שלכם

קראו את השאלה למטה, חשבו על תשובתכם, ואז לחצו על המשולש כדי לגלות את הפתרון.

אם אנחנו באמת מתעניינים רק באותיות אנגליות, כמה ביטים אנחנו צריכים?

תשובה:

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

החברים שלנו, אליס ובוב, רוצים לשתף מפתח קוונטי כך שאף אחד אחר לא יוכל ליירט אותו (לפחות לא מבלי שידעו). הם צריכים שיהיה להם דרך לשלוח מצבים קוונטיים זה לזה. לעשות זאת בנאמנות גבוהה וללא רעש/שגיאות אינו טריוויאלי. אך יש שתי גישות שאנחנו אמורים להיות מסוגלים להבין בשלב זה:

  1. כבל סיב אופטי מאפשר לכם לשלוח אור... שהוא מאוד קוונטי-מכני. פוטונים בודדים ניתן לזהות בנאמנות גבוהה על פני קילומטרים רבים של כבל סיב אופטי. זה אינו ערוץ קוונטי מושלם וללא שגיאות, אך הוא יכול להיות טוב מאוד.
  2. נוכל להשתמש בטלפורטציה קוונטית, כפי שתוארה במודול קודם. כלומר, אליס ובוב יכולים לשתף קיוביטים שזורים ומצב יכול להישלח מאליס לבוב באמצעות פרוטוקול הטלפורטציה.

למודול זה, אנחנו לא רוצים לדרוש מכם הגדרות אופטיות בנאמנות גבוהה לשיתוף פוטונים, ולכן נשתמש בשיטה השנייה לשיתוף מצבים קוונטיים. אך אין בכך לומר שזו הכי ריאליסטית לשיתוף מפתחות קוונטיים לטווח ארוך.

כעת נחקור פרוטוקול שהוצג לראשונה על ידי צ'ארלס בנט וז'יל ברסאר ב-1984 לשיתוף מצבים הנמדדים בבסיסים שונים מאליס לבוב. נשתמש בשיטת מדידה חכמה כדי לצבור מפתח לשימוש בהצפנה מאוחרת יותר. במילים אחרות, אנחנו מפיצים מפתח קוונטי בין שני צדדים המעוניינים לתקשר, ומכאן "הפצת מפתח קוונטי" (QKD).

שלב 1 ב-QKD: הביטים האקראיים והבסיסים האקראיים של אליס

אליס תתחיל בייצור רצף אקראי של 0 ו-1. לאחר מכן היא תבחר באופן אקראי בסיס להכנת מצב קוונטי, בהתבסס על כל ביט אקראי, באמצעות הטבלה למטה (טבלה שגם לבוב יש):

בסיסbit = 0bit = 1
Z0\vert 0\rangle1\vert 1\rangle
X+\vert +\rangle\vert -\rangle

לדוגמה, נניח שאליס יצרה אקראית 0, ובחרה אקראית בבסיס X. אז היא תכין מצב קוונטי ψ=+x=12(0+1)|\psi\rangle = |+\rangle_x = \frac{1}{\sqrt{2}}(|0\rangle+|1\rangle). אפשר בהחלט למנף את האקראיות הקוונטית כדי לייצר קבוצה אקראית של 0 ו-1, ובחירת בסיס אקראית. לעת עתה, פשוט נניח שנוצרה קבוצה אקראית, כדלקמן:

ביטים של אליס010011010...
בסיסים של אליסXXZZZXZZX...
מצבים של אליס+\vert +\rangle\vert -\rangle0\vert 0\rangle0\vert 0\rangle1\vert 1\rangle\vert -\rangle0\vert 0\rangle1\vert 1\rangle+\vert +\rangle...

קבוצת הביטים האקראיים, הבסיסים והמצבים הנובעים תמשיך ברצף ארוך, כדי לספק מפתח באורך מספיק.

שלב 2 ב-QKD: הבסיסים האקראיים של בוב

גם בוב בוחר בסיסים באופן אקראי. אולם, בעוד שאליס השתמשה בבחירת הבסיס להכנת המצב שלה, בוב ייעשה מדידות בבסיסים אלה. אם בוב מבצע מדידה באותו בסיס שבו אליס הכינה את המצב, אנחנו יכולים לחזות את תוצאת מדידתו של בוב. כאשר בוב בוחר בבסיס שונה מהבסיס שבו השתמשה אליס בהכנה, אנחנו לא יכולים לדעת את תוצאת מדידתו של בוב.

ביטים של אליס010011010...
בסיסים של אליסXXZZZXZZX...
מצבים של אליס+\vert +\rangle\vert -\rangle0\vert 0\rangle0\vert 0\rangle1\vert 1\rangle\vert -\rangle0\vert 0\rangle1\vert 1\rangle+\vert +\rangle...
בסיסים של בובXZXZXXZXX...
מצבים של בוב (a priori)+\vert +\rangle??0\vert 0\rangle?\vert -\rangle0\vert 0\rangle?+\vert +\rangle...
מצבים של בוב (נמדד)+\vert +\rangle0\vert 0\rangle\vert -\rangle0\vert 0\rangle+\vert +\rangle\vert -\rangle0\vert 0\rangle\vert -\rangle+\vert +\rangle...
בטבלה למטה, שקלו את העמודה הראשונה. אליס הכינה את המצב +,\vert +\rangle, שהוא מצב עצמי של X. מאחר שגם בוב בחר אקראית למדוד בבסיס X, יש רק תוצאה אחת אפשרית למצב הנמדד של בוב: +.\vert +\rangle. בעמודה השנייה, לעומת זאת, הם בחרו בסיסים שונים. המצב שאליס שלחה הוא =12(01).\vert -\rangle = \frac{1}{\sqrt{2}}(\vert 0\rangle-\vert 1 \rangle). יש לזה סיכוי של 50% להימדד על ידי בוב במצב 0\vert 0\rangle, וסיכוי של 50% להימדד ב-1.\vert 1\rangle. לכן השורה המראה מה אנחנו יודעים, a priori, על מדידותיו של בוב לא ניתן למילוי לעמודה 2. אך בוב יבצע מדידה ויקבל מצב עצמי של (באותה עמודה) Z. בשורה התחתונה, אנחנו ממלאים את מה שהמדידות הללו קיבלו בפועל.

שלב 3 ב-QKD: דיון ציבורי על בסיסים

אליס ובוב יכולים כעת לשתף זה עם זה איזה בסיס בחרו בכל מקרה. לכל העמודות שבהן הם בחרו אקראית באותו בסיס, כל אחד יודע בוודאות מה היה המצב של השני. בוב יכול להמיר את המצב והבסיס ל-0 או 1 לפי המוסכמה המשותפת לשני הצדדים. אנחנו יכולים לכתוב מחדש את הטבלה לעיל כדי להראות רק את המקרים שבהם הבסיסים של אליס ובוב תאמו:

ביטים של אליס00100...
בסיסים של אליסXZXZX...
מצבים של אליס+\vert +\rangle0\vert 0\rangle\vert -\rangle0\vert 0\rangle+\vert +\rangle...
בסיסים של בובXZXZXX
מצבים של בוב (a priori)+\vert +\rangle0\vert 0\rangle\vert -\rangle0\vert 0\rangle+\vert +\rangle...
מצבים של בוב (נמדד)+\vert +\rangle0\vert 0\rangle\vert -\rangle0\vert 0\rangle+\vert +\rangle...
ביטים של בוב00100...

אליס העבירה בהצלחה את מחרוזת הביטים 00100... לבוב. אם החברים הסכימו מראש להשתמש במחרוזות של 5 ביטים כמספרים בפנקס החד-פעמי שלהם, חמשת הביטים הראשונים הללו יתנו להם את המספר 4=0×24+0×23+1×22+0×21+0×20.4 = 0\times2^4+0\times2^3+1\times2^2+0\times2^1+0\times2^0.

שלב 4 ב-QKD: אימות ושליחת הסוד

לפני שאליס ובוב ימשיכו, עליהם לבחור תת-קבוצה של הביטים הקלאסיים שלהם להשוואה. מאחר שהם שמרו רק מדידות של קיוביטים שהוכנו ונמדדו באמצעות אותו בסיס, כל הערכים הנמדדים אמורים להסכים. אם אחוז קטן מאוד לא הסכים, זה יכול להיות מיוחס לרעש קוונטי או שגיאות. אך אם רבים לא מסכימים, משהו השתבש!

כאן לא נתייחס לאיזה שבר מהמפתח יש להשתמש לאימות. לעת עתה, נניח שבדיקה זו עוברת היטב; נחזור לכך בסעיף להלן על האזנת סתר.

החברים ישלחו אז הודעה מוצפנת זה לזה דרך ערוצים קלאסיים. הם ישתמשו אז במספרים בפנקס החד-פעמי שלהם כדי להצפין/לפענח הודעות סודיות, מבלי אי פעם להעביר את הפנקס החד-פעמי ממיקום אחד לאחר. לסעיף הבא על האזנת סתר, זכרו שכל השיתוף הזה של המפתח מתרחש לפני חשיפת הסוד המוצפן דרך ערוצים קלאסיים.

אליס ובוב העבירו את בסיס הבחירה שלהם דרך ערוצים קלאסיים, אז לא ניתן לעשות ציתות לכך? כן! אך ידיעת הבסיס בו השתמשו למדידה אינה אומרת לך איזה ביט שלחו או קיבלו. זה אפשרי רק אם אתה גם יודע את הביטים ההתחלתיים של אליס. אך אז היית במחשב של אליס, שבו הסודות מאוחסנים, ותקשורת סודית של הסודות הופכת לחסרת משמעות. לכן יירוט התקשורת הקלאסית אינו שובר את ההצפנה. אך מה לגבי יירוט מידע בערוץ הקוונטי?

עמידות של QKD בפני האזנת סתר

לאליס ולבוב יש חברה בשם איב, שידועה לשמצה בהאזנת סתר. איב רוצה ליירט את המפתח הקוונטי של אליס ובוב, כדי שתוכל להשתמש בו לפענוח הודעות הנשלחות בין השניים. זה בהכרח יתרחש בין הכנת המצבים של אליס למדידת המצבים של בוב, מאחר שהמדידה מקרסת את המצב הקוונטי. בפרט, משמעות הדבר היא שהאזנת הסתר תצטרך להתרחש לפני שהיה שיתוף או השוואה כלשהם של בסיסים.

איב חייבת לנחש איזה בסיס שימש לקידוד כל ביט. שוב, אם היא אינה מסוגלת לגשת למחשב של אליס, אין לה שום דבר עליו לבסס ניחוש זה, והוא יהיה אקראי. נניח שהתחלת אליס זהה לקודם, ונניח עוד שבחירת בסיס המדידה האקראית של בוב זהה לקודם. בואו נמלא את מה שאיב מקבלת אם היא עושה מדידות של הערוץ הקוונטי. כמו קודם, אם איב בוחרת אקראית באותו בסיס כמו אליס, אנחנו יודעים מה היא תקבל. אם לא, היא יכולה לקבל אחת משתי תוצאות, כל אחת עם הסתברות של 50%.

ביטים של אליס010011010...
בסיסים של אליסXXZZZXZZX...
מצבים של אליס+\vert +\rangle\vert -\rangle0\vert 0\rangle0\vert 0\rangle1\vert 1\rangle\vert -\rangle0\vert 0\rangle1\vert 1\rangle+\vert +\rangle...
בסיסי ניחוש של איבZXXZXZZXX...
מצבים של איב (a priori)?\vert -\rangle?0\vert 0\rangle??0\vert 0\rangle?+\vert +\rangle...
מצבים של איב (נמדד)1\vert 1\rangle\vert -\rangle+\vert +\rangle0\vert 0\rangle\vert -\rangle0\vert 0\rangle0\vert 0\rangle\vert -\rangle+\vert +\rangle...
בסיסים של בובXZXZXXZXX...

כעת מאחר שלאיב אין מושג אם היא תאמה לבסיס של אליס או לא, היא לא יודעת מה להעביר לבוב כדי להתאים למצבים המקוריים של אליס. כאשר איב מודדת, לדוגמה, 0,|0\rangle, כל מה שהיא יודעת בוודאות הוא שאליס לא הכינה את המצב 1|1\rangle עבור אותו Qubit. אך אליס יכלה להכין 0,|0\rangle, +,|+\rangle, או .|-\rangle. כל אלה יכולים להיות עקביים עם מדידתה של איב. לכן איב חייבת לבחור. היא עשויה להעביר בדיוק את המצב שמדדה, או שתנסה לנחש מקרים שבהם מדידתה לא הייתה המצב העצמי שנשלח על ידי אליס. נכלול תערובת בטבלה שלנו:

ביטים של אליס010011010...
בסיסים של אליסXXZZZXZZX...
מצבים של אליס+\vert +\rangle\vert -\rangle0\vert 0\rangle0\vert 0\rangle1\vert 1\rangle\vert -\rangle0\vert 0\rangle1\vert 1\rangle+\vert +\rangle...
בסיסי ניחוש של איבZXXZXZZXX...
מצבים של איב (a priori)?\vert -\rangle?0\vert 0\rangle??0\vert 0\rangle?+\vert +\rangle...
מצבים של איב (נמדד)1\vert 1\rangle\vert -\rangle+\vert +\rangle0\vert 0\rangle\vert -\rangle0\vert 0\rangle0\vert 0\rangle\vert -\rangle+\vert +\rangle...
מצבים של איב (שנשלחו)1\vert 1\rangle0\vert 0\rangle1\vert 1\rangle0\vert 0\rangle\vert -\rangle+\vert +\rangle0\vert 0\rangle\vert -\rangle0\vert 0\rangle...
בסיסים של בובXZXZXXZXX...
מצבים של בוב (a priori)?0\vert 0\rangle?0\vert 0\rangle\vert -\rangle+\vert +\rangle0\vert 0\rangle\vert -\rangle+\vert +\rangle...
מצבים של בוב (נמדד)\vert -\rangle0\vert 0\rangle+\vert +\rangle0\vert 0\rangle\vert -\rangle+\vert +\rangle0\vert 0\rangle\vert -\rangle+\vert +\rangle...
ביטים של בוב100010010...

בשלב זה, סביר לשאול, "מדוע איב פשוט לא מעתיקה את המצב הקוונטי של אליס, שומרת אחד למדידה, ומעבירה את השני לבוב?" התשובה היא משפט "אי-השכפול". בצורה לא פורמלית, הוא אומר שאין פעולה יוניטרית (מכנית קוונטית) שיכולה ליצור עותק שני של מצב קוונטי שרירותי, תוך שמירה על העותק הראשון. ההוכחה פשוטה יחסית, ונשארת כתרגיל מודרך. אך לעת עתה, הבינו שעשיית עותקים של המצב הקוונטי על ידי איב אסורה על פי חוקי יסוד של הטבע, וזהו עיקרון עוצמה של QKD. כמו קודם, אליס ובוב יתקשרו זה עם זה וישוו בסיסים. הם יצמצמו את הטבלה הזאת למקרים שבהם שני החברים בחרו באותם בסיסים:

ביטים של אליס00100...
בסיסים של אליסXZXZX...
מצבים של אליס+\vert +\rangle0\vert 0\rangle\vert -\rangle0\vert 0\rangle+\vert +\rangle...
בסיסי ניחוש של איבZZZZX...
מצבים של איב (a priori)?0\vert 0\rangle?0\vert 0\rangle+\vert +\rangle...
מצבים של איב (נמדד)1\vert 1\rangle0\vert 0\rangle0\vert 0\rangle0\vert 0\rangle+\vert +\rangle...
מצבים של איב (שנשלחו)1\vert 1\rangle0\vert 0\rangle+\vert +\rangle0\vert 0\rangle0\vert 0\rangle...
בסיסים של בובXZXZX...
מצבים של בוב (a priori)?0\vert 0\rangle+\vert +\rangle0\vert 0\rangle+\vert +\rangle...
מצבים של בוב (נמדד)\vert -\rangle0\vert 0\rangle+\vert +\rangle0\vert 0\rangle+\vert +\rangle...
ביטים של בוב10000...

אליס ובוב העבירו שוב מחרוזת ביטים... אך המחרוזות אינן תואמות. הביטים הקיצוניים בשמאל והאמצעיים הפוכים. בטבלה הקודמת, אתם יכולים לעקוב אחר חוסר ההתאמה הזה לאחר ההפרעה מצד איב. חשוב לציין שאנחנו יכולים לעשות סטטיסטיקה על ההתאמה בין מחרוזות הביטים שלנו כעת, בזמן הגדרת המפתח, הרבה לפני שיתוף הסוד המוצפן שלנו. אליס ובוב חופשיים להשתמש בכמה שיותר מביטי הפנקס החד-פעמי שלהם כדי לבדוק את אבטחת הערוץ שלהם. אם ביט אחד, או אחוז קטן מאוד של ביטים לא תאמו, זה עשוי להיות מיוחס לרעש או שגיאות. אך שבר משמעותי של חוסר התאמה מצביע על האזנת סתר. המשמעות של "משמעותי" כאן תלויה קצת ברעש בהגדרה בשימוש; מה שהוא אומר עבור מחשבי קוונטום של IBM® נדון להלן כאשר אנחנו מיישמים פרוטוקול זה. אם מזוהות שגיאות עודפות, אליס ובוב אינם מגלים את הסוד, ויכולים להתחיל לחפש את המאזין.

הסתיגויות

הוכחת אבטחה היא קשה ביותר. למעשה הפרוטוקול המתואר בצורה רופפת כאן הוצע ב-1984, ולא הוכח כמאובטח עד 16 שנים מאוחר יותר Shor & Preskill, 2000. יש ניואנסים רבים שחורגים מהיקף מבוא זה. אך נפרט בקצרה כמה כדי להדגים שהנושא מורכב יותר ממה שמוצג כאן.

  • ערוצים מאובטחים: כאשר אליס שולחת את הקיוביטים שלה דרך הגדרה קוונטית כלשהי (ערוץ), ובפרט כאשר היא שומעת תגובות קלאסיות בחזרה ממישהו, הנחנו שהמישהו הוא באמת בוב. אם איב חדרה להגדרה זו כך ש__כל__ התקשורת של אליס הייתה בעצם עם איב, ו__כל__ התקשורת של בוב הייתה בעצם עם איב, אז איב השיגה ביעילות מפתח, ויכולה ללמוד סודות. ראשית יש להבטיח "ערוצים מאובטחים", תהליך עם קבוצה שונה של פרוטוקולים שלא טיפלנו בהם כאן.
  • הנחות לגבי איב: כדי להוכיח אבטחה באמת, אנחנו לא יכולים להניח הנחות לגבי התנהגותה של איב; היא תמיד יכולה לתסכל את ציפיותינו. כאן, כדי לתת דוגמאות קונקרטיות, אנחנו מניחים הנחות. לדוגמה, אנחנו עשויים להניח שהמצבים שאיב מעבירה לבוב הם תמיד בדיוק אלו שקיבלה עם המדידה. או שאנחנו עשויים להניח שהיא בוחרת אקראית מצב עקבי ניסויית עם מדידתה. בצורה יסודית יותר, הלשון כאן מניחה שאיב אכן מבצעת מדידה, בניגוד לאחסון המצב במערכת קוונטית אחרת ושליחת Qubit אקראי לבוב. הנחות אלה בסדר להבנת הפרוטוקול, אך הן אומרות שאנחנו לא מוכיחים שום דבר בכלליות מלאה.
  • הגברת פרטיות: אליס ובוב אינם נדרשים להשתמש במפתח הקוונטי בדיוק כפי שהועבר. הם יכולים, לדוגמה, להחיל פונקציית גיבוב על המפתח המשותף. זה ינצל את העובדה שלמאזין יש ידע חלקי בלבד על המפתח כדי לייצר מפתח משותף קצר יותר, אך מאובטח.

ניסוי 1: QKD ללא מאזין

בואו נממש את הפרוטוקול שלמעלה בהיעדר מאזין. נעשה זאת תחילה באמצעות סימולטור, פשוט כדי להבין את תהליך העבודה.

ראשית, הערה על סימולטורים קוונטיים: רוב הבעיות הקוונטיות הכוללות יותר מ-~30 קיוביטים לא ניתנות לסימולציה על ידי רוב המחשבים. אף מחשב קלאסי, על-מחשב או GPU לא יכול לדמות את מלוא טווח ההתנהגות של מחשב קוונטי בן 127 קיוביטים. בדרך כלל, המוטיבציה לשימוש במחשבים קוונטיים אמיתיים היא שהקיוביטים השזורים הרבים אינם ניתנים לסימולציה. במקרה זה, אין שזירה של קיוביטים, אלא אם כן אנחנו משתמשים בסכמת הטלפורטציה להעברת מידע. במקרה זה, המוטיבציה לשימוש במחשבים קוונטיים אמיתיים שונה: היא משפט אי-השכפול. מחשב קלאסי המדמה Qubit יכול לשלוח מידע על מצב קוונטי מאליס לבוב, אך אם מידע קלאסי זה יירוט, ניתן לשכפל אותו בקלות, ואיב יכולה לשמור עותק מושלם, תוך שליחת עותק אחר לבוב. זה אינו אפשרי עם מצבים קוונטיים אמיתיים.

IBM Quantum ממליצה לטפל בבעיות קוונטיות באמצעות מסגרת שאנחנו קוראים לה "תבניות Qiskit". היא מורכבת מהשלבים הבאים.

  • שלב 1: מפה את הבעיה שלך ל-Circuit קוונטי
  • שלב 2: אופטימיזציה של ה-Circuit שלך להרצה על חומרה קוונטית אמיתית
  • שלב 3: הרץ את העבודה שלך על מחשבי קוונטום של IBM באמצעות Runtime primitives
  • שלב 4: עיבוד לאחר של התוצאות

שלב 1 בתבניות Qiskit: מיפוי הבעיה שלך ל-Circuit קוונטי

במקרה זה, מיפוי הבעיה שלנו ל-Circuits קוונטיים מצטמצם פשוט להכנת מצבי אליס, ולאחר מכן הכללת מדידותיו של בוב. אנחנו מתחילים בבחירת הביט האקראי ובסיס אקראי.

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

import numpy as np
from qiskit import QuantumCircuit

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

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

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

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

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

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

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

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

qc.barrier()

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

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

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

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

בואו נמחיש את הביטים, הבסיסים וה-Circuit. שימו לב שלפעמים הבסיסים תואמים, ולפעמים לא.

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

Output of the previous code cell

שלב 2 בתבניות Qiskit: אופטימיזציה של הבעיה להרצה קוונטית

שלב זה לוקח את הפעולות שאנחנו רוצים לבצע ומבטא אותן במונחים של הפונקציונליות של מחשב קוונטי ספציפי. הוא גם ממפה את הבעיה שלנו על הפריסה של המחשב הקוונטי.

נתחיל בטעינת כמה חבילות שנדרשות לתקשורת עם מחשבים קוונטיים של IBM. אנחנו גם צריכים לבחור Backend שעליו להריץ. אפשר לבחור את ה-Backend הכי פחות עמוס, או לבחור Backend ספציפי שאת המאפיינים שלו אנחנו מכירים. למרות שנשתמש בסימולטור לרגע, חשוב להשתמש במודל רעש סביר בסימולציה, וכדאי לשמור את תהליך העבודה קרוב ככל האפשר למה שנשתמש בו מאוחר יותר עם מחשבים קוונטיים אמיתיים.

יש קוד למטה לשמירת האישורים שלך בשימוש הראשון. הקפד למחוק את המידע הזה מה-notebook לאחר השמירה לסביבה שלך, כדי שהאישורים שלך לא יישתפו בטעות כאשר אתה משתף את ה-notebook. ראה הגדרת חשבון IBM Cloud שלך ואתחול השירות בסביבה לא מהימנה להנחיות נוספות.

# Load the Qiskit Runtime service
from qiskit_ibm_runtime import QiskitRuntimeService

# Load the Qiskit Runtime service

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

# Load saved credentials
service = QiskitRuntimeService()

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

למטה אנחנו בוחרים סימולטור ומודל רעש.

# Load the backend sampler
from qiskit.primitives import BackendSamplerV2

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

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

noise_model = NoiseModel.from_backend(backend)

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

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

שלב 3 בתבניות Qiskit: הרצה

השתמש ב-Sampler להרצת העבודה שלך, עם ה-Circuit כארגומנט.

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

שלב 4 בתבניות Qiskit: עיבוד לאחר מדידה

כאן אנחנו מפרשים את התוצאות שלנו ומחלצים מידע שימושי. אפשר לנסות להמחיש את הפלט של ה-Sampler שלנו, אך השתמשנו ב-Sampler בדרך לא קונבנציונלית. במקום לבצע מדידות רבות של ה-Circuit שלנו ולפתח סטטיסטיקה על המצבים, ביצענו רק מדידה אחת (של בוב). כל Qubit שמצבו הוכן ונמדד באותה בסיס אמור להיות בעל תוצאה דטרמיניסטית, כך שנדרשת רק מדידה אחת. ה-Qubits שמצביהם הוכנו ונמדדו בבסיסים שונים (שיהיו בעלי תוצאות הסתברותיות ודורשים מדידות רבות לפרשנות) לא ישמשו לבניית ה-one-time pad/מפתח שלנו. נוציא רשימת תוצאות מדידה מה-bitstring הזה. שים לב להפוך את הסדר אם משווים עם מערך הביטים של אליס שבו השתמשנו ליצירת ה-Circuit.

# Get an array of bits

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

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

bbits = bmeas_ints[::-1]

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

בואו נשווה בין הבסיסים שנבחרו באקראי על ידי אליס ובוב. זה היה שלב 3 בפרוטוקול QKD שלנו (דיון ציבורי על בסיסים). בכל פעם שבחרו אותו בסיס עבור Qubit, אנחנו מוסיפים את הביטים הקשורים ל-Qubit הזה לרשימת ביטים ליצירת מספרים ב-one-time pad. כאשר הבסיסים לא תואמים, התוצאות נזרקות. בואו גם נבדוק אם שתי הרשימות של ביטים מסכימות, או אם היו אובדנים עקב רעש או גורמים אחרים.

# QKD step 3: Public discussion of bases

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

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

לאליס ולבוב יש כל אחד רשימת ביטים, והם תואמים ב-100% נאמנות. הם יכולים להשתמש בהם כדי ליצור מספרים ב-one-time pad. לאחר מכן הם יכולים להשתמש בזה בשלב 4 של QKD: שליחה ופענוח של סוד. מערך הביטים הנוכחי קצר מדי לפענוח של כמעט כל דבר. נחזור לכך לאחר הכללת האזנת סתר.

בדוק את ההבנה שלך

קרא את השאלה למטה, חשוב על התשובה שלך, ואז לחץ על המשולש לגילוי הפתרון.

נניח שאתה צריך ספרות גדולות מספיק כדי לאפשר הזזת אותיות באלפבית האנגלי לפי האורך המלא של האלפבית, או יותר, למרות שבהחלט קיימות תוכניות קידוד אחרות. (א) כמה אותיות יכולה להיות הודעה כדי שניתן יהיה לפענחה באמצעות הביטים שבמפתח לעיל? (ב) האם התשובה שלך חייבת להסכים עם התשובה של חבריך לכיתה? למה כן או למה לא?

תשובה:

(א) התשובה תלויה בכמה בסיסים שנבחרו באקראי תאמו בין אליס ובוב. מכיוון שיש סיכוי של בערך 50-50 לתאימות הבסיסים עבור כל Qubit נתון, אנחנו מצפים שקרוב ל-10 מהביטים שלנו יהיו שימושיים. 9 או 11 יהיו שכיחים לגמרי. אפילו 4 או 15 אינם מחוץ לתחום האפשרי. 5 ביטים נדרשים להזזה במספר גדול מ- או שווה לאורך האלפבית האנגלי, כלומר ניתן להחיל את ההזזה על אות אחת עבור כל 5 ביטים שיש לך. אם יש לך לפחות 5 ביטים משותפים בין אליס ובוב, ניתן לקודד אות בודדת. אם יש לך לפחות 10, ניתן לקודד 2 אותיות, וכן הלאה. (ב) אין צורך שיסכים, מהסיבות שפורטו ב-(א).

ניסוי 2: QKD עם מאזין סתר

נממש בדיוק את אותו הפרוטוקול כמו קודם. הפעם נכניס מערכת נוספת של מדידות, על ידי איב, בין אליס ובוב.

from qiskit import ClassicalRegister, QuantumCircuit, QuantumRegister

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

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

# Alice's random bits and bases, as before

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

# Alice's state preparation, as before

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

qc.barrier()

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

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

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

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

שלב 4 בתבניות Qiskit (עיבוד לאחר מדידה) פשוט במקרה זה. אין צורך להמחיש את התפלגות המדידות, מכיוון שביצענו רק מדידה אחת. לאיב יש את הביטים הבאים:

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

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

עכשיו איב חייבת לשחזר מצבים כדי לשלוח הלאה לבוב. כפי שמתואר במבוא, אין לה דרך לדעת אם ניחשה נכון את בסיסי הקידוד, ולכן היא אינה מסוגלת להכין בדיוק את אותם המצבים שנשלחו. היא יכולה להניח שכל בחירת בסיס הייתה נכונה ולקודד בדיוק את מה שמדדה, או שהיא יכולה להניח שבחרה את הבסיס בצורה שגויה ולבחור מצב eigenvector כלשהו של הבסיס ההפוך. כאן, אנחנו מניחים את הראשון, לפשטות. אנחנו מבצעים זאת על ידי בניית Circuit קוונטי חדש לגמרי, תוך חזרה על שלבי תבניות Qiskit כמו קודם.

from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

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

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

# Eve's state preparation

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

qc.barrier()

# QKD step 2: Random bases for Bob

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

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

# Qiskit patterns step 2: Transpile

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

# Qiskit patterns step 3: Execute

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

# Qiskit patterns step 4: Post-processing

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

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

עכשיו בואו נשווה את הביטים של אליס ובוב:

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

בעבר, הייתה התאמה מושלמת בין הביטים במפתחות של אליס ובוב. עכשיו, מהפרעת איב, אנחנו רואים שהביטים של אליס ובוב שונים ב-14% מהמקרים שאמורים להתאים בגלל שאליס ובוב בחרו באותם בסיסים. זה אמור להיות קל לגילוי על ידי אליס ובוב. עם זאת, הסתמכות על אחוז שגיאות כזה אכן אומרת שיש גבול לכמות הרעש שאנחנו יכולים לסבול בערוץ הקוונטי.

ניסוי 3: השוואת QKD עם ובלי האזנה במחשב קוונטי אמיתי

בואו נריץ את זה על מחשב קוונטי אמיתי. ככה נוכל לנצל את משפט אי-השכפול. יחד עם זאת, למחשבים קוונטיים אמיתיים יש רעש, ושיעורי שגיאה גבוהים יותר מאשר למחשבים קלאסיים. אז בואו נשווה את אובדן הנאמנות בביטי המפתח שלנו עם ובלי האזנה, כדי לוודא שהפרש ניתן לזיהוי כשמשתמשים במחשב קוונטי אמיתי. נתחיל בהיעדר האזנה:

from qiskit_ibm_runtime import SamplerV2 as Sampler

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

bit_num = 127
qc = QuantumCircuit(bit_num, bit_num)

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

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

# Alice's state preparation

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

# QKD step 2: Random bases for Bob

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

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

# Qiskit patterns step 2: Transpilation

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

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

# Qiskit patterns step 3: Execute

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

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

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

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

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

# Print some results

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

ללא האזנה, קיבלנו 100% נאמנות על פני קבוצה זו של 127 ביטים לניסוי, מה שהוביל ל-55 בסיסים תואמים וביטי מפתח שמישים. עכשיו בואו נחזור על הניסוי הזה עם איב שמאזינה:

from qiskit_ibm_runtime import SamplerV2 as Sampler

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

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

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

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

# Alice's state preparation

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

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

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

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

# Qiskit patterns step 2: Transpile

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

sampler = Sampler(mode=backend)

# Qiskit patterns step 3: Execute

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

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

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

# print(ebits)

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

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

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

# Eve's state preparation

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

# QKD step 2: Random bases for Bob

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

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

# Qiskit patterns step 2: Transpile

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

# Qiskit patterns step 3: Execute

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

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

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

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

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

# Print some results

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

כאן מצאנו אובדן נאמנות של כמעט 23% בביטים המשותפים בגלל ההאזנה! זה ניתן לזיהוי בקלות! שימו לב שהעברת מידע קוונטי על פני מרחקים ארוכים עלולה עדיין להכניס רעש ושגיאות נוספות. הבטחה שניתן לזהות האזנה, גם בנוכחות רעש, וגם כשאיב משתמשת בכל הטריקים שברשותה — היא תחום מורכב שמעבר למבוא הזה.

שאלות

מדריכים יכולים לבקש גרסאות של המחברות האלה עם מפתחות תשובות והנחיות לשילוב בתכניות לימוד נפוצות על ידי מילוי סקר קצר זה על האופן שבו המחברות נמצאות בשימוש.

מושגי מפתח

  • מידע קוונטי לא ניתן להעתקה או "שכפול".
  • אפשר לחזור על אותו תהליך הכנה כדי ליצור אנסמבל של מצבים קוונטיים שכולם זהים, או כמעט זהים.
  • מפתח הצפנה/פענוח (רפידה חד-פעמית) ניתן לשיתוף בין שני חברים תוך שימוש במצבים קוונטיים.
  • כשבשני החברים בוחרים בסיס מדידה באקראי, במחצית מהמקרים הם יבחרו שונה, ויצטרכו לזרוק את המידע על אותם Qubits.
  • הבחירה האקראית של בסיס המדידה גם מבטיחה שמאזין לא יכול לדעת את המצב ההתחלתי שהוכן, ולכן לא יכול לשחזר את המצב שנשלח. זה מבטיח שהאזנה תיחשף.

שאלות נכון/לא נכון

  1. נ/לנ: בהפצת מפתח קוונטית, שני השותפים המתקשרים מודדים כל Qubit באותו בסיס.
  2. נ/לנ: מאזין שמיירט מידע קוונטי ב-QKD מנוע על ידי חוקי הטבע מלהעתיק את המצב הקוונטי שיירט.
  3. נ/לנ: רפידה חד-פעמית היא מפתח להצפנה/פענוח הודעות מאובטחות שבו נעשה שימוש בסכמת קידוד מסוימת רק פעם אחת, עבור פיסת מידע אחת (כמו אות אחת באלפבית).

שאלות רב-ברירה

  1. בחר את האפשרות שמשלימה את המשפט בצורה הטובה ביותר. כפי שתואר במודול זה, רפידה חד-פעמית היא קבוצת מפתחות הצפנה/פענוח שנמצאת בשימוש...
  • א. רק פעם אחת עבור פיסת מידע אחת, כמו אות אחת.
  • ב. רק פעם אחת עבור הודעה אחת.
  • ג. רק פעם אחת לתקופת זמן מסוימת, כמו יום אחד.
  • ד. עד שיש ראיות להאזנה.
  1. נניח שאליס ובוב בוחרים את בסיסי המדידה שלהם באקראי. הם מודדים. אחר כך הם חולקים את בסיסי המדידה שלהם, ושומרים רק את ביטי המידע מהמקרים שבהם השתמשו באותו בסיס. בהתאם לתנודות אקראיות כלשהן, בערך איזה אחוז מה-Qubits שלהם אמורים לתת ביטי מידע שמישים?
  • א. 100%
  • ב. 50%
  • ג. 25%
  • ד. 12.5%
  • ה. 0%
  1. לאחר שאליס ובוב בוחרים מקרים שבהם השתמשו באותם בסיסי מדידה, איזה אחוז מביטי המידע האלה אמורים להתאים, אם רעש וטעויות קוונטיות היו זניחים?
  • א. 100%
  • ב. 50%
  • ג. 25%
  • ד. 12.5%
  • ה. 0%
  1. נניח שאליס בחרה את בסיסי המדידה שלה באקראי. איב גם בוחרת את הבסיסים שלה באקראי, והיא מאזינה (מודדת). היא שולחת מצבים לבוב שעקביים עם המדידות שלה. אליס ובוב משווים בחירות בסיס ושומרים רק את ה-Qubits שנמדדו/הוכנו על ידם באותם בסיסים. בהתאם לתנודות אקראיות כלשהן, בערך איזה אחוז ממדידות ה-Qubit השמורות האלה יתאימו, לפי אליס ובוב?
  • א. 100%
  • ב. 75%
  • ג. 50%
  • ד. 25%
  • ה. 12.5%
  • ו. 0%

שאלות לדיון

  1. נניח שכל בחירות הבסיס אקראיות לכל המשתתפים, אליס, בוב ואיב. נניח שאחרי שאיב מאזינה, היא שולחת לבוב מצב שמוכן באותו בסיס שבו מדדה, ועקבי עם אותה מדידה. שכנעו את השותפים שלכם ש-12.5% מכל ה-Qubits שאותחלו על ידי אליס יניבו אי-התאמות מדידה בין אליס לבוב, מה שמצביע על האזנה (תוך התעלמות מטעויות ורעש קוונטי). רמז 1: מכיוון שאין בסיס מועדף, אם אתם שוקלים רק בחירה אחת ראשונית של אליס, היחס לבחירה הבודדת הזו אמור להיות זהה ליחס של סכום כל הבחירות. רמז 2: ייתכן שאין זה מספיק לספור את מספר הדרכים שדבר מה יכול לקרות, מכיוון שחלק מהתוצאות עשויות להתרחש בהסתברויות שונות.