**ZUC** הוא צופן זרם שפותח ב-2010 על ידי האקדמיה הסינית למדע עבור טכנולוגיית LTE. זהו צופן זרם סינכרוני, מותאם לחומרה ותוכנה כאחד, פועל ברמת מילים באורך 32 סיביות, מקבל מפתח הצפנה באורך 128 סיביות, וקטור אתחול באורך 128 סיביות ומייצר מילים פסאודו-אקראיות באורך 32 סיביות המשמשות חלק מזרם מפתח להצפנה ופענוח של המידע מילה אחר מילה. ZUC שוכן בליבת תקן 3GPP להצפנה מאומתת של שיחה סלולרית באלגוריתמים EEA3 להצפנה ו-EIA3 לאימות. הצופן קרוי על שמו של המתמטיקאי הסיני זו צ'אנגזי שחי במאה החמישית לספירה.

תיאור הצופן
-----------

תרשים סכמטי של צופן ZUC המתאר את שלוש השכבות (הקווים המקווקווים); השכבה הראשונה LFSR מייצגת את אוגר הזיזה בעל 16 המצבים, שכבת סידור הסיביות מחדש BitReorganization נמצאת באמצע ומתחתה שכבת הפונקציה הליניארית.
ZUC מחולק לשני מצבי הפעלה, מצב הכנה ומצב העבודה. בשלב הראשון מפתח ההצפנה ווקטור האתחול נטענים לתוך המצב הפנימי והצופן מופעל (clocked) ללא יצירת פלט. בשלב השני בכל פעימת שעון נוצרת מילה פסאודו אקראית באורך 32 סיביות.
בהמרות ממילים לבתים מתייחסים לכל הערכים כאל מספרים שלמים לפי סדר בתים קטן. לדוגמה אם {\displaystyle a={\text{0x1234}}} ו-{\displaystyle b={\text{0x5678}}} אז {\displaystyle c=a\ \|\ b={\text{0x12345678}}}. הסימן "{\displaystyle \lll \_{n}}" מייצג הזזה מעגלית לשמאל בגבולות מילה באורך {\displaystyle n} סיביות.הסימנים "{\displaystyle \ll }" ו-"{\displaystyle \gg }" מייצגים הזזה (shift) של סיביות לימין או לשמאל בהתאמה, במספר פוזיציות לפי הערך המופיע לאחר הסימן. הסימן {\displaystyle \boxplus } מייצג חיבור מודולו {\displaystyle 2^{32}}. הסימן {\displaystyle \oplus } הוא XOR. ל-ZUC שלוש שכבות כמתואר בתרשים משמאל:

* שכבה עליונה - LFSR בעל 16 מצבים (Taps).
* שכבה אמצעית - סידור מחדש ברמה של סיביות.
* שכבה תחתונה - פונקציה אי-ליניארית.

  

### LFSR

בשכבה העליונה הצופן מכיל אוגר זיזה ממושב ליניארי הכולל 16 כניסות באורך 31 סיביות כל אחת המסומנות {\displaystyle (s\_{0},s\_{1},...s\_{15})} כאשר {\displaystyle s\_{i}\in \{1,2,3,...2^{31}-1\}}. בכל פעימה תכולת האוגר מוזזת צעד אחד לימין כלומר תכולת כל תא מועתקת לתא הבא שלימינו והתא הראשון ({\displaystyle s\_{15}}) מתעדכן לפי הפונקציה להלן. בשלב האתחול האוגר מקבל מילה אחת {\displaystyle u} באורך 31 סיביות המתקבלת על ידי הסרת הסיבית הימנית (הכי פחות משמעותית) של הפלט {\displaystyle W} של הפונקציה האי-ליניארית, כלומר {\displaystyle u=W\gg 1}. בשלב האתחול בהינתן הקלט {\displaystyle u} מתבצעים המהלכים הבאים:

1. {\displaystyle v=2^{15}s\_{15}+2^{17}s\_{13}+2^{21}s\_{10}2^{20}s\_{4}+(1+2^{8})s\_{0}{\text{ mod }}(2^{31}-1)};
2. {\displaystyle s\_{16}=(v+u){\text{ mod }}(2^{31}-1)};
3. {\displaystyle {\text{If }}s\_{16}=0{\text{ then set }}s\_{16}=2^{31}-1};
4. {\displaystyle (s\_{1},s\_{2},...s\_{15},s\_{16})\rightarrow (s\_{0},s\_{1},...s\_{14},s\_{15})}.

במצב עבודה ה-LFSR אינו מקבל קלט ופועל כדלהלן:

1. {\displaystyle s\_{16}=2^{15}s\_{15}+2^{17}s\_{13}+2^{21}s\_{10}2^{20}s\_{4}+(1+2^{8})s\_{0}{\text{ mod }}(2^{31}-1)};
2. {\displaystyle {\text{If }}s\_{16}=0{\text{ then set }}s\_{16}=2^{31}-1};
3. {\displaystyle (s\_{1},s\_{2},...s\_{15},s\_{16})\rightarrow (s\_{0},s\_{1},...s\_{14},s\_{15})}.

