**CLEFIA** הוא צופן בלוקים קנייני במבנה פייסטל שפותח על ידי סוני כחלק ממערכת ניהול זכויות דיגיטלי. שמו נגזר מהמילה הצרפתית *Clef* שפירושה "מפתח". הצופן מקבל בלוק קלט באורך 128 סיביות ומפתח הצפנה בשלושה אורכים אפשריים: 128, 192 או 256 סיביות ומחזיר בלוק מוצפן באורך 128 סיביות. CLEFIA הוצג לראשונה ב- FSE 2007 (סדנת הצפנה מהירה בתוכנה), הוצע כמועמד לתקן הצפנה עבור ממשלת יפן ב-CRYPTREC-2013, נחשב בטוח לשימוש ומציג ביצועים 'סטייט אוף דה ארט' בקטגוריה של צפנים קלי משקל. CLEFIA מוגן בזכויות יוצרים והשימוש בו כרוך ברישיון. הוא נמנה עם הצפנים שתוקננו על ידי תקן איזו 29192-2 בקטגוריה צופן בלוקים קל משקל.

תיאור כללי
----------

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

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

CLEFIA הוא צופן מאוזן היטב הן מהיבט של יעילות והן מהיבט של ביטחון. הוא משיג ביצועים גבוהים בחומרה, תפוקה של 1.60 Gbps (גיגה-בתים לשנייה) בקירוב עם פחות מ-6000 שערים, עם ספריית CMOS ASIC {\displaystyle 0.09\mu m}. בתוכנה הוא מגיע ל-13 מחזורי שעון לבית (cpb) או 1.48 Gbps על מעבד AMD אתלון 64 ביט. הביצועים הגבוהים בחומרה מציבים אותו כמתחרה ראוי עבור חומרה מוגבלת משאבים כמו RFID או סנסורים אלחוטיים זעירים.

פירוט מהלכי הצופן
-----------------

שלד פונקציות ההצפנה והפענוח בנוי משלושה מהלכים. המהלך הראשון והאחרון הם פעולות הלבנה והמהלך האמצעי כולל קריאה לפונקציה פנימית המבצעת r סבבים של פעולות החלפה ופיזור. מספר הסבבים משתנה בהתאם לאורך המפתח. עבור מפתח באורך 128 סיביות {\displaystyle r=18}, עבור מפתח 192 סיביות {\displaystyle r=22} ועבור מפתח 256 סיביות {\displaystyle r=26}.

### הצפנה

|  |  |  |
| --- | --- | --- |
| 1. **הלבנה**:
2. **הצפנה**:
3. **הלבנה**:
 |  |  :{\displaystyle T\_{0}|T\_{1}|T\_{2}|T\_{3}\leftarrow P\_{0}|(P\_{1}\oplus WK\_{0})|P\_{2}|(P\_{3}\oplus WK\_{1})},
{\displaystyle T\_{0}|T\_{1}|T\_{2}|T\_{3}\leftarrow {\text{GFN}}\_{4,r}(RK\_{0},...RK\_{2r-1},T\_{0},T\_{1},T\_{2},T\_{3})},
{\displaystyle C\_{0}|C\_{1}|C\_{2}|C\_{3}\leftarrow T\_{0}|(T\_{1}\oplus WK\_{2})|T\_{2}|(T\_{3}\oplus WK\_{3})}. |

### פענוח

|  |  |  |
| --- | --- | --- |
| 1. **הלבנה**:
2. **פענוח**:
3. **הלבנה**:
 |  |  :{\displaystyle T\_{0}|T\_{1}|T\_{2}|T\_{3}\leftarrow C\_{0}|(C\_{1}\oplus WK\_{2})|C\_{2}|(C\_{3}\oplus WK\_{3}))},
{\displaystyle T\_{0}|T\_{1}|T\_{2}|T\_{3}\leftarrow GFN\_{4,r}^{-1}(RK\_{0},...RK\_{2r-1},T\_{0},T\_{1},T\_{2},T\_{3}))},
{\displaystyle C\_{0}|C\_{1}|C\_{2}|C\_{3}\leftarrow T\_{0}|(T\_{1}\oplus WK\_{0})|T\_{2}|(T\_{3}\oplus WK\_{1}))}. |

### פונקציות עזר

פונקציית ההצפנה הפנימית הנקראת {\displaystyle {\text{GFN}}\_{d,r}} היא בסגנון רשת פייסטל כללית מסוג 2, כאשר d נקרא ענף המייצג את מספר המילים שהפונקציה מקבלת ו-r מייצג את מספר החזרות שהיא אמורה לבצע. פונקציית ההצפנה מנצלת שתי פונקציות פנימיות F0 ו-F1 המפורטות להלן שמקבלות קלט באורך 32 סיביות ומחזירות פלט באורך 32 סיביות. ביתר פירוט, הפונקציה {\displaystyle {\text{GFN}}\_{4,r}} מקבלת ארבע מילים באורך 32 סיביות כל אחת המסומנים {\displaystyle X\_{0}|...|X\_{d-1}} וכן {\displaystyle dr/2} מפתחות סבבים {\displaystyle RK\_{0}|...|RK\_{rd/2-1}} באורך 32 סיביות כל אחד ומחזירה ארבע מילים {\displaystyle Y\_{0}|...|Y\_{d-1}}. הסימן "{\displaystyle |}" משמש להפרדה בין המילים. לדוגמה אם נבחר מפתח באורך 128 סיביות, מספר הסבבים הוא 18 ולכן מספר תת-המפתחות הוא {\displaystyle 18\cdot 4/2=36}.

תיאור הפונקציה הפנימית בשתי גרסאות {\displaystyle {\text{GFN}}\_{4,r}} שמבוצעת בתהליך ההצפנה ו-{\displaystyle {\text{GFN}}\_{8,r}} לצורך הכנת תת-המפתחות במקרה שנבחר מפתח 192 או 256:


