הצפנה סימטרית לפרחחי ווב

איך הצפנה סימטרית עובדת? הסבר למתכנתי ווב + דוגמאות ב node.
כיתוב: WEB

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

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

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

צופן אתב״ש מתוך ויקיפדיה
 צופן אתב״ש מתוך ויקיפדיה – CC BY-SA 3.0

כך למשל המילה יופי תכתב כ״מפומ״. במקרה הזה, הטקסט שאותו אנו מצפינים הוא ״יופי״, המפתח הוא אתבש והטקסט המוצפן הוא ״מפומ״. באופן עקרוני, איך זה עובד? צד א׳ רוצה להצפין את המילה ״יופי״. מצפין אותה באמצעות המפתח (שזו הטבלה לעיל). יוצא מפומ. שולח את המילה מפומ לצד ב׳. צד ב׳ לוקח את המפתח (שוב, הטבלה לעיל) וממיר את מפומ ל״יופי״. אם מישהו מאזין באמצע, הוא רואה רק את הטקסט ״מפומ״ ולא מבין כלום, בוכה בפינה ומתאבד.

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

אם הקרבות בין מפתחי הצפנים והמפצחים שלהם מעניינים אתכם, אני ממליץ לקרוא את הספר ״סודות ההצפנה״ של סיימון סינג שבאמת פותח את הראש ואני מודה מאוד לד״ר דן פלג שהמליץ לי עליו (ואף השאיל לי אותו!).

בפועל כמובן אנחנו לא נשתמש בצופן אתב"ש ואפילו לא בלוח ויז'נר כיוון שמדובר בשיטות שרגישות להתקפות brute force וזו החולשה העיקרית של מפתח סימטרי – מדובר בסופו של דבר בהצפנות שככל שכוח המחשוב מתקדם יותר, כך הן פגיעות יותר. אבל, וזה אבל גדול, ההצפנות הסימטריות הנהוגות כיום מצריכות המון זמן עיבוד מבחינת brute force attacks כאשר משך הזמן תלוי בגודל המפתח. ככל שהוא יותר גדול, כך צריך יותר זמן לפצח אותו.

חלק מהחולשה של הצפנה סימטרית היא בכך שבהצפנות סימטריות אם אנו משתמשים במפתח זהה לאותו טקסט שאנו רוצים להצפין, אנו נקבל את אותו טקסט מוצפן. וזה רע, כי אפשר לזהות חזרות ובכך לשבור את הצופן ואכן עשו את זה עם הצפנת לוח ויז׳נר. שנחשבה לתקופתה כמתוחכמת אך ניגפה מפני התקפה שפשוט עשתה שימוש בתדירויות של אותיות. אנו יודעים שהאות A למשל היא האות הנפוצה ביותר בשפה האנגלית ואז אנחנו יכולים לנסות ו׳לנחש׳ איזו אות מיוצגת בטקסט. זו הסיבה שבהצפנות מודרנית יש לנו וקטור אתחול (Initialization vector – IV) שמשמש להכנסת רנדומליזציה בהצפנה.

ההצפנה הסימטרית המקובלת כיום נקראת Advanced Encryption Standard ובראשי תבות AES. אני לא רוצה (או אפילו יכול) להכנס כאן להסברים על איך ההצפנה הזו עובדת. אבל בגדול היא חינמית והרשיון שלה מאפשר לכל אחד להשתמש בה לצורך מסחרי או לא מסחרי. בגדול, ההצפנה הזו אינה מבוססת טקסט אלא ׳בלוקים׳ והחוזק שלה נמדד באמצעות אורך המפתח כשהמפתח הוא בעצם ׳חזרות׳ של האלגוריתם המצפין וככל שיש יותר חזרות, כך הפיענוח לוקח יותר זמן וכוח עיבוד. כך שאם אנו משתמשים ב AES 256bit זה יקח לנו המון זמן לפענח את הצופן. שימוש במפתחות חלשים יותר יזניק את מהירות הפיענוח, אך יהפוך את הנתונים לרגישים יותר להתקפה. במה להשתמש? זה תלוי באפליקציה שלכם כמובן.

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