מהיבט פרקטי כפל האלמנט {\displaystyle s\_{j}} בחזקות {\displaystyle i} של 2 מעל השדה {\displaystyle GF(2^{31}-1)} מתבצע על ידי הזזה מעגלית של {\displaystyle s\_{j}} לשמאל {\displaystyle i} סיביות. לכן במהלך 1 לעיל כל שנדרש הוא חיבור מודולו {\displaystyle 2^{31}-1} לאחר סדרה של כמה הזזות. ההזזה המעגלית בקוד נראית כך:

{\displaystyle ((s\_{j}\ll i)\lor (s\_{j}\gg (31-i)))\land {\text{0x7FFFFFFF}}}.
ובאופן כללי מהלך 1 המתואר לעיל ניתן לביצוע בתוכנה באופן הבא:

{\displaystyle v=(s\_{15}\lll \_{31}15)+(s\_{13}\lll \_{31}17)+(s\_{10}\lll \_{31}21)+(s\_{4}\lll \_{31}20)+(s\_{0}\lll \_{31}8)+(s\_{0}{\text{ mod }}2^{31}-1))}.
חיבור שני אלמנטים {\displaystyle a} ו-{\displaystyle b} מעל השדה {\displaystyle GF(2^{31}-1)} ניתן לביצוע באופן הבא: תחילה מחשבים את {\displaystyle v=a+b} ואם מתרחשת גלישה כלומר סיבית הנשא היא 1 מבצעים בנוסף {\displaystyle v=v+1}. התנאי שבודק אם הסיבית העליונה היא '1' פותח פתח ל**התקפת תיזמון** - סוג של התקפת ערוץ צדדי, כיוון שכעת מהירות פעולת החיבור תלויה בסיבית זו לכן ניתן לבצע ניתוח סטטיסטי של מהירות החישוב כדי לחשוף סיביות. כדי לעקוף בעיה זו מבצעים באופן קבוע כך: תחילה מחשבים את {\displaystyle w=a+b} כאשר {\displaystyle w} הוא ערך באורך 32 סיביות ואז {\displaystyle v} שווה 31 הסיביות הכי פחות משמעותיות של {\displaystyle w} וכעת נוטלים את הסיבית הכי משמעותית של {\displaystyle w} מזיזים אותה להתחלה ומחברים עם {\displaystyle v} הקוד נראה כך:

{\displaystyle w=a+b,v=(w\land {\text{0x7FFFFFFF}})+(w\gg 31)}
### סידור מחדש (BitReorganization)

בשכבה האמצעית של האלגוריתם הנקראת בקיצור BR, מחלצים 128 סיביות משמונה תאים של ה-LFSR במיקומים המתוארים להלן ומהם מרכיבים ארבע מילים באורך 32 סיביות. שלוש המילים הראשונות ישמשו קלט לפונקציה האי-ליניארית להלן ואילו המילה הרביעית משתתפת ביצירת מילת פלט אחת של זרם המפתח. המיקומים ב-LFSR מהם נוטלים סיביות הם: {\displaystyle s\_{0},s\_{2},s\_{5},s\_{7},s\_{9},s\_{11},s\_{14},s\_{15}}. ארבע המילים האמורות מיוצגות על ידי {\displaystyle X\_{0},X\_{1},X\_{2},X\_{3}} אותם מרכיבים על ידי חצאי הקלט לפי הסדר הבא: 

1. {\displaystyle X\_{0}=s\_{15H}\ \|\ s\_{14L}};
2. {\displaystyle X\_{1}=s\_{11L}\ \|\ s\_{9H}};
3. {\displaystyle X\_{2}=s\_{7L}\ \|\ s\_{5H}};
4. {\displaystyle X\_{3}=s\_{2L}\ \|\ s\_{0H}}.

הסמלים {\displaystyle H} ו-{\displaystyle L} מייצגים את החצי העליון והחצי התחתון של המילה בהתאמה. למשל {\displaystyle s\_{iH}} פירושו הסיביות {\displaystyle 30...15} ולא {\displaystyle 31...16} של {\displaystyle s\_{i}} היות ש-{\displaystyle s\_{i}} מוגדר באורך 31 סיביות. לדוגמה בשורה 1 לעיל הערך של {\displaystyle X\_{0}} הוא שרשור של 16 הסיביות המשמעותיות ביותר של {\displaystyle s\_{15}} החל מהסיבית במיקום ה-15 ועד הסיבית ה-30 עם 16 הסיביות הפחות משמעותיות של {\displaystyle s\_{14}} החל מהסיבית במיקום ה-0 ועד הסיבית ה-15.

### פונקציה אי-ליניארית

השכבה התחתונה כוללת פונקציה {\displaystyle F} המכילה שני תאי זיכרון {\displaystyle R\_{1}} ו-{\displaystyle R\_{2}} באורך 32 סיביות כל אחד. הקלט הוא {\displaystyle X\_{0},X\_{1},X\_{2}} שהם פלט השכבה הקודמת והפלט הוא מילה {\displaystyle W} באורך 32 סיביות. ביתר פירוט:

1. {\displaystyle W=(X\_{0}\oplus R\_{1})\boxplus R\_{2}};
2. {\displaystyle W\_{1}=R\_{1}\boxplus X\_{1}};
3. {\displaystyle W\_{2}=R\_{2}\oplus X\_{2}};
4. {\displaystyle R\_{1}=S(L\_{1}(W\_{1L}\ \|\ W\_{2H}))};
5. {\displaystyle R\_{2}=S(L\_{2}(W\_{2L}\ \|\ W\_{1H}))}.

