אימות (Authentication) הוא השומר בכניסה לאפליקציה שלך. בכל פעם שמישהו נרשם או מתחבר, המערכת שלך צריכה להחליט אם הוא באמת מי שהוא טוען שהוא. אם תטעה, לא תסתפק רק בניסיון לתקן (debugging) כשל בהתחברות; אתה מסתכן בכך שמידע אמיתי של משתמשים פשוט ייצא מהדלת. כדי לעשות זאת כראוי, דרושים שני כלים אמינים: Bcrypt להגנה על סיסמאות במצב מנוחה (at rest), ו-JSON Web Tokens לאימות זהות בזמן שהמשתמש נע בתוך האפליקציה.
למה אחסון בטקסט גלוי (Plaintext) נכשל
אם תזכרו רק כלל אחד מהמאמר הזה, שיהיה זה הכלל הזה: לעולם אל תאחסנו סיסמאות כטקסט גלוי (plaintext) במסד הנתונים שלכם. לא משנה אם מסד הנתונים שלכם נמצא מאחורי חומת אש או אם אתם סומכים על כל מהנדס בצוות. כתיבת סיסמאות לתוך טבלאות בצורתן הגולמית היא כמו להשאיר מפתחות של הבית מתחת לשטיח בפתח הדלת. ברגע שמישהו מקבל גישה למסד הנתונים הזה — דרך API שאינו מוגדר כראוי, גיבוי שדלף או מתקפת הזרקה (injection attack) — כל פרטי ההזדהות נחשפים באופן מיידי.
הנזק מוכפל מכיוון שאנשים משתמשים שוב ושוב באותן סיסמאות. פריצה אחת יכולה לסכן לא רק את האפליקציה שלכם, אלא גם את חשבון האימייל, הבנק ורשתות החברתיות של המשתמש. זו הסיבה שאנחנו מבצעים hashing לסיסמאות. Hashing הופך את הסיסמה למחרוזת מבולבלת שאין לה שום דמיון ברור למקור. התהליך הוא חד-כיווני ובלתי הפיך. אי אפשר לשפוך "חומצה מתמטית" על hash כדי להמיס אותו בחזרה לסיסמה שיצרה אותו.
ביצוע Hashing לסיסמאות באמצעות Bcrypt
Bcrypt היא פונקציית hashing שנבנתה במיוחד עבור סיסמאות. היא לוקחת את המחרוזת הגולמית, מריצה אותה דרך צופן Blowfish, ומחזירה תוצאה שנראית בערך כך: $2b$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy. הקידומת הזו אומרת לכם מהו האלגוריתם ומהו גורם העלות (cost factor). הזנב הארוך הוא שילוב של ה-salt וה-hash עצמו.
ה-salt הוא מידע אקראי שמוטמע בסיסמה לפני תחילת תהליך ה-hashing. מכיוון שה-salt ייחודי לכל משתמש, שני אנשים שיבחרו בשניהם ב-"password123" יקבלו בסופו של דבר hashes שונים לחלוטין במסד הנתונים שלכם. ההבדל הזניח הזה מנטרל rainbow tables — מילונים מחושבים מראש של hashes עבור סיסמאות נפוצות — מכיוון שתוקפים יצטרכו לייצר מחדש את הטבלה כולה עבור כל salt ייחודי.
Bcrypt גם איטית בכוונה. חומרה מודרנית יכולה לנחש מיליארדי hashes בשנייה באמצעות אלגוריתמים מהירים כמו SHA-256. Bcrypt "גוררת רגליים". היא מריצה את תהליך ה-hashing מספר פעמים, תחת שליטה של גורם עלות (cost factor) שניתן להעלות ככל שהמחשבים הופכים למהירים יותר. האיטיות הזו מענישה כל מי שמנסה לבצע brute-force כדי לפרוץ דרך מסד נתונים גנוב. משתמש לגיטימי שימתין עוד מאתיים מילי-שניות בזמן ההתחברות לא יבחין בכך. תוקף שמנסה לבדוק מיליוני ניחושים בהחלט יבחין.
איך עובדים JSON Web Tokens
בעוד ש-Bcrypt מטפל בדלת הקדמית, JWT מטפל ב"כרטיס המעבר" במסדרון. JSON Web Token הוא מחרוזת קומפקטית ובטוחה לשימוש ב-URL שמוכיחה שהמשתמש כבר עבר אימות. חשבו על זה כעל תעודת זהות דיגיטלית שהשרת מנפיק והלקוח (client) נושא איתו.
JWT מכיל שלושה מקטעים המופרדים בנקודות: ה-header, ה-payload וה-signature. ה-header מציין את סוג ה-token ואת אלגוריתם החתימה. ה-payload נושא claims — הצהרות על המשתמש ועל ה-token עצמו — כגון מזהה משתמש (user ID), שם משתמש וחותמת זמן לתפוגה (expiration timestamp). ה-signature הוא החותם הקריפטוגרפי. השרת יוצר אותו על ידי קידוד ה-header וה-payload, ולאחר מכן הרצתם דרך מפתח סודי. אם מישהו מתעסק ב-payload, ה-signature כבר לא יתאים, והשרת ידחה את ה-token באופן מיידי.
