הצפנת TEA - לאלו שמבינים בקריפטוגרפיה:

Dizzy Doop

New member
הצפנת TEA - לאלו שמבינים בקריפטוגרפיה:

להלן פונקציות ההצפנה והפענוח של TEA ממומשות בשפת C:
void encrypt (unsigned long* v, unsigned long* k) { unsigned long v0=v[0], v1=v[1], sum=0, i; //* set up * unsigned long delta=0x9e3779b9; //* a key schedule constant * unsigned long k0=k[0], k1=k[1], k2=k[2], k3=k[3]; //* cache key * for (i=0; i < 32; i++) { //* basic cycle start * sum += delta; v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1); v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3); //* end cycle * } v[0]=v0; v[1]=v1; } void decrypt (unsigned long* v, unsigned long* k) { unsigned long v0=v[0], v1=v[1], sum=0xC6EF3720, i; //* set up * unsigned long delta=0x9e3779b9; //* a key schedule constant * unsigned long k0=k[0], k1=k[1], k2=k[2], k3=k[3]; //* cache key * for (i=0; i<32; i++) { //* basic cycle start * v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3); v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1); sum -= delta; //* end cycle * } v[0]=v0; v[1]=v1; }​
אני כותב תוכנית קצרה מאד בסי שאמורה לקרוא קובץ ולהצפין אותו עם אלגוריתם TEA. העתקתי את פונקציות ההצפנה והפענוח מויקיפדיה, רק אין לי שמץ של מושג איך להשתמש בהן (מעולם לא למדתי מדמ"ח ולכן אני לא בקיא במימושן הלוגי ובשימושן). לאחר שכבר קראתי את הקובץ שאותו אני מעוניין להצפין עם fread(...) באופן בינארי, על כל תוכנו, אל תוך משתנה char* בזיכרון ולקחתי מהמשתמש מפתח - מה בעצם אמור להיות השלב הבא? האם אני פשוט אמור לשלוח את המשתנה שמכיל את כל תוכן הקובץ כפרמטר לפונקציה יחד עם המפתח? או שצריך לחלק אותו לבלוקים? העניין של הבלוקים לא כל כך מובן לי: מהו בעצם בלוק? האם מדובר בחלק קטן מהתוכן של המידע שעליו מעוניינים לבצע את ההצפנה? האם התוכנית אמורה בעצם לחלק את תוכן המידע שאותו שאני מעוניין להצפין לחלקים קטנים, ולאחר מכן היא אמורה לעבור חלק-חלק (בלוק-בלוק) ולהפעיל עליו את הפונקציה encrypt? זה נראה קצת מסורבל ולא יעיל מבחינת ביצועים. כאן אני אדגים את השימוש בפונקציות, כפי שניסיתי לעשות.. כאשר v הוא משתנה מסוג char* שמכיל את כל תוכן המידע הבינארי שאותו אני להצפין, ו- k הוא char* שמכיל את תוכן המפתח שהיוזר הקליד בזמן ריצה... זו בכלל הצפנה תקינה כפי שנהוג לעשות בד"כ?
for(i = 0; i < size; i+=8) encrypt((unsigned long*) (v+i), (unsigned long*) key);​
ועבור הפענוח:
for(i = 0; i < size; i+=8) decrypt((unsigned long*) (v+i), (unsigned long*) key);​
במידה ולא, אשמח אם מישהו יוכל לשפוך מעט אור על איך אמורה להתבצע החלוקה של המידע לבלוקים בצורה מאורגנת ויעילה יותר... כאשר יש לי קבצים גדולים מדי של כמעל 10 MB, האם כדאי לבצע את החלוקה באמצעות Threadים? כך שכל ההצפנה תתבצע "במכה אחת" במקום לעבור חלק-חלק?
 

vinney

Well-known member
קצת רקע

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

Dizzy Doop

New member
אני עושה את זה לשם התנסות ראשונית בהצפנות...

ואמורים ש TEA הוא יחסית אלג' פשוט ולא קשה כמו חבריו הסימטריים, AES/DES, לכן חשבתי שזה טוב להתחיל לנסות להשתמש באחד כזה ולאחר מכן לשאוף לנסות את המימוש המתמטי שלו (מעולם השתמשתי באופרטורים בינאריים-לוגיים בהיותי מתכנת בC ולכן יקח לי עוד לזמן להבין את המשמעות של הפעולות). הייתי שמח אם תוכל להתייחס גם לשאלות ששאלתי לגבי הביצועים: האם בד"כ ישנה שיטה מוגדרת לשם חלוקת הקובץ לבלוקים באופן יעיל מתוחכם יותר מאשר סתם לעבור בלולאה "ולמשוך" לזיכרון בכל פעם 32 בתים (256 סיביות) שיועברו לפונקציית ההצפנה/הפענוח? כי שמתי לב, משימוש בתוכנות כגון open ssl, שהצפנת קובץ של 10 מגה-בייט לצורך העניין, לוקחת ממש "טיק-טק" - ובעוד התוכנית שלי מתעכבת לאיזה כמה שניות... האם בד"כ נהוג בהצפנות להשתמש בתהליכונים (Multithreadin) כדי להגיע לרמת ביצועים גבוה יותר? למשל, הקצאת תהליכון אחד עבור הצפנה של כל בלוק? וסתם שאלה כללית, אילו שימושים יש להצפנות ולקריפטוגרפיה? באילו עוד מקרים משתמשים בהצפנות, חוץ מאשר עבור מידע כגון קבצים? האם ניתן להצפין גם חבילות (packetים) שעוברים מהשרת שלי ברוטוקול TCP/IP?
 

vinney

Well-known member
אם אתה רוצה להתחיל - אז תתחיל מהתחלה

תתחיל מצפני החלפה פשוטים (ההצפנה ה"רומית"), תשיג איזה ספר טוב (סודות ההצפנה של סימון סינג, בתור מדע פופולרי, או אחד הספרים הכבדים יותר מתוך שרשור הספרים בטאגליינס), וכמובן - אתה צריך קצת הבנה במתמטיקה (פונקציות, קצת רקע בתורת המספרים, וכו'). אני חייב לציין שאם בתור מתכנת מעולם לא השתמשת באופרטורים לוגיים, אז כדאי גם לחזור על החומר הזה, ובכלל זה כל מה שקשור למערכות ספרתיות - ספר הקורס של האוניברסיטה הפתוחה יתן לך את כל מה שאתה צריך. עבודה עם אופרטורים בינאריים זה דבר בסיסי לא רק בקריפטוגרפיה. לגבי ביצועים - זה לא קשור לקריפטוגרפיה, אלא לתכנות נכון, לעבודה נכונה עם זכרון, ומימוש יעיל. אין טעם לקרוא 32 בתים מהדיסק בכל פעם, כי זה נורא יקר, תקרא כמה שיותר לזכרון, ואז תחלק לחלקים שאתה צריך, זה יחסוך לך המון זמן. בהצפנה לא תמיד אפשר להשתמש בריבוי תהליכים, יש צפנים שמשתמשים בתוצר של הצפנת הבלוק הקודם בשביל להצפין את הבלוק הבא, במקרה כזה ההצפנה חייבת להיות סדרתית. במקרה שלך - אתה יכול להשתמש בתהליכונים כי ההצפנה של בלוק אחד לא משפיעה על אחר, אבל אתה תצטרך לסנכרן גישה לנתונים בצורה כלשהי מבלי להתבלבל, אם אתה יודע לתכנת באופן מקבילי - אתה תסתדר. שימושים להצפנה (קריפטוגרפיה זה המילה בלעז להצפנה) הם רבים ומגוונים, הקשורים רובם ככולם לאבטחת מידע והבטחת מידע. אבל קבצים זה רק חלק מועט מהמידע שמוצפן בדרך כלל. הרבה מהתעבורה ברשת מוצפנת (כל אתרי הקניון המאובטחים מצפינים את התעבורה בין הלקוח לאתר, מצפינים דואר אלקטרוני, וכד'), משתמשים בהצפנה לאימות זיהוי (חתימה אלקטרונית) והבטחת נתונים (integrity) - בעזרת שיטות checksum או hush למינהן, וכד'. לא ניתן להצפין את פרוטוקול TCP ובטח שלא IP, אבל מה שכן ניתן זה לעשות שכבת tunnelling מעל, ולזה יש פרוטוקולי VPN כדוגמת PPP או IPSec או L2TP שבטח שמעת על חלק מהם (הם משתמשים, בין היתר, להקמת רשת של ספקי אינטרנט על בסיס רשת של ספקי תשתית). גם SSL עקרונית מאפשר לך לבצע תקשורת מוצפנת כללית, אבל משתמשים בו בעיקר בהיבט של אתרים מאובטחים (פרוטוקול HTTPS), ולפעמים דואר.
 

Dizzy Doop

New member
אגב, אני לא דייקתי מספיק...

זה לא שלא השתמשתי באופרטורים לוגיים בכלל - אני משתמש באלו אשר משמשים להרכבת ביטויים לוגיים (&&, ||, <, >, <=, >=, ==, !=, !) במשפטי התנייה ולולאות המון... פשוט ישנם עוד כמה אופרטורים מוזרים לטיפול במידע בינארי/הקסדצימלי (^, >>, <<, |, & ודומים) - שבהם מעולם לא מצאתי עדיין צורך להשתמש ואין לי מושג מה המשמעות שלהם, נודע לי שהם משמשים בעיקר עבור אופטימיזציות לפרוייקטים של מערכות RT.
 

vinney

Well-known member
אופרטורים לוגיים ובינאריים זה לא אותו דבר

האופרטורים >,<,==, !=, ||, &&, ! הם אופרטורים לוגיים, המחזירים תמיד "TRUE" שזה ערך שונה מ0 , או "FALSE" שזה 0. האופרטורים ^, |, &, ~, >> ו<< אלה אופרטורים בינאריים/אונאריים המבצעים פעולות על ביטים. אלה דברים דומים, אבל שונים, וזה יכול קצת לבלבל, אז צריך לשים לב
אופרטורים על ביטים משמשים כשצריך לבצע פעולות על ביטים, זה לא בהכרח במערכות RT, ואתה כנראה התכוונת למערכות משובצות מחשב (Embedded), שם באמת משתמשים בהם הרבה.
 

Dizzy Doop

New member
ואגב, כיצד בדרך-כלל נהוג בהצפנות ->

להמיר את המחרוזת הטקסטואלית (ASCII) של המפתח (כפי שנקלט מהיוזר ברן-טיים למשנה char*), למידע בינארי שמחולק לארבעה איברים במערך unsigned long* ?? האם צריך להשתמש באיזו פונקציית ספרייה ייעודית לשם כך? או שאם אני עושה קסטינג (casting) של זה מ- char* ל- unsigned long*, הקומפיילר כבר ידע להתייחס לכך כאל מידע בינארי? ולגבי ה- plain text שקראתי מהדיסק למשתנה char* בעזרת freed(...) : האם הוא כבר נחשב למידע בינארי או שגם אותו יש להמיר? ואגב, האם לא היה אפשרי פשוט לקרוא את ה- plain text מלכתחילה כ- unsigned long* מהדיסק, ולחלק אותו לבלוקים תוך כדי הקריאה עצמה ובכך לחסוך את ההמרה בעתיד? תודה על תשומת הלב :)
 

vinney

Well-known member
המם...

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

BlackBamba

New member
תחשוב גם על מטרת "התרגיל"

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

skies

New member
לגבי העבודה עם הקבצים

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