הפונקציה {\displaystyle S} היא תיבות החלפה S-box בגודל 32x32 סיביות והפונקציות {\displaystyle L\_{1}} ו-{\displaystyle L\_{2}} הן פונקציות ליניאריות כמתואר להלן.

### תיבות החלפה

{\displaystyle S} הוא תיבת החלפה s-box בגודל 32x32 המורכבת מארבע תיבות {\displaystyle S=(S\_{0},S\_{1},S\_{2},S\_{3})} שהן פונקציות אי-ליניאריות קבועות בצורת ארבע טבלאות בגודל 8x8 (המכילות 256 כניסות בגודל 8 סיביות). כאשר {\displaystyle S\_{2}=S\_{0}} וכן {\displaystyle S\_{3}=S\_{1}}. והטבלאות {\displaystyle S\_{0}} ו-{\displaystyle S\_{1}} מובאות להלן. הפונקציה {\displaystyle S\_{i}} מקבלת את הקלט {\displaystyle x=h\|l} בגודל בית אחד ומחזירה את הערך הנמצא בכניסה הנמצאת בשורה {\displaystyle h} ובעמודה {\displaystyle l} בטבלה וכן לגבי יתר הבתים של מילת הקלט (בסך הכול ארבעה בתים במילה), {\displaystyle X=x\_{0}\|x\_{1}\|x\_{2}\|x\_{3}}, ו-{\displaystyle Y=y\_{0}\|y\_{1}\|y\_{2}\|y\_{3}} כאשר {\displaystyle x\_{i}} ו-{\displaystyle y\_{i}} הם בתים. הפונקציה {\displaystyle S} אם כן מוגדרת כך: {\displaystyle y\_{i}=S\_{i}(x\_{i})} כאשר {\displaystyle i=0,1,2,3}.


| S0 |
| --- |
|  | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
| **0** | 3E | 72 | 5B | 47 | CA | E0 | 00 | 33 | 04 | D1 | 54 | 98 | 09 | B9 | 6D | CB |
| **1** | 7B | 1B | F9 | 32 | AF | 9D | 6A | A5 | B8 | 2D | FC | 1D | 08 | 53 | 03 | 90 |
| **2** | 4D | 4E | 84 | 99 | E4 | CE | D9 | 91 | DD | B6 | 85 | 48 | 8B | 29 | 6E | AC |
| **3** | CD | C1 | F8 | 1E | 73 | 43 | 69 | C6 | B5 | BD | FD | 39 | 63 | 20 | D4 | 38 |
| **4** | 76 | 7D | B2 | A7 | CF | ED | 57 | C5 | F3 | 2C | BB | 14 | 21 | 06 | 55 | 9B |
| **5** | E3 | EF | 5E | 31 | 4F | 7F | 5A | A4 | 0D | 82 | 51 | 49 | 5F | BA | 58 | 1C |
| **6** | 4A | 16 | D5 | 17 | A8 | 92 | 24 | 1F | 8C | FF | D8 | AE | 2E | 01 | D3 | AD |
| **7** | 3B | 4B | DA | 46 | EB | C9 | DE | 9A | 8F | 87 | D7 | 3A | 80 | 6F | 2F | C8 |
| **8** | B1 | B4 | 37 | F7 | 0A | 22 | 13 | 28 | 7C | CC | 3C | 89 | C7 | C3 | 96 | 56 |
| **9** | 07 | BF | 7E | F0 | 0B | 2B | 97 | 52 | 35 | 41 | 79 | 61 | A6 | 4C | 10 | FE |
| **A** | BC | 26 | 95 | 88 | 8A | B0 | A3 | FB | C0 | 18 | 94 | F2 | E1 | E5 | E9 | 5D |
| **B** | D0 | DC | 11 | 66 | 64 | 5C | EC | 59 | 42 | 75 | 12 | F5 | 74 | 9C | AA | 23 |
| **C** | 0E | 86 | AB | BE | 2A | 02 | E7 | 67 | E6 | 44 | A2 | 6C | C2 | 93 | 9F | F1 |
| **D** | F6 | FA | 36 | D2 | 50 | 68 | 9E | 62 | 71 | 15 | 3D | D6 | 40 | C4 | E2 | 0F |
| **E** | 8E | 83 | 77 | 6B | 25 | 05 | 3F | 0C | 30 | EA | 70 | B7 | A1 | E8 | A9 | 65 |
| **F** | 8D | 27 | 1A | DB | 81 | B3 | A0 | F4 | 45 | 7A | 19 | DF | EE | 78 | 34 | 60 |