|  |  |
| --- | --- |
| {\displaystyle {\boldsymbol {\mathbf {GFN} \_{4,r}(RK\_{0},RK\_{1},...RK\_{2r-1},X\_{0},X\_{1},...X\_{7})}}}
{\displaystyle 1.\ \ T\_{0}|T\_{1}|T\_{2}|T\_{3}\leftarrow X\_{0}|X\_{1}|X\_{2}|X\_{3}}
{\displaystyle 2.\ \ {\text{For }}i=0{\text{ to }}r-1{\text{ do the following: }}}
{\displaystyle \ \ \ \ \ \ 2.1:\ T\_{1}\leftarrow T\_{1}\oplus \mathbf {F0} (RK\_{2i},T\_{0})},
{\displaystyle \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ T\_{3}\leftarrow T\_{3}\oplus \mathbf {F1} (RK\_{2i+1},T\_{2})},
{\displaystyle \ \ \ \ \ \ 2.2:\ T\_{0}|T\_{1}|T\_{2}|T\_{3}\leftarrow T\_{1}|T\_{2}|T\_{3}|T\_{0}},
{\displaystyle 3.\ \ Y\_{0}|Y\_{1}|Y\_{2}|Y\_{3}\leftarrow T\_{3}|T\_{0}|T\_{1}|T\_{2}} | {\displaystyle {\boldsymbol {\mathbf {GFN} \_{8,r}(RK\_{0},...RK\_{4r-1},X\_{0},...X\_{7})}}}
{\displaystyle 1.\ \ T\_{0}|T\_{1}|\cdots |T\_{7}\leftarrow X\_{0}|X\_{1}|\cdots |X\_{7}}
{\displaystyle 2.\ \ {\text{For }}i=0{\text{ to }}r-1{\text{ do the following:}}}
{\displaystyle \ \ \ \ \ \ \ 2.1\ \ T\_{1}\leftarrow T\_{1}\oplus \mathbf {F0} (RK\_{4i},T\_{0}),\ \ T\_{3}\leftarrow T\_{3}\oplus \mathbf {F1} (RK\_{4i+1},T\_{2})},
{\displaystyle \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ T\_{5}\leftarrow T\_{5}\oplus \mathbf {F0} (RK\_{4i+2},T\_{4}),\ \ T\_{7}\leftarrow T\_{7}\oplus \mathbf {F1} (RK\_{4i+3},T\_{6})},
{\displaystyle \ \ \ \ \ \ \ 2.2\ \ T\_{0}|T\_{1}|\cdots |T\_{6}jT\_{7}\leftarrow T\_{1}|T\_{2}|\cdots |T\_{7}|T\_{0}}
{\displaystyle 3.\ \ Y\_{0}|Y\_{1}|\cdots |Y\_{6}|Y\_{7}\leftarrow T\_{7}|T\_{0}|\cdots |T\_{5}|T\_{6}} |

לפונקציה {\displaystyle {\text{GFN}}\_{4,r}} קיימת פונקציה הופכית לצורך פענוח המסומנת {\displaystyle {\text{GFN}}\_{4,r}^{-1}}. את פונקציית הפענוח הפנימית מכינים מפונקציית ההצפנה על ידי שינוי סדר מפתחות הסבבים {\displaystyle RK\_{i}} מהסוף להתחלה וכן שינוי סדר ההחלפה בשלב 2.2 ל-{\displaystyle T\_{0}|T\_{1}|T\_{2}|T\_{3}\leftarrow T\_{3}|T\_{0}|T\_{1}|T\_{2}} וסדר ההחלפה בשלב 3 משתנה ל-{\displaystyle Y\_{0}|Y\_{1}|Y\_{2}|Y\_{3}\leftarrow T\_{1}|T\_{2}|T\_{3}|T\_{0}}.

הפונקציות {\displaystyle \mathbf {F0} } ו-{\displaystyle \mathbf {F1} } הן:


| F0 | F1 |
| --- | --- |
| {\displaystyle 1.\ \ T\leftarrow RK\oplus x}
{\displaystyle 2.\ \ {\text{Let }}T=T\_{0}|T\_{1}|T\_{2}|T\_{3},T\_{i}\in \{0,1\}^{8}}
{\displaystyle \ \ \ \ \ 2.1\ \ T\_{0}\leftarrow \mathbf {S0} (T\_{0}),T\_{1}\leftarrow \mathbf {S1} (T\_{1})},
{\displaystyle \ \ \ \ \ 2.2\ \ T\_{2}\leftarrow \mathbf {S0} (T\_{2}),T\_{3}\leftarrow \mathbf {S1} (T\_{3})},
{\displaystyle 3.\ \ {\text{Let }}y=y\_{0}|y\_{1}|y\_{2}|y\_{3},y\_{i}\in \{0,1\}^{8}}
{\displaystyle \ \ \ \ 3.1\ \ ^{t}(y\_{0},y\_{1},y\_{2},y\_{3})=M\_{0}\ \ ^{t}(T\_{0},T\_{1},T\_{2},T\_{3})} | {\displaystyle 1.\ \ T\leftarrow RK\oplus x}
{\displaystyle 2.\ \ {\text{Let }}T=T\_{0}|T\_{1}|T\_{2}|T\_{3},T\_{i}\in \{0,1\}^{8}}
{\displaystyle \ \ \ \ \ 2.1\ \ T\_{0}\leftarrow \mathbf {S1} (T\_{0}),T\_{1}\leftarrow \mathbf {S0} (T\_{1})},
{\displaystyle \ \ \ \ \ 2.2\ \ T\_{2}\leftarrow \mathbf {S1} (T\_{2}),T\_{3}\leftarrow \mathbf {S0} (T\_{3})},
{\displaystyle 3.\ \ {\text{Let }}y=y\_{0}|y\_{1}|y\_{2}|y\_{3},y\_{i}\in \{0,1\}^{8}}
{\displaystyle \ \ \ \ \ 3.1\ \ ^{t}(y\_{0},y\_{1},y\_{2},y\_{3})=M\_{1}\ ^{t}(T\_{0},T\_{1},T\_{2},T\_{3})} |

### תיבות ההחלפה S0 ו-S1

ישנם שני סוגי תיבות החלפה ב-CLEFIA האחד מבוסס על בחירה אקראית של ערכים עם תכונות סטטיסטיות טובות כמו ב-DES והשני מבוסס על פונקציה הופכית מעל השדה {\displaystyle GF(2^{8})} כמו ב-AES. הטבלאות הבאות מכילות את ערכי תיבות ההחלפה בבסיס הקסדצימלי כאשר עבור קלט בגודל בית אחד (8 סיביות), ארבע הסיביות המשמעותיות (הניבל העליון) משמשות כאינדקס לשורה המתאימה בטבלה ואילו ארבע הסיביות הפחות משעותיות (הניבל התחתון) משמשות כאינדקס לעמודה המתאימה:

| **S0** | **S1** |
| --- | --- |
| 
```
   0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
0. 57 49 d1 c6 2f 33 74 fb 95 6d 82 ea 0e b0 a8 1c
1. 28 d0 4b 92 5c ee 85 b1 c4 0a 76 3d 63 f9 17 af
2. bf a1 19 65 f7 7a 32 20 06 ce e4 83 9d 5b 4c d8
3. 42 5d 2e e8 d4 9b 0f 13 3c 89 67 c0 71 aa b6 f5
4. a4 be fd 8c 12 00 97 da 78 e1 cf 6b 39 43 55 26
5. 30 98 cc dd eb 54 b3 8f 4e 16 fa 22 a5 77 09 61
6. d6 2a 53 37 45 c1 6c ae ef 70 08 99 8b 1d f2 b4
7. e9 c7 9f 4a 31 25 fe 7c d3 a2 bd 56 14 88 60 0b
8. cd e2 34 50 9e dc 11 05 2b b7 a9 48 ff 66 8a 73
9. 03 75 86 f1 6a a7 40 c2 b9 2c db 1f 58 94 3e ed
a. fc 1b a0 04 b8 8d e6 59 62 93 35 7e ca 21 df 47
b. 15 f3 ba 7f a6 69 c8 4d 87 3b 9c 01 e0 de 24 52
c. 7b 0c 68 1e 80 b2 5a e7 ad d5 23 f4 46 3f 91 c9
d. 6e 84 72 bb 0d 18 d9 96 f0 5f 41 ac 27 c5 e3 3a
e. 81 6f 07 a3 79 f6 2d 38 1a 44 5e b5 d2 ec cb 90
f. 9a 36 e5 29 c3 4f ab 64 51 f8 10 d7 bc 02 7d 8e

```
 | 
