Menu
CoddyTech

Verificando uma senha

Parte da seção Autenticação e segurança do Journey de Node.js da Coddy. Lição 2 de 17.

Um hash não pode ser revertido, então um login nunca lê a senha armazenada. Você aplica hash à tentativa da mesma maneira e compara as duas chaves. Da mesma maneira significa com o mesmo salt: divida o salt:hash armazenado e reutilize o salt.

Compare com timingSafeEqual, não com ===. === para no primeiro byte diferente, então um invasor que cronometra muitas tentativas aprende quanto de um palpite estava certo. timingSafeEqual sempre leva o mesmo tempo. Ele compara dois Buffers do mesmo tamanho e lança um erro quando os tamanhos diferem.

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') transforma o texto hexadecimal novamente em bytes.

challenge icon

Desafio

Fácil
  • Em passwords.js, adicione e exporte verifyPassword(password, stored): verdadeiro quando a senha gerou aquele valor armazenado.
  • Em server.js, adicione POST /login com { username, password }: 200 { username } ou 401 { "error": "Wrong username or password" } para uma senha incorreta ou um nome desconhecido.

Cadastre ada, faça login e, em seguida, faça login com uma senha incorreta.

Experimente você mesmo

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

const scryptAsync = promisify(scrypt);

// Transforma uma senha no texto que signup armazena.
export async function hashPassword(password) {
    const salt = randomBytes(16).toString('hex');
    const key = await scryptAsync(password, salt, 64);
    return `${salt}:${key.toString('hex')}`;
}

Todas as lições de Autenticação e segurança