|
|  |
| S1 |
|  | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
| **0** | 55 | C2 | 63 | 71 | 3B | C8 | 47 | 86 | 9F | 3C | DA | 5B | 29 | AA | FD | 77 |
| **1** | 8C | C5 | 94 | 0C | A6 | 1A | 13 | 00 | E3 | A8 | 16 | 72 | 40 | F9 | F8 | 42 |
| **2** | 44 | 26 | 68 | 96 | 81 | D9 | 45 | 3E | 10 | 76 | C6 | A7 | 8B | 39 | 43 | E1 |
| **3** | 3A | B5 | 56 | 2A | C0 | 6D | B3 | 05 | 22 | 66 | BF | DC | 0B | FA | 62 | 48 |
| **4** | DD | 20 | 11 | 06 | 36 | C9 | C1 | CF | F6 | 27 | 52 | BB | 69 | F5 | D4 | 87 |
| **5** | 7F | 84 | 4C | D2 | 9C | 57 | A4 | BC | 4F | 9A | DF | FE | D6 | 8D | 7A | EB |
| **6** | 2B | 53 | D8 | 5C | A1 | 14 | 17 | FB | 23 | D5 | 7D | 30 | 67 | 73 | 08 | 09 |
| **7** | EE | B7 | 70 | 3F | 61 | B2 | 19 | 8E | 4E | E5 | 4B | 93 | 8F | 5D | DB | A9 |
| **8** | AD | F1 | AE | 2E | CB | 0D | FC | F4 | 2D | 46 | 6E | 1D | 97 | E8 | D1 | E9 |
| **9** | 4D | 37 | A5 | 75 | 5E | 83 | 9E | AB | 82 | 9D | B9 | 1C | E0 | CD | 49 | 89 |
| **A** | 01 | B6 | BD | 58 | 24 | A2 | 5F | 38 | 78 | 99 | 15 | 90 | 50 | B8 | 95 | E4 |
| **B** | D0 | 91 | C7 | CE | ED | 0F | B4 | 6F | A0 | CC | F0 | 02 | 4A | 79 | C3 | DE |
| **C** | A3 | EF | EA | 51 | E6 | 6B | 18 | EC | 1B | 2C | 80 | F7 | 74 | E7 | FF | 21 |
| **D** | 5A | 6A | 54 | 1E | 41 | 31 | 92 | 35 | C4 | 33 | 07 | 0A | BA | 7E | 0E | 34 |
| **E** | 88 | B1 | 98 | 7C | F3 | 3D | 60 | 6C | 7B | CA | D3 | 1F | 32 | 65 | 04 | 28 |
| **F** | 64 | BE | 85 | 9B | 2F | 59 | 8A | D7 | B0 | 25 | AC | AF | 12 | 03 | E2 | F2 |

### טרנספורמציה ליניארית

ישנן שתי פונקציות ליניאריות {\displaystyle L\_{1}} ו-{\displaystyle L\_{2}} הפועלות על קלט של מילים באורך 32 סיביות ומפיקות פלט של מילים באורך 32 סיביות והן מוגדרות כדלהלן:

{\displaystyle L\_{1}(X)=X\oplus (X\lll \_{32}2)\oplus (X\lll \_{32}10)\oplus (X\lll \_{32}18)\oplus (X\lll \_{32}24)},
{\displaystyle L\_{2}(X)=X\oplus (X\lll \_{32}8)\oplus (X\lll \_{32}14)\oplus (X\lll \_{32}22)\oplus (X\lll \_{32}30)}.
### הכנת מפתח

תהליך ההכנה מקבל את המפתח הראשוני המסופק על ידי המשתמש מחולק ל-16 בתים {\displaystyle k=k\_{0}\|k\_{1}\|...\|k\_{15}} (128 סיביות) וכן וקטור האתחול {\displaystyle iv=iv\_{0}\|iv\_{1}\|...\|iv\_{15}} (16 בתים), וטוען אותם לתוך 16 הכניסות של אוגר ה-LFSR בתוספת קבוע {\displaystyle D} באורך 240 סיביות המובא להלן, המחולק ל-16 מקטעים באורך 15 סיביות כל אחד {\displaystyle D=d\_{0}\|d\_{1}\|...\|d\_{15}}. הערך ההתחלתי של כל כניסה באוגר הוא שרשור של שלושת הערכים: קטע אחד מהמפתח, חלק אחד מהקבוע {\displaystyle D} להלן וחלק מוקטור האתחול, כך: 

{\displaystyle s\_{i}=k\_{i}\ \|\ d\_{i}\ \|\ iv\_{i}} עבור {\displaystyle 0\leq i\leq 15}.
הקבוע {\displaystyle D} הוא:

{\displaystyle d\_{0}={\text{44D7}},d\_{1}={\text{26BC}},d\_{2}={\text{626B}},d\_{3}={\text{135E}},d\_{4}={\text{5789}},d\_{5}={\text{35E2}},d\_{6}={\text{7135}},d\_{7}={\text{09AF}}},
{\displaystyle d\_{8}={\text{4D78}},d\_{9}={\text{2F13}},d\_{10}={\text{6BC4}},d\_{11}={\text{1AF1}},d\_{12}={\text{5E26}},d\_{13}={\text{3C4D}},d\_{14}={\text{789A}},d\_{15}={\text{47AC}}}.

הצפנה ופענוח
------------

לשימוש בצופן ZUC בפעם הראשונה מפעילים אותו 32 פעימות במצב אתחול, פעימה אחת במצב סרק ולאחר מכן עוברים למצב עבודה רגיל. בשלב האתחול הצופן מבצע תחילה את פרוצדורת טעינת המפתח כמתואר לעיל ומאפס את האוגרים {\displaystyle R\_{1}} ו-{\displaystyle R\_{2}} ואז מתבצעות שלוש הפעולות הבאות 32 פעמים:

1. {\displaystyle {\text{BitReorganization}}()} (סידור סיביות מחדש),
2. {\displaystyle w=F(X\_{0},X\_{1},X\_{2})} (טרנספורמציה ליניארית),
3. {\displaystyle {\text{LFSRInitialisationMode}}(w\gg 1)} (הפעלת אוגר ה-LFSR).

שים לב שבשלב זה אוגר ה-LFSR בשורה 3 מקבל את הפרמטר {\displaystyle w} שהופק מהפונקציה האי-ליניארית, כלומר פלט הפונקציה האי-ליניארית מוזן בחזרה ל-LFSR בלולאה סגורה. לאחר מכן מתבצע מהלך סרק אחד שבו לא משתמשים בפלט הצופן אלא מתעלמים ממנו:

1. {\displaystyle {\text{BitReorganization}}()} (סידור סיביות מחדש),
2. {\displaystyle F(X\_{0},X\_{1},X\_{2})} (טרנספורמציה ליניארית),
3. {\displaystyle {\text{LFSRWorkingMode}}()} (הפעלת אוגר ה-LFSR).

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

1. {\displaystyle {\text{BitReorganization}}()} (סידור סיביות מחדש),
2. {\displaystyle Z=F(X\_{0},X\_{1},X\_{2})\oplus X\_{3}} (טרנספורמציה ליניארית),
3. {\displaystyle {\text{LFSRWorkingMode}}()} (הפעלת אוגר ה-LFSR).

בניגוד לשלב האתחול הפעלת אוגר ה-LFSR חסרת פרמטרים במצב עבודה. פלט הצופן בכל פעימה הוא {\displaystyle Z} באורך 32 סיביות והוא משמש חלק מזרם המפתח להצפנת או פענוח המידע.

ביטחון
------

ZUC הוא צופן חדש יחסית והוא בעצם שיפור של הצופן SNOW. חוקרים גילו שהצופן בגרסה המקורית (1.4) היה פגיע להתקפת מוצפן נבחר על וקטור האתחול. במקרים מסוימים הבדלים בוקטור האתחול הניבו מפתח הצפנה זהה מה שמצמצם את אורך המפתח האפקטיבי לכ-100 סיביות במקום 128. בצופן זרם שימוש במפתח הצפנה זהה להצפנת חלקים מהנתונים מהווה פגיעה הרסנית במיוחד בביטחון ההצפנה. כדי למנוע התקפה זו הם המליצו להחליף את ה-XOR בחיבור ({\displaystyle \boxplus }) מודולו {\displaystyle 2^{31}-1} בביטוי ({\displaystyle v+u}) בשלב האתחול, גרסה זו של הצופן נקראת 1.6 והיא מעודכנת בתיאור הצופן לעיל. ZUC הוא צופן מהיר מאוד בהשוואה לצפנים כמו SNOW. הוא למעשה מהמהירים ביותר הקיימים כיום וכן בשל המפתח הארוך ווקטור האתחול הארוך (128 סיביות כל אחד) מספק הגנה מספיק טובה מפני כמה התקפות ידועות כמו: התקפת מפתח חלש, התקפות ניחוש, התקפה אלגברית, התקפות תיזמון, התקפה דיפנרציאלית והתקפת קירוב ליניארי. הצופן אינו מספק הגנה טובה מפני התקפת ערוץ צדדי המתמקדת בגרף צריכת האנרגיה שלו במהלך הצפנה או פענוח. חוקרים הראו שההתקפה הנקראת DPA קיצור של Differential Power Analysis אפשרית נגד הצופן במידה שלתוקף יכולת למדוד את צריכת האנרגיה במחשב בו מבוצעת ההצפנה.

וקטור בדיקה
-----------

לדוגמה אם המפתח הוא:

{\displaystyle k={\text{3D 4C 4B E9 6A 82 FD AE B5 8F 64 1D B1 7B 45 5B}}}
וקטור האתחול הוא:

{\displaystyle iv={\text{84 31 9A A8 DE 69 15 CA 1F 6B DA 6B FB D8 C7 66}}}
המילה הראשונה של פלט הצופן צריכה להיות: {\displaystyle {\text{14F1C272}}}.

קוד לדוגמה
----------

