HC-128

מתוך המכלול, האנציקלופדיה היהודית
קפיצה לניווט קפיצה לחיפוש

HC-128 הוא צופן זרם סינכרוני מותאם במיוחד לתוכנה שפותח ב-2004 על ידי Hongjun Wu אוניברסיטת לוון, הוצע לפרויקט eSTREAM[1] ונבחר כצופן זרם מועדף בקטגוריית תוכנה יחד עם מבחר אלגוריתמים נוספים. הצופן מקבל מפתח בגודל 128 סיביות ווקטור אתחול בגודל 128 סיביות. המצב הפנימי (internal state) של הצופן מורכב משתי טבלאות כל אחת בגודל 512 אוגרים בגודל 32 סיביות. בכל צעד, אוגר אחד באחת הטבלאות מעודכן באמצעות פונקציית הזנה אי-לינארית והפלט בגודל 32 סיביות נוצר על ידי פונקציית סינון אי-לינארית. אפשר לייצר זרם מפתח בגודל מרבי של הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle 2^{64}} סיביות. המסר מוצפן ומפוענח באמצעות XOR עם זרם המפתח.

מפתח הצופן מציין את ההצהרות הבאות: מחזוריות הצופן היא לכל היותר . שחזור מפתח ההצפנה קשה כחיפוש ממצה. התקפת הבחנה (distinguishing attack) דורשת לפחות הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle 2^{64}} סיביות מפתח. לא קיימים מפתחות הצפנה חלשים. הצופן אינו מוגן בפטנט כלשהו. מהירות ההצפנה היא בערך 3.05 מחזורי שעון לבית על מחשב פנטיום.

HC-128 הוא גרסה פשוטה של צופן HC-256 והוא פשוט ומהיר בתוכנה, מנצל את יכולות המעבד המודרני ומאפשר מקיביליות, פונקציית ההזנה ופונקציית הפלט יכולות להתבצע בו זמנית.

תיאור הצופן

סימנים מוסכמים:

הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle x+y} הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle (x+y)\text{ mod }2^{32}} כאשר הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle 0\le x,y<2^{32}} .
הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle (x-y)\text{ mod }2^9} , למשל הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle 2-10=504} .
הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle \oplus} XOR
הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle \|} שרשור. למשל אם הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle a=1011} ו-הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle b=1001} , שרשור המחרוזות יחד הוא הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle a \ \| \ b=10111001} .
הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle x\gg n} אופרטור הזזה לימין (shift left) של הסיביות המשתנה הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle x} בסך הכול הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle n} צעדים, כאשר הסיביות המשמעותיות מאופסות.
הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle x\ll n} אופרטור ההזזה לשמאל הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle n} צעדים כך ש-הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle n} הסיביות הפחות משמעותיות מאופסות.
הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle x\ggg n} אופרטור הזזה מעגלית (rotate) לימין על מילים באורך 32 סיביות. הסיביות של מוזזות לימין הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle n} צעדים כאשר כל הסיביות שנפלטות מצד ימין מוחזרות מצד שמאל. בניסוח פורמלי הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle ((x \gg n)\oplus (x\ll {(32-n)})}
הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle x\lll n} הזזה מחזורית לשמאל. בניסוח פורמלי הפענוח נכשל (שגיאת המרה. השרת ("https://wikimedia.org/api/rest_") השיב: "Cannot get mml. Server problem."): {\displaystyle ((x\ll n)\oplus (x\gg {(32-n)})}

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

ישנן 6 פונקציות עזר בצופן. הפונקציות ו- שאולות מפונקציות דומות שהן חלק מפונקציית התמצות של SHA-2. לצורך הפונקציה הפענוח נכשל (שגיאת המרה. השרת ("https://wikimedia.org/api/rest_") השיב: "Cannot get mml. Server problem."): {\displaystyle h_{1}(x)} משתמשים בטבלה כתיבות החלפה (s-box) ועבור הפונקציה משתמשים בטבלה הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle P} . הפונקציות הן:

הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle f_1(x)=(x\ggg 7)\oplus (x\ggg {18})\oplus (x\gg 3)}
הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle f_2(x)=(x\ggg {17})\oplus (x\ggg {19})\oplus (x\gg {10})}
הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle g_1(x,y,z)=((x\ggg {10})\oplus (x\ggg {23}))+(y\ggg 8)}
הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle g_2(x,y,z)=((x\lll {10})\oplus (z\lll {23}))+(y\lll 8)}
הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle h_2(x)=P[x_0]+P[256+x_2]}