ראשית אנו בוחרים את האלגוריתם (במקרה שלנו AES החזק יותר) ואת אורך חוזקו. אחרי כן אנו בוחרים את המצב שלו. ישנם מספר מצבים: ECB, CBC, CTR, OFB, CFB לדיסקים קשיחים משתמשים ב- XEX, XTS, LRW. במה נשתמש? זו שאלה שכאמור אני לא יכול לענות עליה. לצורך הדוגמה, אנו נשתמש במוד gcm שהוא מוצלח לתוכן כללי (כך אמרו לי).

אחרי כן אנו ניצור את המפתח שלנו. זה יכול להיות סתם טקסט כמו Password used to generate key. באותה הזדמנות חגיגית זו ניצור גם את ה-Initialization vector. ומפה? מפה זה רק מימוש פשוט של ספרית crypto הטבעית שנמצאת ב-node כבר:

const crypto = require('crypto');

// choose Algorithm, there are several flavours
const algorithm = 'aes-256-gcm';
const password = 'Password used to generate key';

// 32 bytes (256 bits).
const key = crypto.scryptSync(password, 'SomeSalt', 32);

// Create Initialization vector
const iv = crypto.randomBytes(32); // Initialization vector.

function encrypt(text){
  const cipher = crypto.createCipheriv(algorithm, key, iv);
  let crypted = cipher.update(text,'utf8','hex');
  crypted += cipher.final('hex');
  return crypted;
}

function decrypt(text){
  let decipher = crypto.createDecipheriv(algorithm, key, iv);
  let dec = decipher.update(text,'hex','utf8');
  return dec;
}
const encryptedText = encrypt('This is super secret text');
console.log(encryptedText)
// This is super secret text
console.log(decrypt(encryptedText));

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

➜  crypto node index.js
01afae88c98c0807faaa55
hello world
➜  crypto node index.js
49f8076a127f46240cc38953221d625547561aec448f988367
This is super secret text
➜  crypto node index.js
aa2c262cbcd270b918057a01b511800090e916a575af473c93
This is super secret text
➜  crypto node index.js
c50965bcfa0de5bd1c1e32d627cff8bfc78337d859fedf2e24
This is super secret text

האם להשתמש ב-IV רנדומלי או לא? האם להשתמש בהצפנה מסוג 256 או 128? ובאיזה מוד? הו! אלו שאלות מעולות שהייתי יכול לענות עליהן אם הייתי קריפטוגרף. אבל אני לא. וזו הסיבה שאני שוכר קריפטוגרף אם אני צריך לממש דברים כאלו מאפס. אבל הדוגמאות שהבאתי הן מעולות אם נרצה להבין הצפנה סימטרית ואת העקרונות שלה.

לסיכום, הצפנה סימטרית היא מהירה, עמידה יחסית לפריצה (אך לא חסינה לפריצה) ואנו צריכים כדי לפתוח אותה מפתח אחד או מפתח ו-Initialization vector. האלגוריתם הוא חינמי וניתן לממש אותו בכל שפה. ב-node יש אינספור ספריות שמאפשרות לנו תקשורת סימטרית מוצפנת עם כל שירות שהוא. אנו אפילו משתמשים בה כחלק מתקשורת https. 

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

פוסטים נוספים שכדאי לקרוא

תמונת תצוגה של מנעול על מחשב
פתרונות ומאמרים על פיתוח אינטרנט

הגנה מפני XSS עם Trusted Types

תכונה ב-CSP שמאפשרת מניעה כמעט הרמטית להתקפות XSS שכל מפתח ווב צריך להכיר וכדאי שיכיר.

פתרונות ומאמרים על פיתוח אינטרנט

יישום של nonce על מנת להגן מפני התקפות injection

בפוסט הקודם הסברתי על hash עם CSP על משאבי inline – שזה נחמד ומעולה אבל פחות ישים בעולם האמיתי שבו בדרך כלל התוכן ה-inline (בין

גלילה לראש העמוד