```
typedef unsigned char byte;
typedef unsigned int uint;

uint LFSR[16];
uint F\_R1;
uint F\_R2;
uint BRC[4];

byte S0[256] = {
 0x3e,0x72,0x5b,0x47,0xca,0xe0,0x00,0x33,0x04,0xd1,0x54,0x98,0x09,0xb9,0x6d,0xcb,
 0x7b,0x1b,0xf9,0x32,0xaf,0x9d,0x6a,0xa5,0xb8,0x2d,0xfc,0x1d,0x08,0x53,0x03,0x90,
 0x4d,0x4e,0x84,0x99,0xe4,0xce,0xd9,0x91,0xdd,0xb6,0x85,0x48,0x8b,0x29,0x6e,0xac,
 0xcd,0xc1,0xf8,0x1e,0x73,0x43,0x69,0xc6,0xb5,0xbd,0xfd,0x39,0x63,0x20,0xd4,0x38,
 0x76,0x7d,0xb2,0xa7,0xcf,0xed,0x57,0xc5,0xf3,0x2c,0xbb,0x14,0x21,0x06,0x55,0x9b,
 0xe3,0xef,0x5e,0x31,0x4f,0x7f,0x5a,0xa4,0x0d,0x82,0x51,0x49,0x5f,0xba,0x58,0x1c,
 0x4a,0x16,0xd5,0x17,0xa8,0x92,0x24,0x1f,0x8c,0xff,0xd8,0xae,0x2e,0x01,0xd3,0xad,
 0x3b,0x4b,0xda,0x46,0xeb,0xc9,0xde,0x9a,0x8f,0x87,0xd7,0x3a,0x80,0x6f,0x2f,0xc8,
 0xb1,0xb4,0x37,0xf7,0x0a,0x22,0x13,0x28,0x7c,0xcc,0x3c,0x89,0xc7,0xc3,0x96,0x56,
 0x07,0xbf,0x7e,0xf0,0x0b,0x2b,0x97,0x52,0x35,0x41,0x79,0x61,0xa6,0x4c,0x10,0xfe,
 0xbc,0x26,0x95,0x88,0x8a,0xb0,0xa3,0xfb,0xc0,0x18,0x94,0xf2,0xe1,0xe5,0xe9,0x5d,
 0xd0,0xdc,0x11,0x66,0x64,0x5c,0xec,0x59,0x42,0x75,0x12,0xf5,0x74,0x9c,0xaa,0x23,
 0x0e,0x86,0xab,0xbe,0x2a,0x02,0xe7,0x67,0xe6,0x44,0xa2,0x6c,0xc2,0x93,0x9f,0xf1,
 0xf6,0xfa,0x36,0xd2,0x50,0x68,0x9e,0x62,0x71,0x15,0x3d,0xd6,0x40,0xc4,0xe2,0x0f,
 0x8e,0x83,0x77,0x6b,0x25,0x05,0x3f,0x0c,0x30,0xea,0x70,0xb7,0xa1,0xe8,0xa9,0x65,
 0x8d,0x27,0x1a,0xdb,0x81,0xb3,0xa0,0xf4,0x45,0x7a,0x19,0xdf,0xee,0x78,0x34,0x60
};

byte S1[256] = {
 0x55,0xc2,0x63,0x71,0x3b,0xc8,0x47,0x86,0x9f,0x3c,0xda,0x5b,0x29,0xaa,0xfd,0x77,
 0x8c,0xc5,0x94,0x0c,0xa6,0x1a,0x13,0x00,0xe3,0xa8,0x16,0x72,0x40,0xf9,0xf8,0x42,
 0x44,0x26,0x68,0x96,0x81,0xd9,0x45,0x3e,0x10,0x76,0xc6,0xa7,0x8b,0x39,0x43,0xe1,
 0x3a,0xb5,0x56,0x2a,0xc0,0x6d,0xb3,0x05,0x22,0x66,0xbf,0xdc,0x0b,0xfa,0x62,0x48,
 0xdd,0x20,0x11,0x06,0x36,0xc9,0xc1,0xcf,0xf6,0x27,0x52,0xbb,0x69,0xf5,0xd4,0x87,
 0x7f,0x84,0x4c,0xd2,0x9c,0x57,0xa4,0xbc,0x4f,0x9a,0xdf,0xfe,0xd6,0x8d,0x7a,0xeb,
 0x2b,0x53,0xd8,0x5c,0xa1,0x14,0x17,0xfb,0x23,0xd5,0x7d,0x30,0x67,0x73,0x08,0x09,
 0xee,0xb7,0x70,0x3f,0x61,0xb2,0x19,0x8e,0x4e,0xe5,0x4b,0x93,0x8f,0x5d,0xdb,0xa9,
 0xad,0xf1,0xae,0x2e,0xcb,0x0d,0xfc,0xf4,0x2d,0x46,0x6e,0x1d,0x97,0xe8,0xd1,0xe9,
 0x4d,0x37,0xa5,0x75,0x5e,0x83,0x9e,0xab,0x82,0x9d,0xb9,0x1c,0xe0,0xcd,0x49,0x89,
 0x01,0xb6,0xbd,0x58,0x24,0xa2,0x5f,0x38,0x78,0x99,0x15,0x90,0x50,0xb8,0x95,0xe4,
 0xd0,0x91,0xc7,0xce,0xed,0x0f,0xb4,0x6f,0xa0,0xcc,0xf0,0x02,0x4a,0x79,0xc3,0xde,
 0xa3,0xef,0xea,0x51,0xe6,0x6b,0x18,0xec,0x1b,0x2c,0x80,0xf7,0x74,0xe7,0xff,0x21,
 0x5a,0x6a,0x54,0x1e,0x41,0x31,0x92,0x35,0xc4,0x33,0x07,0x0a,0xba,0x7e,0x0e,0x34,
 0x88,0xb1,0x98,0x7c,0xf3,0x3d,0x60,0x6c,0x7b,0xca,0xd3,0x1f,0x32,0x65,0x04,0x28,
 0x64,0xbe,0x85,0x9b,0x2f,0x59,0x8a,0xd7,0xb0,0x25,0xac,0xaf,0x12,0x03,0xe2,0xf2
};

uint EK\_d[16] = {
 0x44D7, 0x26BC, 0x626B, 0x135E, 0x5789, 0x35E2, 0x7135, 0x09AF,
 0x4D78, 0x2F13, 0x6BC4, 0x1AF1, 0x5E26, 0x3C4D, 0x789A, 0x47AC
};
// c = a + b mod (2^31 – 1)
uint AddM(uint a, uint b)
{
 uint c = a + b;
 return (c & 0x7FFFFFFF) + (c >> 31);
}

#define MulByPow2(x, k) ((((x) << k) | ((x) >> (31 - k))) & 0x7FFFFFFF)

void LFSRWithInitialisationMode(uint u)
{
 uint f = LFSR[0];
 uint v = MulByPow2(LFSR[0], 8);
 f = AddM(f, v);
 v = MulByPow2(LFSR[4], 20);
 f = AddM(f, v);
 v = MulByPow2(LFSR[10], 21);
 f = AddM(f, v);
 v = MulByPow2(LFSR[13], 17);
 f = AddM(f, v);
 v = MulByPow2(LFSR[15], 15);
 f = AddM(f, v);
 f = AddM(f, u);
 for (int i = 0; i < 15; i++)
 LFSR[i] = LFSR[i + 1];
 LFSR[15] = f;
}

void LFSRWithWorkMode()
{
 uint f = LFSR[0];
 uint v = MulByPow2(LFSR[0], 8);
 f = AddM(f, v);
 v = MulByPow2(LFSR[4], 20);
 f = AddM(f, v);
 v = MulByPow2(LFSR[10], 21);
 f = AddM(f, v);
 v = MulByPow2(LFSR[13], 17);
 f = AddM(f, v);
 v = MulByPow2(LFSR[15], 15);
 f = AddM(f, v);
 for (int i = 0; i < 15; i++)
 LFSR[i] = LFSR[i + 1];
 LFSR[15] = f;
}

void BitReorganization()
{
 BRC[0] = ((LFSR[15] & 0x7FFF8000) << 1) | (LFSR[14] & 0xFFFF);
 BRC[1] = ((LFSR[11] & 0xFFFF) << 16) | (LFSR[9] >> 15);
 BRC[2] = ((LFSR[7] & 0xFFFF) << 16) | (LFSR[5] >> 15);
 BRC[3] = ((LFSR[2] & 0xFFFF) << 16) | (LFSR[0] >> 15);
}

#define ROT(a, k) (((a) << k) | ((a) >> (32 - k)))

uint L1(uint X)
{
 return (X ^ ROT(X, 2) ^ ROT(X, 10) ^ ROT(X, 18) ^ ROT(X, 24));
}

uint L2(uint X)
{
 return (X ^ ROT(X, 8) ^ ROT(X, 14) ^ ROT(X, 22) ^ ROT(X, 30));
}

#define MAKEU32(a, b, c, d) (((uint)(a) << 24) | ((uint)(b) << 16) | ((uint)(c) << 8) | ((uint)(d)))

uint F()
{
 uint W = (BRC[0] ^ F\_R1) + F\_R2;
 uint W1 = F\_R1 + BRC[1];
 uint W2 = F\_R2 ^ BRC[2];
 uint u = L1((W1 << 16) | (W2 >> 16));
 uint v = L2((W2 << 16) | (W1 >> 16));
 F\_R1 = MAKEU32(S0[u >> 24], S1[(u >> 16) & 0xFF], S0[(u >> 8) & 0xFF], S1[u & 0xFF]);
 F\_R2 = MAKEU32(S0[v >> 24], S1[(v >> 16) & 0xFF], S0[(v >> 8) & 0xFF], S1[v & 0xFF]);
 return W;
}

#define MAKEU31(a, b, c) (((uint)(a) << 23) | ((uint)(b) << 8) | (uint)(c))

void Initialization(byte\* k, byte\* iv)
{
 LFSR[0] = MAKEU31(k[0], EK\_d[0], iv[0]);
 LFSR[1] = MAKEU31(k[1], EK\_d[1], iv[1]);
 LFSR[2] = MAKEU31(k[2], EK\_d[2], iv[2]);
 LFSR[3] = MAKEU31(k[3], EK\_d[3], iv[3]);
 LFSR[4] = MAKEU31(k[4], EK\_d[4], iv[4]);
 LFSR[5] = MAKEU31(k[5], EK\_d[5], iv[5]);
 LFSR[6] = MAKEU31(k[6], EK\_d[6], iv[6]);
 LFSR[7] = MAKEU31(k[7], EK\_d[7], iv[7]);
 LFSR[8] = MAKEU31(k[8], EK\_d[8], iv[8]);
 LFSR[9] = MAKEU31(k[9], EK\_d[9], iv[9]);
 LFSR[10] = MAKEU31(k[10], EK\_d[10], iv[10]);
 LFSR[11] = MAKEU31(k[11], EK\_d[11], iv[11]);
 LFSR[12] = MAKEU31(k[12], EK\_d[12], iv[12]);
 LFSR[13] = MAKEU31(k[13], EK\_d[13], iv[13]);
 LFSR[14] = MAKEU31(k[14], EK\_d[14], iv[14]);
 LFSR[15] = MAKEU31(k[15], EK\_d[15], iv[15]);
 F\_R1 = 0;
 F\_R2 = 0;
 uint nCount = 32, w;
 while (nCount > 0)
 {
 BitReorganization();
 w = F();
 LFSRWithInitialisationMode(w >> 1);
 nCount--;
 }
}
void GenerateKeystream(uint\* pKeystream, int KeystreamLen)
{
 BitReorganization();
 F(); // discard the output of F
 LFSRWithWorkMode();

 for (int i = 0; i < KeystreamLen; i++)
 {
 BitReorganization();
 pKeystream[i] = F() ^ BRC[3];
 LFSRWithWorkMode();
 }
}

```