```
   0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
0. 6c da c3 e9 4e 9d 0a 3d b8 36 b4 38 13 34 0c d9
1. bf 74 94 8f b7 9c e5 dc 9e 07 49 4f 98 2c b0 93
2. 12 eb cd b3 92 e7 41 60 e3 21 27 3b e6 19 d2 0e
3. 91 11 c7 3f 2a 8e a1 bc 2b c8 c5 0f 5b f3 87 8b
4. fb f5 de 20 c6 a7 84 ce d8 65 51 c9 a4 ef 43 53
5. 25 5d 9b 31 e8 3e 0d d7 80 ff 69 8a ba 0b 73 5c
6. 6e 54 15 62 f6 35 30 52 a3 16 d3 28 32 fa aa 5e
7. cf ea ed 78 33 58 09 7b 63 c0 c1 46 1e df a9 99
8. 55 04 c4 86 39 77 82 ec 40 18 90 97 59 dd 83 1f
9. 9a 37 06 24 64 7c a5 56 48 08 85 d0 61 26 ca 6f
a. 7e 6a b6 71 a0 70 05 d1 45 8c 23 1c f0 ee 89 ad
b. 7a 4b c2 2f db 5a 4d 76 67 17 2d f4 cb b1 4a a8
c. b5 22 47 3a d5 10 4c 72 cc 00 f9 e0 fd e2 fe ae
d. f8 5f ab f1 1b 42 81 d6 be 44 29 a6 57 b9 af f2
e. d4 75 66 bb 68 9f 50 02 01 3c 7f 8d 1a 88 bd ac
f. f7 e4 79 96 a2 fc 6d b2 6b 03 e1 2e 7d 14 95 1d

```
 |

את ההחלפה אפשר לבצע לפי הטבלאות האמורות או לחשבן תוך כדי ריצה במידה שהזיכרון מוגבל. שטח הזיכרון ששתי טבלאות מאכלסות הוא 512 בתים (4096 סיביות). את הכנת הטבלה S0 אפשר לבצע כך. מתחילים מטבלה המכילה 4 על 16 ערכים בגודל 4 סיביות (בסך הכול 256 סיביות):


|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| x | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f |
| SS0(x) | e | 6 | c | a | 8 | 7 | 2 | f | b | 1 | 4 | 0 | 5 | 9 | d | 3 |
| SS1(x) | 6 | 4 | 0 | d | 2 | b | a | 3 | 9 | c | e | f | 8 | 7 | 5 | 1 |
| SS2(x) | b | 8 | 5 | e | a | 6 | 4 | c | f | 7 | 2 | 3 | 1 | 0 | d | 9 |
| SS3(x) | a | 2 | 6 | d | 3 | 4 | 5 | e | 0 | 7 | 8 | 9 | b | f | c | 1 |

מחלקים את הקלט x לשני חצאים {\displaystyle x\_{0},x\_{1}} באורך 4 סיביות כל אחד ומחשבים:

|  |
| --- |
| 1. {\displaystyle t\_{0}=SS0(x\_{0}),t\_{1}=SS1(x\_{1})}
2. {\displaystyle u\_{0}=t\_{0}\oplus 2\cdot t\_{1},u1=2\cdot t\_{0}\oplus t\_{1}}
3. {\displaystyle y\_{0}=SS2(u\_{0}),y\_{1}=SS3(u\_{1})}
 |

התוצאה היא {\displaystyle y=(y\_{0},y\_{1})}.

את הטבלה S1 אפשר להכין על ידי הנוסחה הבאה: אם {\displaystyle f(x)\neq 0} אז {\displaystyle y=g(f(x)^{-1})} אחרת {\displaystyle y=g(0)}. הפונקציה ההופכית מבוצעת מעל השדה {\displaystyle GF(2^{8})} עם הפולינום הפרימיטיבי {\displaystyle z^{8}+z^{4}+z^{3}+z^{2}+1} והפונקציות f ו-g הן טרנספורמציות אפיניות מעל {\displaystyle GF(2)} (הכפלת וקטור הקלט במטריצה קבועה וחיבור עם וקטור קבוע):


| f | g |
| --- | --- |
| {\displaystyle \textstyle {\begin{pmatrix}y\_{0}\\y\_{1}\\y\_{2}\\y\_{3}\\y\_{4}\\y\_{5}\\y\_{6}\\y\_{7}\end{pmatrix}}={\begin{pmatrix}0&0&0&1&1&0&0&0\\0&1&0&1&0&0&0&1\\0&0&0&0&0&0&0&1\\0&0&0&0&0&1&1&0\\0&1&1&0&0&1&0&1\\0&1&0&1&1&1&0&0\\0&1&1&0&0&0&0&0\\1&0&0&0&0&0&0&1\end{pmatrix}}\cdot {\begin{pmatrix}x\_{0}\\x\_{1}\\x\_{2}\\x\_{3}\\x\_{4}\\x\_{5}\\x\_{6}\\x\_{7}\end{pmatrix}}+{\begin{pmatrix}0\\0\\0\\1\\1\\1\\1\\0\end{pmatrix}}} | {\displaystyle {\begin{pmatrix}y\_{0}\\y\_{1}\\y\_{2}\\y\_{3}\\y\_{4}\\y\_{5}\\y\_{6}\\y\_{7}\end{pmatrix}}={\begin{pmatrix}0&0&0&0&1&0&1&0\\0&1&0&0&0&0&0&1\\0&1&0&1&1&0&0&0\\0&0&1&0&0&0&0&0\\0&0&1&1&0&0&0&0\\0&0&0&0&0&0&1&0\\1&0&0&1&0&0&0&0\\0&1&0&0&0&1&0&0\end{pmatrix}}\cdot {\begin{pmatrix}x\_{0}\\x\_{1}\\x\_{2}\\x\_{3}\\x\_{4}\\x\_{5}\\x\_{6}\\x\_{7}\end{pmatrix}}+{\begin{pmatrix}0\\1\\1\\0\\1\\0\\0\\1\end{pmatrix}}} |

### מטריצות הפיזור M0 ו-M1

{\displaystyle M\_{0}={\begin{pmatrix}{\text{0x01}}&{\text{0x02}}&{\text{0x04}}&{\text{0x06}}\\{\text{0x02}}&{\text{0x01}}&{\text{0x06}}&{\text{0x04}}\\{\text{0x04}}&{\text{0x06}}&{\text{0x01}}&{\text{0x02}}\\{\text{0x06}}&{\text{0x04}}&{\text{0x02}}&{\text{0x01}}\end{pmatrix}},M1={\begin{pmatrix}{\text{0x01}}&{\text{0x08}}&{\text{0x02}}&{\text{0x0a}}\\{\text{0x08}}&{\text{0x01}}&{\text{0x0a}}&{\text{0x02}}\\{\text{0x02}}&{\text{0x0a}}&{\text{0x01}}&{\text{0x08}}\\{\text{0x0a}}&{\text{0x02}}&{\text{0x08}}&{\text{0x01}}\end{pmatrix}}}

