הצפנת מקאליס

הצפנת מקאליס (באנגלית: McEliece Cryptosystem) היא מערכת הצפנה אסימטרית המבוססת על קוד תיקון שגיאות, שפותחה ב-1978 על ידי רוברט מקאליס (R.J. McEliece).

הרעיון הכללי הוא; בהינתן מחרוזת של <math>k</math> סיביות המקודדת למילת קוד בגודל <math>n > k</math> סיביות על ידי מקודד ידוע לכול של קוד ליניארי בינארי באורך <math>n</math> וממד <math>k</math>, אזי הטקסט המוצפן מיוצר על ידי החדרת <math>t</math> שגיאות אקראיות, כלומר הפיכת <math>t</math> סיביות (Bit flipping) במיקומים אקראיים במילת הקוד. אם <math>t</math> קטן בחצי לפחות ממרחק המינג של הקוד הליניארי של טקסט מוצפן נתון קיים רק טקסט גלוי יחיד המתאים לו שניתן לשחזור באמצעות קוד תיקון השגיאות. אך אם הפרמטרים <math>n,k,t</math> גדולים חילוץ הטקסט הגלוי מהטקסט המוצפן באמצעות תיקון שגיאות אינו מעשי אלא אם כן נתון מידע נוסף לגבי מבנה הקוד. ההבדל בפקטור העבודה בין קידוד מילת הקוד לבין תיקון השגיאות הוא הבסיס להצפנה האסימטרית שהציע מקאליס, המפתח הציבורי יהיה הקוד הליניארי והמפתח הפרטי יהיה המידע המאפשר את תיקון השגיאות בזמן פולינומי. מקאליס המליץ על שימוש בקוד תיקון שגיאות שנקרא "קוד גוֹפַּא בינארי" על שם ממציאו וולרי גופא (Valerii Goppa) מפני כמה סיבות, לקוד זה קיים אלגוריתם פענוח פולינומי יעיל וכן העובדה שקוד גופא מהווה מועמד טוב לפונקציה חד-כיוונית - קל לייצר קוד כזה אך קשה מאוד לזהות אותו.

===הגדרות כלליות===
כדי להקים מערכת הצפנת מקאליס, אפשר לפעול כדלהלן:
בוחרים קוד גוֹפַּא שהוא פולינום שרירותי אי-פריק <math>g(z)</math> ממעלה <math>t</math> מעל השדה <math>GF(2^m)</math> ותת-קבוצה <math>L</math> של <math>GF(2^m)</math> עם הפרמטרים <math>[n,\ge n-mt,\ge 2t+1]</math>. כדי לקבל מרחק מינימלי גדול ככל האפשר רצוי שמספר השורשים של <math>g(z)</math> יהיה שווה למעלה שלו (נקרא separable).
מכינים מטריצה יוצרת <math>G</math> של קוד גופא מסדר <math>k\times n</math>.
לאחר מכן בוחרים מטריצה הפיכה (לא סינגולרית) <math>S</math> אקראית מסדר <math>k\times k</math>, ומטריצת תמורה <math>P</math> (מטריצה בינארית ריבועית המכילה בדיוק כניסה אחת שהיא '1' בכל שורה ואו בכל עמודה וכל היתר אפסים) מסדר <math>n\times n</math> ומחשבים את <math>G^*=SGP</math>.
מפיצים את <math>G^*</math> ואת <math>t</math> כפרמטרים ציבוריים ושומרים בסוד את כל היתר.
אם מישהו רוצה להצפין מסר כלשהו <math>m</math> באורך <math>k</math> סיביות, הוא בוחר וקטור שגיאות <math>e</math> באורך <math>n</math> במשקל <math>t</math> (שבו לכל היותר <math>t</math> קואורדינטות שונות מאפס), וההצפנה של <math>m</math> היא <math>y=mG^*+e</math> אותה הוא שולח למקבל. המקבל יכול לחשב עם הפרמוטציה הסודית <math>P</math> את:
:<math>y'=yP^{-1}=mG^*P^{-1}+eP^{-1}=mSGPP^{-1}+e'=(mS)G+e'</math>
כאשר <math>e'</math> במשקל נמוך מ-<math>t</math>. עם אלגוריתם הפענוח של קוד גופא המקבל יכול לתקן את <math>y'</math> למילה <math>m'=mS</math> על ידי חישוב <math>e'</math>. כיוון שהמטריצה <math>S</math> הפיכה אפשר לחלץ את המסר על ידי <math>m=m'S^{-1}</math>.