ראו גם
------

* צופן זרם
* GSM
* SNOW

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

1. ↑  Specification of the 3GPP Confidentiality and Integrity Algorithms 128-EEA3 & 128-EIA3. Document 2: ZUC Specification
2. ↑  The New LTE Cryptographic Algorithms EEA3 and EIA3
3. ↑  Differential Attacks Against Stream Cipher ZUC
4. ↑  The Stream Cipher Core of the 3GPP Encryption Standard 128-EEA3: Timing Attacks and Countermeasures
5. ↑  Linear Approximations of Addition Modulo 2^n-1
6. ↑  Differential Power Analysis on ZUC Algorithm

  


| קריפטוגרפיה |
| --- |
| 

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

 |
| 

| הצפנה קלאסית |
| --- |
| מכונת הצפנה • צופן החלפה • צופן אתב"ש • צופן קיסר • צופן ויז'נר • צופן ורנם • צופן פלייפייר • צופן היל • אולטרה • אניגמה • ציקלומטר • קולוסוס • PURPLE • ג'ייד • מג'יק • צופן שחלוף |

 |
| 

| צופן בלוקים |
| --- |
| לוציפר • AES • 3DES • DES • Threefish • Twofish • Blowfish • FEAL • SEED • CAST • IDEA • RC2 • RC6 • MARS • RC5 • GOST • סרפנט • MISTY • KASUMI • קמליה • ARIA • SAFER • TEA • LEA • CLEFIA • SEA • Hummingbird • PRESENT • KATAN • KeeLoq • Simon & Speck • אנוביס |

 |