כאשר הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle x=x_0\ \| \ x_1 \ \| \ x_2 \ \| \ x_3} הוא מילה בגודל 32 סיביות והאלמנטים הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle x_i} הם ארבעת הבתים המרכיבים את המילה לפי סדר בתים קטן. כאשר בית אפס מייצג את החלק הפחות משמעותי של המילה.

תהליך אתחול

תהליך האתחול של הצופן כולל הרחבת וקטור האתחול והמפתח הסודי לשתי הטבלאות הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle P} ו- בדומה ל-SHA-256. ואז מריצים את הצופן 1024 צעדים בהם לא משתמשים בפלט הצופן כמפתח אלא הפלט מוזן בחזרה לעדכון אלמנטים בטבלאות. יהי הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle K=K_0\ \| \ K_1\ \| \ K_2\ \| \ K_3} וכן הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle IV=IV_0\ \| \ IV_1\ \| \ IV_2\ \| \ IV_3} כאשר כל הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle K_i} ו-הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle IV_i} בגודל 32 סיביות. משכפלים את המפתח ווקטור האתחול ארבע פעמים בניסוח פורמלי: הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle K_{i+4}=K_i} ו-הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle IV_{i+1}=IV_i} עבור הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle 0\le i<4} . המפתח ווקטור האתחול מורחבים למערך עזר זמני בגודל 1280 אלמנטים של 32 סיביות כדלהלן:

הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle W_i = \begin{cases} K_i, & 0\le i\le 7 \\ IV_{i-8}, & 8\le i\le 15 \\ f_2(W_{i-2})+W_{i-7} +f_1(W_{i-15})+W_{i-16}+i, & 16\le i\le 1279 \end{cases}}

מעדכנים את הטבלאות כדלהלן: עבור הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle i=0} עד הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle 511} בצע: הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle P[i]=W_{i+256},Q[i]=W_{i+768}} . מריצים את הצופן 1024 צעדים כדלהלן:

הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle \text{If }i=0\text{ to }511\text{ do }}
הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle P[i]=(P[i]+g_1(P[i\boxminus 3],P[i\boxminus 10],P[i\boxminus 511]))\oplus h_1(P[i\boxminus 12])}
הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle \text{If }i=0\text{ to }511\text{ do }}
הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle Q[i]=(Q[i]+g_2(Q[i\boxminus 3],Q[i\boxminus 10],Q[i\boxminus 511]))\oplus h_2(Q[i\boxminus 12])}

בשלב זה הצופן מוכן לשימוש.

הצפנה ופענוח

הצפנה ופענוח זהים כמו בכל צופן זרם, תחילה מייצרים זרם מפתח באורך המסר המיועד להצפנה ואז מבצעים XOR מילה אחר מילה של כל המסר עם זרם המפתח. המחולל המייצר את זרם המפתח מעדכן בכל צעד אלמנט אחד מהטבלאות וכן מפיק פלט של 32 סיביות כחלק מזרם המפתח. כל תיבת החלפה מתוך הטבלאות משמשת להפקת 512 פלטים בלבד ולאחר מכן מתעדכנת לצורך 512 הפלטים הבאים. להלן פסאודו קוד המתאר את מהלכי מחולל זרם המפתח בכל צעד או פעימה. שומרים מונה הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle i} שמתחיל באפס ומקודם אחרי כל ריצה של המחולל:

  1. הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle j=i\text{ mod }512}
  2. הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle \text{If }(i\text{ mod }1024) < 512\text{ then do }}
    הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle P[j]=P[j]+g_1(P[i\boxminus 3],P[j\boxminus 10],P[j\boxminus 511])}
    הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle s_i=h_1(P[j\boxminus 12])\oplus P[j]}
  3. הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle \text{Else do }}
    הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle Q[j]=Q[j]+g_2(Q[j\boxminus 3],Q[j\boxminus 10],Q[j\boxminus 511])}
    הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle s_i=h_2(Q[j\boxminus 12])\oplus Q[j]}
  4. הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle i=i+1}

הפלט הוא הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle s_i} . חוזרים על תהליך זה שוב ושוב עד שמתקבל זרם מפתח באורך הרצוי, עד לאורך מקסימלי של הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle 2^{64}} סיביות או הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle 2^{59}} מילים. לאחר מכן רצוי להחליף וקטור אתחול או מפתח.