כדי שהמערכת האמורה תהיה בטוחה ההמלצה של מקאליס הייתה לפני 25 שנה שהפרמטרים יהיו <math>m=10</math> והפולינום <math>g(z)</math> הוא פולינום אי פריק מסדר <math>t=50</math> ובמקרה זה <math>n=2^{10}=1024</math> ו-<math>k\ge 1024-10\cdot 50=525</math>. אולם כדי לעמוד בהתקדמות הטכנולוגית שחלה ב-25 השנים האחרונות מומלץ כיום להשתמש בפרמטרים קצת יותר גדולים כמו <math>n=2048,m=11</math> ומספר השגיאות בין 30 ל-120 והממד במקרה זה נע בין 1,718 ל-728. לסיכום המערכת היא:
{| class="wikitable" width="450"
|-
| width="25%" | מפתח ציבורי || מטריצה מותאמת <math>G^*</math> מסדר <math>k\times n</math> 

עם יכולת תיקון עד <math>t</math> שגיאות
|-
| מפתח סודי || הפולינום <math>g(z)</math>, 
המטריצה היוצרת המקורית <math>G</math> מסדר <math>k\times n</math>, 

המטריצה <math>P</math> מסדר <math>k\times k</math>,
 
המטריצה <math>S</math> מסדר <math>n\times n</math> 

כך שמתקיים <math>G^*=SGP</math>
|-
| המסר לקידוד || <math>m\in\{0,1\}^k</math>
|-
| הצפנה || <math>y=mG^*+e</math> כאשר <math>wt(e)\le t</math>
|-
| פענוח || תחילה <math>y'=yP^{-1}</math>, 

מתקנים את <math>y'</math> ל-<math>m'=mS</math> 

מחשבים את <math>m=m'S^{-1}</math>
|}

===דוגמה במספרים קטנים===
לשם המחשה: אם נבחר השדה <math>GF(2^4)</math>, הפולינום <math>k(X)=X^4+X+1</math> אי פריק ואז <math>\alpha</math> הוא אלמנט פרימיטיבי רק אם הוא מסדר 15. האלמנטים של תת-הקבוצה <math>GF(2^4)^*</math> הם החזקות של <math>\alpha</math> כאשר <math>\alpha^4=\alpha+1</math> הקבוצה המתקבלת היא <math>\{\alpha,\alpha^2,...,\alpha^{14}\}</math>. קוד גופה מעל שדה זה יכול להיות
:<math>g(z)=(z+\alpha)(z+\alpha^{14})=z^2+\alpha^7z+1</math>
:<math>L=\{\alpha^i|2\le i\le 13\}</math>
עבור קוד זה <math>n=12, t=2</math> ו-<math>k</math> צריך להיות <math>12-4\cdot 2=4</math>. המרחק המינימלי הוא <math>d\ge2\cdot 2+1=5</math>. בקיצור זהו קוד גופא בינארי <math>\Gamma(L,g(z))</math> עם הפרמטרים <math>[12,\ge 4,\ge 5]</math> ואפשר לתקן איתו עד שתי שגיאות. אם נבחר לדוגמה את המטריצות הבאות
:<math>G=\begin{pmatrix}
1 \ \ 1 \ \ 1 \ \ 1 \ \ 0 \ \ 1 \ \ 0 \ \ 1 \ \ 0 \ \ 1 \ \ 0 \ \ 0 \\
0 \ \ 1 \ \ 0 \ \ 0 \ \ 1 \ \ 1 \ \ 1 \ \ 1 \ \ 0 \ \ 0 \ \ 1 \ \ 0 \\
0 \ \ 0 \ \ 1 \ \ 0 \ \ 1 \ \ 0 \ \ 1 \ \ 1 \ \ 1 \ \ 0 \ \ 0 \ \ 0 \\
0 \ \ 1 \ \ 0 \ \ 1 \ \ 0 \ \ 0 \ \ 1 \ \ 1 \ \ 0 \ \ 0 \ \ 0 \ \ 1 
\end{pmatrix}</math>