| 

| אופני הפעלה |
| --- |
| אופן הפעלה של צופן בלוקים • EAX • OCB • IAPM • CWC mode • GCM • CCM |

 |
| 

| צופן זרם |
| --- |
| RC4 • Salsa20 • SOSEMANUK • גריין • E0 • A5/1 • A5/2 • A5/3 • A5/4 • MICKEY • HC-128 • SNOW • Trivium • Rabbit • ZUC • ChaCha |

 |
| 

| הצפנה אסימטרית |
| --- |
| פרוטוקול דיפי-הלמן • חידות מרקל • חתימת למפורט • הצפנת תרמיל • RSA • הצפנת רבין • חתימה דיגיטלית רבין • צופן אל-גמאל • חתימה דיגיטלית אל-גמאל • DSA • הצפנת בלום-גולדווסר • ECC • הצפנת קריימר-שופ • הצפנת פאיי • הצפנת מקאליס • GGH • NTRU • עקום 25519 • חתימה דיגיטלית של שנור • הצפנת אוקמוטו-אושיאמה |

 |
| 

| פרוטוקולים |
| --- |
| עץ מרקל • פרוטוקול אתגר-מענה • פרוטוקול נידהאם-שרודר • פרוטוקול קרברוס • הוכחה באפס ידע • פרוטוקול פייגה-פיאט-שמיר • העברה עלומה • חלוקת סוד • TLS (SSL) • Secure Shell • MQV • X.509 • פרוטוקול שיתוף מפתח
• מיסור שלא לפרסום • פרוטוקול סיגנל |

 |
| 

| פרימיטיבים תאורטיים |
| --- |
| מחולל פסבדו-אקראי קריפטוגרפי • פונקציה חד-כיוונית • תמורה חד-כיוונית • סיבית קשה • פונקציה פסבדו-אקראית קריפטוגרפית • תמורה פסאודו-אקראית • פונקציית גיבוב קריפטוגרפית • וקטור אתחול • פונקציית ספוג • הצפנה מבוססת סריג |

 |
| 

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

 |
| 

| בעיות מתמטיות ואלגוריתמים |
| --- |
| בעיית לוגריתם בדיד • תחשיב אינדקסים • נפה ריבועית • אלגוריתם rho של פולרד • נפת שדה מספרים • אלגוריתם רו של פולרד ללוגריתמים • אלגוריתם פוליג-הלמן |

 |
| 

| פונקציות גיבוב קריפטוגרפיות |
| --- |
| SHA • MD5 • MD4 • SHA-1 • SHA-2 • SHA-3 • RIPEMD • Skein • BLAKE • Grøstl • SipHash |

 |
| 

| אימות וזיהוי |
| --- |
| אימות זהות • סיסמה • קוד אימות מסרים • Poly1305 • סיסמה חד-פעמית |

 |
| 

| נושאים נלווים |
| --- |
| מספר אקראי • מספר ראשוני • יתירות • מפתח שיחה • סטגנוגרפיה • הצפנה קוונטית • הצפנה פוסט-קוונטית • עקרון קרקהופס • אבטחת מידע • קריפטוגרפיה ויזואלית • אליס ובוב • מסיבת חתימה על מפתחות ציבוריים • שידור מוצפן • הצפנת דיסקים • הצפנת סף • חתימה דיגיטלית מבוססת פונקציית גיבוב • פונקציה זניחה • רשת פייסטל • רשת החלפה-תמורה • הלבנה • אימות מסרים • חתימה עיוורת • חישוב רב משתתפים בטוח |

 |