Menu
CoddyTech

לעולם אל תשמרו סיסמאות

חלק מהיחידה אימות ואבטחה במסלול ה-Node.js של Coddy. שיעור 4 מתוך 24.

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

const salt = randomBytes(16).toString('hex');
const key = await scryptAsync(inviteCode, salt, 32);
const saved = salt + '.' + key.toString('hex');

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

challenge icon

אתגר

קל

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

  1. בקובץ passwords.js, יש לשנות את hashPassword(password) כך שתחזיר את הטקסט שההרשמה שומרת, בפורמט מלח, נקודתיים, גיבוב:
    • המלח הוא 16 בתים אקראיים, שנוצרים מחדש בכל קריאה ונכתבים בהקסדצימלי: 32 תווים מתוך 0 עד 9 ו־a עד f.
    • הגיבוב הוא מפתח באורך 64 בתים ש־scrypt יוצרת מהסיסמה ומהמלח הזה, וגם הוא נכתב בהקסדצימלי: 128 תווים. הארגומנט השלישי של scryptAsync הוא אורך המפתח בבתים.
    • יש לחבר את השניים באמצעות נקודתיים. ערך שמור נראה כך: f2bba0669d9fa2d203afc7e61bf8f065:c3f7cae352e023a8d4766da9a316b5a2c844100efff22c4079f89a8ab8512ac91c33227481c3afa88c3ba0e88347f9e3e0c22dad9d55f19688a350f71be8dbd2
  2. אין צורך לשנות את server.js. הפעולה POST /signup שבו כבר קוראת ל־hashPassword ושומרת את הערך שהיא מחזירה. יש בו גם את GET /debug/users/:username, שמציגה מה נשמר עבור משתמש אחד. הנתיב הזה קיים רק כדי שתוכלו לבדוק; באפליקציה אמיתית הוא לעולם לא קיים.

נסו זאת: לחצו על "שחק". שלחו POST /signup עם {"username": "ada", "password": "correct horse"}. תקבלו סטטוס 201 ואת {"username": "ada"}. שלחו את אותו גוף עם "username": "bob". כעת שלחו GET /debug/users/ada, ואז GET /debug/users/bob. כל passwordHash מכיל 32 תווים, נקודתיים ועוד 128 תווים. שני הערכים שונים, אף על פי ש־ada ו־bob בחרו באותה סיסמה.

נסו בעצמכם

import { randomBytes, scrypt } from 'node:crypto';
import { promisify } from 'node:util';

const scryptAsync = promisify(scrypt);

// ממירה סיסמה לטקסט ש-signup שומר.
// לעת עתה היא משאירה את הסיסמה כפי שהוקלדה.
export async function hashPassword(password) {
    return password;
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה אימות ואבטחה

תרגלו בעצמכם: Express אונליין