הכפל של המטריצה בוקטור הקלט מתבצע מודולו פולינום אי פריק (פולינום פרימיטיבי) {\displaystyle x^{8}+x^{4}+x^{3}+x^{2}+1} מעל השדה {\displaystyle GF(2^{8})} ובבסיס הקסדצימלי הוא {\displaystyle {\text{0x11d}}}. דרך יעילה במחשב לבצע את הכפל היא רקורסיה של הכפלה בפולינום 'x' ({\displaystyle {\text{0x02}}}) ששקולה להזזה (shift) של הקלט שמאלה סיבית אחת בתנאי אחד; אם מתרחשת גלישה (אם הסיבית המשמעותית ביותר הייתה '1' לפני ההזזה) יש לבצע חיסור (XOR) עם הפולינום הפרימיטיבי האמור (נקרא *צמצום מודולרי*). אם נתונה פונקציה {\displaystyle {\text{MUL2}}(a)} שמבצעת את הכפל האמור אז אפשר להכפיל את a בכל מספר, למשל {\displaystyle {\text{MUL4}}(a)={\text{MUL2}}({\text{MUL2}}(a))} או {\displaystyle {\text{MUL6}}(a)={\text{MUL2}}(a)\oplus ({\text{MUL4}}(a)}. להסבר נוסף על אריתמטיקה של פולינומים מעל שדה בינארי מורחב ראה צופן ריינדל.

### הכנת מפתחות הסבבים

תהליך הכנת המפתחות תומך בשלושה מפתחות שונים: 128 סיביות, 192 סיביות או 256 סיביות. התהליך כולל הכנת {\displaystyle 2r} מפתחות סבבים {\displaystyle RK\_{j}} וארבעה מפתחות הלבנה {\displaystyle WK\_{i}}. והוא כולל פונקציית החלפה הנקראת DoubleSwap המקבלת קלט באורך 128 סיביות ומבצעת החלפה של סיביות לפי הכלל הבא:

{\displaystyle Y=X[7-63]\ \ \ |\ \ \ X[121-127]\ \ \ |\ \ \ X[0-6]\ \ \ |\ \ \ X[64-120]} ,
כאשר {\displaystyle X[a-b]} פירושו תת-מחרוזת של X המתחילה בפוזיציה a ומסתיימת בפוזיציה b.

בנוסף תהליך ההכנה עושה שימוש ב-n קבועים {\displaystyle CON\_{0}^{k},...CON\_{n-1}^{k}} כאשר {\displaystyle k\in \{128,192,256\}}. מספר הקבועים הדרוש תלוי באורך המפתח שנבחר על ידי המשתמש. הקבועים הללו משמשים כמפתחות הצפנה לפונקציה {\displaystyle {\text{GFN}}\_{4,12}} או {\displaystyle {\text{GFN}}\_{8,10}} (המתוארת לעיל) כשהתוצאה מוצבת במערך זמני L.

אם המפתח K שנבחר על ידי המשתמש באורך 128 סיביות מבצעים כדלהלן:

|  |
| --- |
| 1. {\displaystyle L\leftarrow {\text{GFN}}\_{4,12}(CON\_{0}^{(128)},...CON\_{23}^{(128)},K\_{0},...K\_{3})}
2. {\displaystyle WK\_{0}|WK\_{1}|WK\_{2}|WK\_{3}\leftarrow K}
3. {\displaystyle {\text{For }}i=0{\text{ to }}8{\text{ do the following:}}}
{\displaystyle \ \ \ \ \ T\leftarrow L\oplus (CON\_{24+4i}^{(128)}|CON\_{24+4i+1}^{(128)}|CON\_{24+4i+2}^{(128)}|CON\_{24+4i+3)}^{(128)}}
{\displaystyle \ \ \ \ \ L\leftarrow {\text{DoubleSwap}}(L)}
{\displaystyle \ \ \ \ \ {\text{If }}i{\text{ is odd: }}T\leftarrow T\oplus K}
{\displaystyle \ \ \ \ \ RK\_{4i}|RK\_{4i+1}|RK\_{4i+2}|RK\_{4i+3}\leftarrow T}
 |

להכנת מפתחות הסבבים במקרה של מפתח מאסטר 192 או 256, תחילה מכינים שני משתנים {\displaystyle K\_{L},K\_{R}} בהם מציבים את המפתח K. לאחר מכן מחשבים שני משתנים נוספים {\displaystyle L\_{L},L\_{R}} על ידי הפונקציה {\displaystyle {\text{GFN}}\_{8,10}}. מתוך ארבעת המשתנים שהתקבלו מכינים את כל {\displaystyle RK\_{i}} מפתחות הסבבים ואת כל {\displaystyle WK\_{i}} מפתחות ההלבנה כדלקמן.

הכנת המשתנים {\displaystyle L\_{L},L\_{R}} מתוך {\displaystyle K\_{L},K\_{R}} עבור מפתח באורך k סיביות כאשר {\displaystyle k=192} או {\displaystyle k=256}:

|  |
| --- |
| {\displaystyle 1.\ \ {\text{Set }}k=192{\text{ or }}k=256}
{\displaystyle 2.\ \ {\text{If }}k=192{\text{ then }}K\_{L}\leftarrow K\_{0}|K\_{1}|K\_{2}|K\_{3},K\_{R}\leftarrow K\_{4}|K\_{5}|{\overline {K\_{0}}}|{\overline {K\_{1}}}}
{\displaystyle \ \ \ \ \ \ {\text{else if }}k=256{\text{ then }}K\_{L}\leftarrow K\_{0}|K\_{1}|K\_{2}|K\_{3},K\_{R}\leftarrow K\_{4}|K\_{5}|K\_{6}|K\_{7}}
{\displaystyle 3.\ \ {\text{Let }}K\_{L}=K\_{L0}|K\_{L1}|K\_{L2}|K\_{L3},K\_{R}=K\_{R0}|K\_{R1}|K\_{R2}|K\_{R3}}
{\displaystyle \ \ \ \ 3.1\ \ \ L\_{L}|L\_{R}\leftarrow }
{\displaystyle \ \ \ \ \ \ \ \ \ \mathbf {GFN} \_{8,10}(CON\_{0}^{(k)},...CON\_{39}^{(k)},K\_{L0},...K\_{L3},K\_{R0},...K\_{R3})} |

הרחבת המשתנים {\displaystyle K\_{L},K\_{R},L\_{L},L\_{R}} עבור מפתח באורך k סיביות כאשר {\displaystyle k=192} או {\displaystyle k=256}:

|  |
| --- |
| {\displaystyle 4.\ \ WK\_{0}|WK\_{1}|WK\_{2}|WK\_{3}\leftarrow K\_{L}\oplus K\_{R}}
{\displaystyle 5.\ \ {\text{For }}i=0{\text{ to }}10{\text{ (if }}k=192),{\text{ or }}12{\text{ (if }}k=256){\text{ do the following:}}}
{\displaystyle \ \ \ \ \ \ {\text{If }}(i{\text{ mod }}4)=0{\text{ or }}1{\text{ then:}}}
{\displaystyle \ \ \ \ \ \ \ \ \ T\leftarrow L\_{L}\oplus (CON\_{40+4i}^{(k)}|CON\_{40+4i+1}^{(k)}|CON\_{40+4i+2}^{(k)}|CON\_{40+4i+3}^{(k)})}
{\displaystyle \ \ \ \ \ \ \ \ \ L\_{L}\leftarrow {\text{DoubleSwap}}(L\_{L})}
{\displaystyle \ \ \ \ \ \ \ \ \ {\text{if }}i{\text{ is odd then: }}T\leftarrow T\oplus K\_{R}}
{\displaystyle \ \ \ \ \ \ {\text{else: }}}
{\displaystyle \ \ \ \ \ \ \ \ \ T\leftarrow L\_{R}\oplus (CON\_{40+4i}^{(k)}|CON\_{40+4i+1}^{(k)}|CON\_{40+4i+2}^{(k)}|CON\_{40+4i+3}^{(k)})}
{\displaystyle \ \ \ \ \ \ \ \ \ L\_{R}\leftarrow {\text{DoubleSwap}}(L\_{R})}
{\displaystyle \ \ \ \ \ \ \ \ \ {\text{if }}i{\text{ is odd then: }}T\leftarrow T\oplus K\_{L}}
{\displaystyle \ \ \ \ \ \ RK\_{4i}|RK\_{4i+1}|RK\_{4i+2}|RK\_{4i+3}\leftarrow T} |

### הקבועים להכנת המפתחות

הקבועים {\displaystyle CON\_{i}^{(k)}} כאשר {\displaystyle k\in \{128,192,256\}} מכילים בסך הכול 60, 84 או 92 ערכים באורך 32 סיביות בהתאם לאורך המפתח. את הקבועים אפשר להכין בזמן ריצה או להשתמש בטבלאות מוכנות מראש אם זיכרון זמין.

להכנת הקבועים תחילה מציבים את {\displaystyle P=(e-2)\cdot 2^{16}}, {\displaystyle Q=(\pi -3)\cdot 2^{16}}. אילו הם 16 הספרות הבינאריות הראשונות של חלק השבר של הלוגריתם הטבעי ופאי (בבסיס הקסדצימלי: {\displaystyle {\text{0xb7e1}},{\text{0x243f}}} בהתאמה). לאחר מכן מבצעים {\displaystyle \ell ^{(k)}} פעמים:

|  |
| --- |
| {\displaystyle 1.\ T\_{0}=IV^{(k)}}
{\displaystyle 2.\ {\text{For }}i=0{\text{ to }}\ell ^{(k)}-1{\text{ do: }}}
{\displaystyle \ \ \ \ \ 2.1\ \ CON\_{2i}^{(k)}\leftarrow (T\_{i}\oplus P)|({\overline {T\_{i}}}\lll 1),}
{\displaystyle \ \ \ \ \ 2.2\ \ CON\_{2i+1}^{(k)}\leftarrow ({\overline {T\_{i}}}\oplus Q)|(T\_{i}\lll 8),}
{\displaystyle \ \ \ \ \ 2.3\ \ T\_{i+1}\leftarrow T\_{i}\cdot {\text{0x0002}}^{-1}} |

הסימן {\displaystyle {\overline {T}}} פירושו אופרטור השלילה. הכפל האחרון (שורה 2.3) מתבצע מעל השדה {\displaystyle GF(2^{16})} מודולו הפולינום האי פריק {\displaystyle z^{16}+z^{15}+z^{13}+z^{11}+z^{5}+z^{4}+1} או {\displaystyle {\text{0x1a831}}}. למשל {\displaystyle {\text{0x428a}}\cdot {\text{0x0002}}^{-1}\equiv {\text{0x2145}}}. בפועל הכפל הזה מבוצע על ידי סדרה של ארבע הזזות ברמה של בתים ושני XOR בלבד. הפעולה מומחשת בפסאודו קוד הבא כאשר המשתנה T המחולק לשני בתים מוכפל ב-{\displaystyle {\text{0x0002}}^{-1}} מודולו {\displaystyle z^{16}+z^{15}+z^{13}+z^{11}+z^{5}+z^{4}+1}:

|  |
| --- |
| {\displaystyle {\text{If }}T{\text{ is Odd }}{\text{ then: }}T\_{0}=T\_{0}\oplus {\text{0xa8}},T\_{1}=T\_{1}\oplus {\text{0x30}}}
{\displaystyle tmp=T\_{0}\ll 7,T\_{0}=(T\_{0}\gg 1)\ \ |\ \ (T\_{1}\ll 7),T\_{1}=(T\_{1}\gg 1)\ \ |\ \ tmp} |

וקטורי האתחול עבור כל המפתחות, מספר הקבועים ומספר הסבבים {\displaystyle \ell ^{(k)}} מוצגים בטבלה הבאה:

| מפתח {\displaystyle (k)} | מספר הקבועים | מספר הסבבים {\displaystyle \ell ^{(k)}} | וקטור אתחול {\displaystyle IV^{(k)}} |
| --- | --- | --- | --- |
| 128 | 60 | 30 | 0x428a |
| 192 | 84 | 42 | 0x7137 |
| 256 | 92 | 46 | 0xb5c0 |

וקטורי האתחול הם 16 הספרות הבינאריות הראשונות של חלק השבר של שורש ממעלה שלישית של 2, 3 ו-5 בהתאמה.

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

CLEFIA הוא צופן חדש יחסית עם מעט קריפטואנליזה ידועה, בעיקר וריאציות של קריפטואנליזה דיפרנציאלית. ההתקפה הטובה ביותר נגד הצופן היא התקפת "דיפרנציאלים בלתי סבירים" שמצריכה {\displaystyle 2^{126.83}} טקסטים נבחרים נגד 13 סבבים בסיבוכיות של {\displaystyle 2^{126.83}} הצפנות עם מפתח 128 סיביות. התקפה דומה ישימה נגד הצופן עם 14 ו-15 סבבים עם מפתחות 192 ו-256 בהתאמה. התקפה נוספת היא התקפת "דיפרנציאלים בלתי אפשריים" היעילה נגד CLEFIA-192/256 עם 11 סבבים בסיבוכיות של {\displaystyle 2^{103.1}} טקסטים נבחרים ו-{\displaystyle 2^{103.1}} הצפנות. נגד 12 סבבים של CLEFIA-128 ההתקפה מגיעה לסיבוכיות זמן ומקום של {\displaystyle 2^{119.1}}. ונגד CLEFIA-192/256 בסיבוכיות של {\displaystyle 2^{181}} עם 13 סבבים. עם 14 סבבים הסיבוכיות מגיעה ל-{\displaystyle 2^{254.4}} הצפנות. אילו בעיקרון התקפות תאורטיות שאינן מסכנות את השימוש באלגוריתם באופן מעשי.

קוד לדוגמה של CLEFIA 256
------------------------

```
const unsigned char clefia\_s0[256] = { /\* S0 (8-bit S-box based on four 4-bit S-boxes) \*/
 0x57U, 0x49U, 0xd1U, 0xc6U, 0x2fU, 0x33U, 0x74U, 0xfbU, 0x95U, 0x6dU, 0x82U, 0xeaU, 0x0eU, 0xb0U, 0xa8U, 0x1cU,
 0x28U, 0xd0U, 0x4bU, 0x92U, 0x5cU, 0xeeU, 0x85U, 0xb1U, 0xc4U, 0x0aU, 0x76U, 0x3dU, 0x63U, 0xf9U, 0x17U, 0xafU,
 0xbfU, 0xa1U, 0x19U, 0x65U, 0xf7U, 0x7aU, 0x32U, 0x20U, 0x06U, 0xceU, 0xe4U, 0x83U, 0x9dU, 0x5bU, 0x4cU, 0xd8U,
 0x42U, 0x5dU, 0x2eU, 0xe8U, 0xd4U, 0x9bU, 0x0fU, 0x13U, 0x3cU, 0x89U, 0x67U, 0xc0U, 0x71U, 0xaaU, 0xb6U, 0xf5U,
 0xa4U, 0xbeU, 0xfdU, 0x8cU, 0x12U, 0x00U, 0x97U, 0xdaU, 0x78U, 0xe1U, 0xcfU, 0x6bU, 0x39U, 0x43U, 0x55U, 0x26U,
 0x30U, 0x98U, 0xccU, 0xddU, 0xebU, 0x54U, 0xb3U, 0x8fU, 0x4eU, 0x16U, 0xfaU, 0x22U, 0xa5U, 0x77U, 0x09U, 0x61U,
 0xd6U, 0x2aU, 0x53U, 0x37U, 0x45U, 0xc1U, 0x6cU, 0xaeU, 0xefU, 0x70U, 0x08U, 0x99U, 0x8bU, 0x1dU, 0xf2U, 0xb4U,
 0xe9U, 0xc7U, 0x9fU, 0x4aU, 0x31U, 0x25U, 0xfeU, 0x7cU, 0xd3U, 0xa2U, 0xbdU, 0x56U, 0x14U, 0x88U, 0x60U, 0x0bU,
 0xcdU, 0xe2U, 0x34U, 0x50U, 0x9eU, 0xdcU, 0x11U, 0x05U, 0x2bU, 0xb7U, 0xa9U, 0x48U, 0xffU, 0x66U, 0x8aU, 0x73U,
 0x03U, 0x75U, 0x86U, 0xf1U, 0x6aU, 0xa7U, 0x40U, 0xc2U, 0xb9U, 0x2cU, 0xdbU, 0x1fU, 0x58U, 0x94U, 0x3eU, 0xedU,
 0xfcU, 0x1bU, 0xa0U, 0x04U, 0xb8U, 0x8dU, 0xe6U, 0x59U, 0x62U, 0x93U, 0x35U, 0x7eU, 0xcaU, 0x21U, 0xdfU, 0x47U,
 0x15U, 0xf3U, 0xbaU, 0x7fU, 0xa6U, 0x69U, 0xc8U, 0x4dU, 0x87U, 0x3bU, 0x9cU, 0x01U, 0xe0U, 0xdeU, 0x24U, 0x52U,
 0x7bU, 0x0cU, 0x68U, 0x1eU, 0x80U, 0xb2U, 0x5aU, 0xe7U, 0xadU, 0xd5U, 0x23U, 0xf4U, 0x46U, 0x3fU, 0x91U, 0xc9U,
 0x6eU, 0x84U, 0x72U, 0xbbU, 0x0dU, 0x18U, 0xd9U, 0x96U, 0xf0U, 0x5fU, 0x41U, 0xacU, 0x27U, 0xc5U, 0xe3U, 0x3aU,
 0x81U, 0x6fU, 0x07U, 0xa3U, 0x79U, 0xf6U, 0x2dU, 0x38U, 0x1aU, 0x44U, 0x5eU, 0xb5U, 0xd2U, 0xecU, 0xcbU, 0x90U,
 0x9aU, 0x36U, 0xe5U, 0x29U, 0xc3U, 0x4fU, 0xabU, 0x64U, 0x51U, 0xf8U, 0x10U, 0xd7U, 0xbcU, 0x02U, 0x7dU, 0x8eU
};

const unsigned char clefia\_s1[256] = { /\* S1 (8-bit S-box based on inverse function) \*/
 0x6cU, 0xdaU, 0xc3U, 0xe9U, 0x4eU, 0x9dU, 0x0aU, 0x3dU, 0xb8U, 0x36U, 0xb4U, 0x38U, 0x13U, 0x34U, 0x0cU, 0xd9U,
 0xbfU, 0x74U, 0x94U, 0x8fU, 0xb7U, 0x9cU, 0xe5U, 0xdcU, 0x9eU, 0x07U, 0x49U, 0x4fU, 0x98U, 0x2cU, 0xb0U, 0x93U,
 0x12U, 0xebU, 0xcdU, 0xb3U, 0x92U, 0xe7U, 0x41U, 0x60U, 0xe3U, 0x21U, 0x27U, 0x3bU, 0xe6U, 0x19U, 0xd2U, 0x0eU,
 0x91U, 0x11U, 0xc7U, 0x3fU, 0x2aU, 0x8eU, 0xa1U, 0xbcU, 0x2bU, 0xc8U, 0xc5U, 0x0fU, 0x5bU, 0xf3U, 0x87U, 0x8bU,
 0xfbU, 0xf5U, 0xdeU, 0x20U, 0xc6U, 0xa7U, 0x84U, 0xceU, 0xd8U, 0x65U, 0x51U, 0xc9U, 0xa4U, 0xefU, 0x43U, 0x53U,
 0x25U, 0x5dU, 0x9bU, 0x31U, 0xe8U, 0x3eU, 0x0dU, 0xd7U, 0x80U, 0xffU, 0x69U, 0x8aU, 0xbaU, 0x0bU, 0x73U, 0x5cU,
 0x6eU, 0x54U, 0x15U, 0x62U, 0xf6U, 0x35U, 0x30U, 0x52U, 0xa3U, 0x16U, 0xd3U, 0x28U, 0x32U, 0xfaU, 0xaaU, 0x5eU,
 0xcfU, 0xeaU, 0xedU, 0x78U, 0x33U, 0x58U, 0x09U, 0x7bU, 0x63U, 0xc0U, 0xc1U, 0x46U, 0x1eU, 0xdfU, 0xa9U, 0x99U,
 0x55U, 0x04U, 0xc4U, 0x86U, 0x39U, 0x77U, 0x82U, 0xecU, 0x40U, 0x18U, 0x90U, 0x97U, 0x59U, 0xddU, 0x83U, 0x1fU,
 0x9aU, 0x37U, 0x06U, 0x24U, 0x64U, 0x7cU, 0xa5U, 0x56U, 0x48U, 0x08U, 0x85U, 0xd0U, 0x61U, 0x26U, 0xcaU, 0x6fU,
 0x7eU, 0x6aU, 0xb6U, 0x71U, 0xa0U, 0x70U, 0x05U, 0xd1U, 0x45U, 0x8cU, 0x23U, 0x1cU, 0xf0U, 0xeeU, 0x89U, 0xadU,
 0x7aU, 0x4bU, 0xc2U, 0x2fU, 0xdbU, 0x5aU, 0x4dU, 0x76U, 0x67U, 0x17U, 0x2dU, 0xf4U, 0xcbU, 0xb1U, 0x4aU, 0xa8U,
 0xb5U, 0x22U, 0x47U, 0x3aU, 0xd5U, 0x10U, 0x4cU, 0x72U, 0xccU, 0x00U, 0xf9U, 0xe0U, 0xfdU, 0xe2U, 0xfeU, 0xaeU,
 0xf8U, 0x5fU, 0xabU, 0xf1U, 0x1bU, 0x42U, 0x81U, 0xd6U, 0xbeU, 0x44U, 0x29U, 0xa6U, 0x57U, 0xb9U, 0xafU, 0xf2U,
 0xd4U, 0x75U, 0x66U, 0xbbU, 0x68U, 0x9fU, 0x50U, 0x02U, 0x01U, 0x3cU, 0x7fU, 0x8dU, 0x1aU, 0x88U, 0xbdU, 0xacU,
 0xf7U, 0xe4U, 0x79U, 0x96U, 0xa2U, 0xfcU, 0x6dU, 0xb2U, 0x6bU, 0x03U, 0xe1U, 0x2eU, 0x7dU, 0x14U, 0x95U, 0x1dU
};

void ByteXor(unsigned char \*dst, const unsigned char \*a, const unsigned char \*b, int bytelen)
{
 while (bytelen-- > 0) {
 \*dst++ = \*a++ ^ \*b++;
 }
}

unsigned char ClefiaMul2(unsigned char x)
{
 if (x & 0x80U) x ^= 0x0eU; // multiplication over GF(2^8) (p(x) = '11d')
 return ((x << 1) | (x >> 7));
}

#define ClefiaMul4(\_x) (ClefiaMul2(ClefiaMul2((\_x))))
#define ClefiaMul6(\_x) (ClefiaMul2((\_x)) ^ ClefiaMul4((\_x)))
#define ClefiaMul8(\_x) (ClefiaMul2(ClefiaMul4((\_x))))
#define ClefiaMulA(\_x) (ClefiaMul2((\_x)) ^ ClefiaMul8((\_x)))

void ClefiaF0Xor(unsigned char \*dst, const unsigned char \*src, const unsigned char \*rk)
{
 unsigned char x[4], y[4], z[4];
 /\* Key addition \*/
 ByteXor(x, src, rk, 4);
 /\* Substitution layer \*/
 z[0] = clefia\_s0[x[0]];
 z[1] = clefia\_s1[x[1]];
 z[2] = clefia\_s0[x[2]];
 z[3] = clefia\_s1[x[3]];
 /\* Diffusion layer (M0) \*/
 y[0] = z[0] ^ ClefiaMul2(z[1]) ^ ClefiaMul4(z[2]) ^ ClefiaMul6(z[3]);
 y[1] = ClefiaMul2(z[0]) ^ z[1] ^ ClefiaMul6(z[2]) ^ ClefiaMul4(z[3]);
 y[2] = ClefiaMul4(z[0]) ^ ClefiaMul6(z[1]) ^ z[2] ^ ClefiaMul2(z[3]);
 y[3] = ClefiaMul6(z[0]) ^ ClefiaMul4(z[1]) ^ ClefiaMul2(z[2]) ^ z[3];
 /\* Xoring after F0 \*/
 memcpy(dst + 0, src + 0, 4);
 ByteXor(dst + 4, src + 4, y, 4);
}

void ClefiaF1Xor(unsigned char \*dst, const unsigned char \*src, const unsigned char \*rk)
{
 unsigned char x[4], y[4], z[4];
 /\* Key addition \*/
 ByteXor(x, src, rk, 4);
 /\* Substitution layer \*/
 z[0] = clefia\_s1[x[0]];
 z[1] = clefia\_s0[x[1]];
 z[2] = clefia\_s1[x[2]];
 z[3] = clefia\_s0[x[3]];
 /\* Diffusion layer (M1) \*/
 y[0] = z[0] ^ ClefiaMul8(z[1]) ^ ClefiaMul2(z[2]) ^ ClefiaMulA(z[3]);
 y[1] = ClefiaMul8(z[0]) ^ z[1] ^ ClefiaMulA(z[2]) ^ ClefiaMul2(z[3]);
 y[2] = ClefiaMul2(z[0]) ^ ClefiaMulA(z[1]) ^ z[2] ^ ClefiaMul8(z[3]);
 y[3] = ClefiaMulA(z[0]) ^ ClefiaMul2(z[1]) ^ ClefiaMul8(z[2]) ^ z[3];
 /\* Xoring after F1 \*/
 memcpy(dst + 0, src + 0, 4);
 ByteXor(dst + 4, src + 4, y, 4);
}

void ClefiaGfn4(unsigned char \*y, const unsigned char \*x, const unsigned char \*rk, int r)
{
 unsigned char fin[16], fout[16];

 memcpy(fin, x, 16);
 while (r-- > 0) {
 ClefiaF0Xor(fout + 0, fin + 0, rk + 0);
 ClefiaF1Xor(fout + 8, fin + 8, rk + 4);
 rk += 8;
 if (r) { /\* swapping for encryption \*/
 memcpy(fin + 0, fout + 4, 12);
 memcpy(fin + 12, fout + 0, 4);
 }
 }
 memcpy(y, fout, 16);
}

void ClefiaGfn8(unsigned char \*y, const unsigned char \*x, const unsigned char \*rk, int r)
{
 unsigned char fin[32], fout[32];

 memcpy(fin, x, 32);
 while (r-- > 0) {
 ClefiaF0Xor(fout + 0, fin + 0, rk + 0);
 ClefiaF1Xor(fout + 8, fin + 8, rk + 4);
 ClefiaF0Xor(fout + 16, fin + 16, rk + 8);
 ClefiaF1Xor(fout + 24, fin + 24, rk + 12);
 rk += 16;
 if (r) { /\* swapping for encryption \*/
 memcpy(fin + 0, fout + 4, 28);
 memcpy(fin + 28, fout + 0, 4);
 }
 }
 memcpy(y, fout, 32);
}

void ClefiaGfn4Inv(unsigned char \*y, const unsigned char \*x, const unsigned char \*rk, int r)
{
 unsigned char fin[16], fout[16];

 rk += (r - 1) \* 8;
 memcpy(fin, x, 16);
 while (r-- > 0) {
 ClefiaF0Xor(fout + 0, fin + 0, rk + 0);
 ClefiaF1Xor(fout + 8, fin + 8, rk + 4);
 rk -= 8;
 if (r) { /\* swapping for decryption \*/
 memcpy(fin + 0, fout + 12, 4);
 memcpy(fin + 4, fout + 0, 12);
 }
 }
 memcpy(y, fout, 16);
}

void ClefiaDoubleSwap(unsigned char \*lk)
{
 unsigned char t[16];
 t[0] = (lk[0] << 7) | (lk[1] >> 1), t[1] = (lk[1] << 7) | (lk[2] >> 1);
 t[2] = (lk[2] << 7) | (lk[3] >> 1), t[3] = (lk[3] << 7) | (lk[4] >> 1);
 t[4] = (lk[4] << 7) | (lk[5] >> 1), t[5] = (lk[5] << 7) | (lk[6] >> 1);
 t[6] = (lk[6] << 7) | (lk[7] >> 1), t[7] = (lk[7] << 7) | (lk[15] & 0x7fU);

 t[8] = (lk[8] >> 7) | (lk[0] & 0xfeU), t[9] = (lk[9] >> 7) | (lk[8] << 1);
 t[10] = (lk[10] >> 7) | (lk[9] << 1), t[11] = (lk[11] >> 7) | (lk[10] << 1);
 t[12] = (lk[12] >> 7) | (lk[11] << 1), t[13] = (lk[13] >> 7) | (lk[12] << 1);
 t[14] = (lk[14] >> 7) | (lk[13] << 1), t[15] = (lk[15] >> 7) | (lk[14] << 1);
 memcpy(lk, t, 16);
}

void ClefiaConSet(unsigned char \*con, const unsigned char \*iv, int lk)
{
 unsigned char t[2];
 unsigned char tmp;
 memcpy(t, iv, 2);
 while (lk-- > 0) {
 con[0] = t[0] ^ 0xb7U; /\* P\_16 = 0xb7e1 (natural logarithm) \*/
 con[1] = t[1] ^ 0xe1U;
 con[2] = ~((t[0] << 1) | (t[1] >> 7));
 con[3] = ~((t[1] << 1) | (t[0] >> 7));
 con[4] = ~t[0] ^ 0x24U; /\* Q\_16 = 0x243f (circle ratio) \*/
 con[5] = ~t[1] ^ 0x3fU;
 con[6] = t[1];
 con[7] = t[0];
 con += 8;

 /\* updating T \*/
 if (t[1] & 0x01U) {
 t[0] ^= 0xa8U;
 t[1] ^= 0x30U;
 }
 tmp = t[0] << 7;
 t[0] = (t[0] >> 1) | (t[1] << 7);
 t[1] = (t[1] >> 1) | tmp;
 }
}

void ClefiaKeySet256(unsigned char \*rk, const unsigned char \*skey)
{
 const unsigned char iv[2] = { 0xb5, 0xc0U }; /\* cubic root of 5 \*/
 unsigned char lk[32];
 unsigned char con256[4 \* 92];
 int i;
 /\* generating CONi^(256) (0 <= i < 92, lk = 46) \*/
 ClefiaConSet(con256, iv, 46);
 /\* GFN\_{8,10} (generating L from K) \*/
 ClefiaGfn8(lk, skey, con256, 10);

 ByteXor(rk, skey, skey + 16, 8); /\* initial whitening key (WK0, WK1) \*/
 rk += 8;
 for (i = 0; i < 13; i++) { /\* round key (RKi (0 <= i < 52)) \*/
 if ((i / 2) % 2) {
 ByteXor(rk, lk + 16, con256 + i \* 16 + (4 \* 40), 16); /\* LR \*/
 if (i % 2) {
 ByteXor(rk, rk, skey + 0, 16); /\* Xoring KL \*/
 }
 ClefiaDoubleSwap(lk + 16); /\* updating LR \*/
 }
 else {
 ByteXor(rk, lk + 0, con256 + i \* 16 + (4 \* 40), 16); /\* LL \*/
 if (i % 2) {
 ByteXor(rk, rk, skey + 16, 16); /\* Xoring KR \*/
 }
 ClefiaDoubleSwap(lk + 0); /\* updating LL \*/
 }
 rk += 16;
 }
 ByteXor(rk, skey + 8, skey + 24, 8); /\* final whitening key (WK2, WK3) \*/
}

void ClefiaEncrypt(unsigned char \*ct, const unsigned char \*pt, const unsigned char \*rk, const int r)
{
 unsigned char rin[16], rout[16];
 memcpy(rin, pt, 16);

 ByteXor(rin + 4, rin + 4, rk + 0, 4); /\* initial key whitening \*/
 ByteXor(rin + 12, rin + 12, rk + 4, 4);
 rk += 8;

 ClefiaGfn4(rout, rin, rk, r); /\* GFN\_{4,r} \*/

 memcpy(ct, rout, 16);
 ByteXor(ct + 4, ct + 4, rk + r \* 8 + 0, 4); /\* final key whitening \*/
 ByteXor(ct + 12, ct + 12, rk + r \* 8 + 4, 4);
}

void ClefiaDecrypt(unsigned char \*pt, const unsigned char \*ct, const unsigned char \*rk, const int r)
{
 unsigned char rin[16], rout[16];
 memcpy(rin, ct, 16);

 ByteXor(rin + 4, rin + 4, rk + r \* 8 + 8, 4); /\* initial key whitening \*/
 ByteXor(rin + 12, rin + 12, rk + r \* 8 + 12, 4);
 rk += 8;

 ClefiaGfn4Inv(rout, rin, rk, r); /\* GFN^{-1}\_{4,r} \*/

 memcpy(pt, rout, 16);
 ByteXor(pt + 4, pt + 4, rk - 8, 4); /\* final key whitening \*/
 ByteXor(pt + 12, pt + 12, rk - 4, 4);
}

```

ראו גם
------

* צופן בלוקים
* PRESENT

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

1. ↑  The 128-bit Blockcipher CLEFIA, Taizo ShiraiKyoji ShibutaniToru AkishitaShiho MoriaiTetsu Iwata
2. ↑  Fast Software Encryption 2007
3. ↑  ISO/IEC 29192-2:2012
4. ↑  The Improbable Differential Attack: Cryptanalysis of Reduced Round CLEFIA
5. ↑  Improved Impossible Differential Cryptanalysis of CLEFIA

| * צ
* ש
* ע
קריפטוגרפיה |
| --- |
| 

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

 |

 |
| 

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

 |

 |
| 

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

 |

 |
| 

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

 |

 |
| 

| צופן זרם |
| --- |
| 
* RC4
* Salsa20
* SOSEMANUK
* Grain
* 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
* סיסמה חד-פעמית

 |

 |
| 

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

 |

 |