Menu
CoddyTech

Verificar una contraseña

Parte de la sección Autenticación y seguridad del Journey de Node.js de Coddy. Lección 2 de 17.

Un hash no se puede revertir, así que al iniciar sesión nunca se vuelve a leer la contraseña almacenada. Calculas el hash del intento de la misma manera y comparas las dos claves. De la misma manera significa con la misma sal: separa el salt:hash almacenado y reutiliza su sal.

Compara con timingSafeEqual, no con ===. === se detiene en el primer byte que difiere, así que un atacante que mide el tiempo de muchas respuestas averigua qué parte de una conjetura era correcta. timingSafeEqual siempre tarda lo mismo. Compara dos búferes de la misma longitud y lanza un error cuando las longitudes difieren.

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') convierte el texto hexadecimal de nuevo en bytes.

challenge icon

Desafío

Fácil
  • En passwords.js, agrega y exporta verifyPassword(password, stored): devuelve verdadero cuando la contraseña generó ese valor almacenado.
  • En server.js, agrega POST /login con { username, password }: devuelve 200 { username } o 401 { "error": "Wrong username or password" } si la contraseña es incorrecta o el nombre es desconocido.

Registra a ada, inicia sesión y después inicia sesión con una contraseña incorrecta.

Pruébalo tú mismo

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

const scryptAsync = promisify(scrypt);

// Convierte una contraseña en el texto que almacena signup.
export async function hashPassword(password) {
    const salt = randomBytes(16).toString('hex');
    const key = await scryptAsync(password, salt, 64);
    return `${salt}:${key.toString('hex')}`;
}

Todas las lecciones de Autenticación y seguridad