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')}`;
}

Все уроки раздела Аутентификация и безопасность