Menu
CoddyTech

التحقق من كلمة المرور

جزء من قسم المصادقة والأمان في رحلة Node.js على Coddy. الدرس 2 من 17.

لا يمكن عكس التجزئة، لذا لا يقرأ تسجيل الدخول كلمة المرور المخزنة مجددًا. تُجزّئ المحاولة بالطريقة نفسها وتقارن بين التجزئتين. والطريقة نفسها تعني استخدام الملح نفسه: قسّم القيمة المخزنة salt:hash وأعِد استخدام ملحها.

استخدم timingSafeEqual للمقارنة، وليس ===. تتوقف === عند أول بايت مختلف، لذا يمكن للمهاجم الذي يقيس زمن العديد من الإجابات أن يعرف مقدار صحة التخمين. تستغرق timingSafeEqual الوقت نفسه دائمًا. وهي تقارن بين مخزنين مؤقتين لهما الطول نفسه، وتُصدر خطأً عندما يختلف الطولان.

import { timingSafeEqual } from 'node:crypto';

const expected = Buffer.from(process.env.API_KEY);
const given = Buffer.from(req.get('x-api-key') ?? '');
const ok = given.length === expected.length && timingSafeEqual(given, expected);

تحوّل Buffer.from(hex, 'hex') النص السداسي عشري إلى بايتات مجددًا.

challenge icon

التحدي

سهل
  • في passwords.js، أضِف وصدِّر verifyPassword(password, stored): تكون النتيجة true عندما تكون كلمة المرور هي التي أنشأت القيمة المخزنة.
  • في server.js، أضِف POST /login مع { username, password }: استجابة 200 تتضمن { username }، أو استجابة 401 تتضمن { "error": "Wrong username or password" } عند إدخال كلمة مرور خاطئة أو اسم غير معروف.

سجّل ada، وسجّل الدخول، ثم سجّل الدخول بكلمة مرور خاطئة.

جرّب بنفسك

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

const scryptAsync = promisify(scrypt);

// يحوّل كلمة المرور إلى النص الذي يخزّنه signup.
export async function hashPassword(password) {
    const salt = randomBytes(16).toString('hex');
    const key = await scryptAsync(password, salt, 64);
    return `${salt}:${key.toString('hex')}`;
}

جميع دروس المصادقة والأمان