בטחון

פונקציות הפלט וההזנה של הצופן הן בעלי תכונת אי-לינאריות גבוהה, לכן התקפת קורלציה והתקפה אלגברית אינן ישימות כנגד צופן זה. בנוסף הטבלאות מתעדכנות בזמן ריצה לכן קשה לפתח יחס לינארי כלשהו בין הקלט לפלט של תיבות ההחלפה. מצב הצופן מכיל בסך הכול 32,778 סיביות, כך שהוא מכיל מחזוריות גבוהה למדי, אם כי קשה להעריכה במדויק. בממוצע מדובר על הפענוח נכשל (SVG (אפשר להפעיל MathML בעזרת הרחבת דפדפן): תשובה בלתי־תקינה ("Math extension cannot connect to Restbase.") מהשרת "https://wikimedia.org/api/rest_v1/":): {\displaystyle 2^{256}} סיביות. כן המספר הגדול של מצבי צופן, מסכל התקפת איזון זמן/זיכרון/דטה כנגד צופן זרם.

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

קוד לדוגמה

typedef struct { 
      uint P[512];
      uint Q[512];
      uint counter1024;     // counter1024 = i mod 1024
      uint keystreamword;
} HC128_State; 

#define ROTR32(x,n)   ( ((x) >> (n))  | ((x) << (32 - (n))) )
#define ROTL32(x,n)   ( ((x) << (n))  | ((x) >> (32 - (n))) )

#define f1(x)    (ROTR32((x),7) ^ ROTR32((x),18) ^ ((x) >> 3))
#define f2(x)    (ROTR32((x),17) ^ ROTR32((x),19) ^ ((x) >> 10))

uint h1(HC128_State *state, uint u) {
      return state->Q[u]+state->Q[256+(u >> 16)];
}

uint h2(HC128_State *state, uint u) {	
      return state->P[u]+state->P[256+(u >> 16)];
}

void OneStep(HC128_State *state) 
{
      uint i   = state->counter1024 & 0x1ff;
      uint i3  = (i - 3) & 0x1ff;
      uint i10 = (i - 10) & 0x1ff;
      uint i12 = (i - 12) & 0x1ff;
      uint i511 = (i - 511) & 0x1ff;

      if (state->counter1024 < 512) {
            state->P[i] = state->P[i] + g1(state->P[i3], state->P[i10], state->P[i511]);
            state->keystreamword = h1(state, state->P[i12]) ^ state->P[i];
            // state->P[i] = h1(state,state->P[i12]) ^ state->P[i]; // replace with this for init
      }
      else {
            state->Q[i] = state->Q[i] + g2(state->Q[i3], state->Q[i10], state->Q[i511]);
            state->keystreamword = h2(state, state->Q[i12]) ^ state->Q[i];
            // state->Q[i] = h2(state,state->Q[i12]) ^ state->Q[i]; // replace with this for init
      }
      state->counter1024 = (state->counter1024+1) & 0x3ff;
}


void Initialization(HC128_State *state, byte *key, byte *iv) 
{
      uint W[1024+256],i;

      for (i = 0; i < 4; i++) {
          W[i] = ((uint*)key)[i]; W[i+4] = ((uint*)key)[i];
      }
      for (i = 0; i < 4; i++) {
          W[i+8] = ((uint*)iv)[i]; W[i+12] = ((uint*)iv)[i];
      }

      for (i = 16; i < 1024+256; i++) 
         W[i] = f2(W[i-2]) + W[i-7] + f1(W[i-15]) + W[i-16]+i; 

      for (i = 0; i < 512; i++)  state->P[i] = W[i+256];
      for (i = 0; i < 512; i++)  state->Q[i] = W[i+256+512];

      state->counter1024 = 0;

      for (i = 0; i < 1024; i++)  InitOneStep(state); // see comment
}

void EncryptMessage(HC128_State *state, byte *message, byte *ciphertext, long msglength)
{
      uint64 i;
      uint j;
      
      for (i = 0; (i+4) <= msglength; i += 4, message += 4, ciphertext += 4) 
      {
            OneStep(state);   
            ((uint*)ciphertext)[0] = ((uint*)message)[0] ^ state->keystreamword;   
      }
 
      if ((msglength & 3) != 0)
      {
            OneStep(state);
            for (j = 0; j < (msglength & 3); j++) {
                  *(ciphertext+j) = *(message+j) ^ ((byte*)&state->keystreamword)[j];
            }
      }    
}

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

הערות שוליים