:<math>S=\begin{pmatrix} 1 & 0 & 1 & 1 \\ 0 & 1 & 0 & 1 \\ 1 & 1 & 0 & 1 \\ 1 & 1 & 1 & 1 \end{pmatrix}</math>

:<math>P=\begin{pmatrix} 
0 \ \ 0 \ \ 0 \ \ 1 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \\ 
0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 1 \ \ 0 \\ 
0 \ \ 0 \ \ 0 \ \ 0 \ \ 1 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \\ 
0 \ \ 1 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \\ 
1 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \\ 
0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 1 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 \ \ 0 
\end{pmatrix}</math>

:<math>G^*=SGP=\begin{pmatrix} 
1 \ \ 0 \ \ 1 \ \ 1 \ \ 0 \ \ 1 \ \ 1 \ \ 1 \ \ 0 \ \ 1 \ \ 0 \ \ 0 \\ 
1 \ \ 1 \ \ 0 \ \ 0 \ \ 0 \ \ 1 \ \ 0 \ \ 1 \ \ 1 \ \ 0 \ \ 0 \ \ 0 \\ 
1 \ \ 0 \ \ 1 \ \ 1 \ \ 1 \ \ 0 \ \ 1 \ \ 1 \ \ 1 \ \ 0 \ \ 1 \ \ 0 \\ 
0 \ \ 0 \ \ 1 \ \ 1 \ \ 0 \ \ 0 \ \ 0 \ \ 1 \ \ 1 \ \ 1 \ \ 1 \ \ 1 
\end{pmatrix}</math>

והמסר להצפנה הוא <math>m=(0,1,0,1)</math> תחילה מחשבים את 
:<math>mG^*=(1,1,1,1,0,1,0,0,0,1,1,1)</math> 
מוסיפים את וקטור השגיאה (שהוא וקטור המכיל אפסים למעט הפוזיציות השנייה והשלישית) ואז ההצפנה של <math>m</math> היא
:<math>y=mG^*+e=(1,\color{Red}0\color{Black},\color{Red}0\color{Black},1,0,1,0,0,0,1,1,1)</math>
המקבל שרוצה לפענח את <math>m</math> מתוך <math>y</math> מחשב תחילה את <math>yP^{-1}</math> מהמטריצה <math>P</math> 
:<math>yP^{-1}=mSG+e'=(1,1,0,\color{Red}0\color{Black},1,1,1,0,1,\color{Red}0\color{Black},0,0)</math>
כתוצאה מהפעולה האחרונה השגיאות עברו לפוזיציות הרביעית והעשירית אחרי תיקון מתקבל 
:<math>mSG=(1,1,0,1,1,1,1,0,1,1,0,0)</math>
ואז אפשר לפענח את הקוד על ידי כפל המטריצות הבא:
:<math>[G^T|(mS)^T]= \begin{pmatrix} 1 & 0 & 0 & 0 & 1 \\ 1 & 1 & 0 & 1 & 1 \\ 1 & 0 & 1 & 0 & 0 \\ 1 & 0 & 0 & 1 & 1 \\ 0 & 1 & 1 & 0 & 1 \\ 1 & 1 & 0 & 0 & 1 \\ 0 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 0 \\ 0 & 0 & 1 & 0 & 1 \\ 1 & 0 & 0 & 0 & 1 \\ 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 \end{pmatrix}\sim\begin{pmatrix} 1 & 0 & 0 & 0 & \color{Green}1 \\ 0 & 1 & 0 & 0 & \color{Green}0 \\ 0 & 0 & 1 & 0 & \color{Green}1 \\ 0 & 0 & 0 & 1 & \color{Green}0 \\ 1 & 1 & 0 & 1 & 1 \\ 1 & 0 & 1 & 0 & 0 \\ 1 & 0 & 0 & 1 & 1 \\ 0 & 1 & 1 & 0 & 1 \\ 1 & 1 & 0 & 0 & 1 \\ 0 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 0 \\ 1 & 0 & 0 & 0 & 1 \end{pmatrix}</math>

לכן <math>mS=(1,0,1,0)</math> והצעד האחרון הוא חישוב <math>S^{-1}</math> 
:<math>m=(1,0,1,0)\cdot \begin{pmatrix} 0 & 1 & 1 & 0 \\ 1 & 0 & 0 & 1 \\ 0 & 0 & 1 & 1 \\ 1 & 1 & 0 & 1 \\ \end{pmatrix}=(0,1,0,1)</math>.

===קוד גופא בינארי===
יהי <math>m</math> שלם חיובי ויהיו <math>n</math> ו-<math>t</math> שני פרמטרים כך שמתקיים <math>n\le 2^m</math> וכן <math>t<n/m</math>. קוד גופה בינארי המסומן <math>\Gamma(L,g)</math> מוגדר על ידי תת-קבוצה סדורה <math>L=(\alpha_1,...,\alpha_n)</math> של השדה <math>F_{2^m}</math> מסדר <math>n</math> שנקראת תמיכה (support) ועל ידי פולינום מתוקן אי פריק <math>g(z)\in F_{2^m}[z]</math> ממעלה <math>t</math> ללא שורשים ב-<math>L</math> הנקרא יוצר (generator). הווקטור <math>a=(a_0,...,a_{n-1})\in F_2^n</math> ייקרא קוד גופא אם מתקיים 
:<math>R_a(z)\triangleq \sum_{j=0}^{n-1} \alpha_j(z-\alpha_j)^{-1}\equiv 0\text{ mod }g(z)</math>

הביטוי <math>(z-\alpha_j)^{-1}</math> קיים מאחר ש-<math>F_{2^m}/g(z)</math> הוא שדה. והמעלה <math>t</math> של הפולינום מהווה גבול תחתון ליכולת תיקון השגיאות של הקוד. הקוד המתואר ליניארי ולו ממד <math>k\ge n-tm</math> וכן מרחק מינימלי של <math>2t+1</math> לפחות לכן ניתן לשחזר עד <math>t</math> שגיאות.

===פענוח אלגברי של קוד גופה===
אם <math>a</math> הוא מילת קוד של <math>\Gamma(L,g)</math> ואם <math>b=a+e</math> עם <math>e\in F_2^n</math> בעל מרחק המינג <math>t</math> או פחות, המילים <math>a</math> ו-<math>e</math> ייחודיים בגלל <math>b</math>. קיים פולינום מתוקן יחיד <math>\sigma(z)</math> ב-<math>F_{2^m}</math> ממעלה לכל היותר <math>t</math> המקיים
:<math>\sigma(z)R_b(z)\equiv\omega(z)\text{ mod }g(z)</math>
כאשר <math>\omega(z)</math> הוא פולינום ב-<math>F_{2^m}</math> ממעלה לכל היותר <math>t-1</math>. לפולינום <math>\sigma(z)</math> יש בדיוק <math>t</math> שורשים ב-<math>L</math> המתאימים לפוזיציות המכילות אחד בווקטור השגיאה <math>e</math>. תהליך הפענוח כולל את הפעולות הבאות:
*חישוב קוד גופה <math>R_b(z)\text{ mod }g(z)</math>,
*פתרון נוסחת המפתח <math>\sigma(z)R_b(z)\equiv\omega(z)\text{ mod }g(z)</math>,
*חישוב השורשים של <math>\sigma(z)</math>.
ישנן כמה וריאציות לפתרון נוסחת המפתח האמורה ביניהן אלגוריתם אוקלידס.

===גרסאות נוספות===
ב-1986 הציע נידריטר (Niederreiter) מערכת דומה בביטחונה שנקראת גרסה דואלית. גרסה נוספת שהוצעה מבוססת על קוד ריד-מולר. מקאליס ציין שהמערכת שלו אינה מתאימה לחתימה דיגיטלית ב-2001 הומצאה חתימה דיגיטלית מבוססת מקאליס.

===גודל מפתחות===
גודל המפתח הציבורי הוא כנראה חסרונה הגדול של המערכת והוא <math>kn</math> כאשר <math>k</math> הוא אורך המידע המיועד להצפנה ו-<math>n</math> הוא אורך הבלוק המוצפן. למשל לפי הפרמטרים המקוריים שהוצעו על ידי מקאליס גודל המפתח הציבורי הוא 536,576 סיביות. סנדריר הציע להפחית מגודל המפתח הציבורי בשיטה סיסטמטית. כלומר <math>G=(I|U)</math> כאשר <math>I</math> הוא מטריצת היחידה <math>k\times k</math> ו-<math>U</math> הוא מסדר <math>k\times(n-k)</math>. כך גודל המפתח מצטמצם ל-<math>k(n-k)</math> סיביות כי יש צורך לאחסן רק את הצד הימני (<math>U</math>), אך עדיין המפתח יהיה די גדול (בערך 262,000 סיביות).

==ביטחון==
הצפנת מקאליס מבוססת על שתי בעיות קשות בתורת הקודים האחת היא מקרה פרטי של בעיית "פענוח סינדרומי" שהוכח שהיא NP-שלמה; בהינתן מטריצה בינארית מסדר <math>r\times n</math> ו-<math>a</math> מילות קוד כלשהן ב-<math>F_2^r</math> הבעיה היא למצוא מילה <math>e</math> ב-<math>F_2^n</math> במשקל נמוך או שווה ל-<math>r/\text{log}_2n</math> כך שמתקיים <math>He^T=s</math> כאשר <math>s</math> הוא הסינדרום. הוכח על ידי ברלקמפ, מקאליס וטילבורג שהבעיה NP-קשה.

והבעיה שנייה היא בעיית זיהוי 'קוד גופא', כלומר בהינתן מטריצה בינארית מסדר <math>r\times n</math> לענות על השאלה האם היא מטריצת גופה. אפשר לתקוף את סכימת מקאליס בשתי דרכים. אחת היא 'התקפה מבנית' בה מנסים לשחזר את המפענח של הקוד הנוצר על ידי המפתח הציבורי <math>G^*</math> ומשם לשחזר את המפתח הפרטי <math>G</math>, אם היא מצליחה המערכת נפרצת לחלוטין. אפשר לסווג קודי שגיאות למחלקות שקילות, שני קודים באורך זהה ייקראו שקולים (שההפרש ביניהם הוא מילת קוד) אם קיימת בדיוק תמורה אחת באורך <math>n</math> המשנה קוד אחד לשני לכן הקוד <math>C'</math> שנוצר על ידי <math>G^*</math> והקוד הנוצר על ידי <math>G</math> נקראים שקולים. בהתקפה זו התוקף מנסה להשוות בין קודים כדי למצוא שקילות. אם נמצאה שקילות אפשר לשחזר את התמורה ביניהם על ידי אלגוריתם פולינומי שנקרא Support Splitting Algorithm (של ניקולס סנדריר 1999). תהליך זה הוא מעבר ליכולת הטכנולוגית הנוכחית עם הפרמטרים המקוריים של מקאליס כי התקפה מבנית מסוג זה דורשת בערך <math>2^{466}</math> קודים כדי שתצליח. בהתקפה השנייה שנקראת התקפת פענוח התוקף מנסה לנחש את פענוח הקוד מבלי לפרוץ את המערכת עצמה. ההתקפה תלויה בפרמטרים של קוד תיקון השגיאות <math>C'</math>, אורכו, הממד שלו ויכולת תיקון השגיאות (<math>t</math>). לפי הפרמטרים המקוריים של מקאליס התקפה כזו תתבצע עם <math>2^{64}</math> פעולות בינאריות. מספר זה נמוך בהשוואה ליכולת הטכנולוגית הנוכחית אך הבעיה היא שכדי להעלות מספר זה יש צורך להגדיל את הפרמטרים וכיוון שהמפתח הציבורי מאוד גדול גם ככה זו בעיה.

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

==קישורים חיצוניים==
* 
* אנציקלופדיה לקריפטוגרפיה ואבטחה, הוצאת שפרינגר, 2005

==הערות שוליים==

מקאליס