Menu
CoddyTech

Never Store Passwords

Part of the Auth and Security section of Coddy's Node.js journey. Lesson 1 of 17.

If your database leaks, every password stored as typed can be read, and people use the same password on other sites. So you store a hash instead: a value computed from the password that cannot be turned back into it.

For passwords, Node offers crypto.scrypt. It is slow on purpose, so guessing millions of passwords costs an attacker hours. A salt, random bytes mixed in before hashing, makes two people with the same password get different hashes. The salt is not secret: you store it beside the hash.

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

const scryptAsync = promisify(scrypt);

const salt = randomBytes(16).toString('hex');
const key = await scryptAsync('pin 4821', salt, 32);
console.log(key.toString('base64'));

promisify turns scrypt's callback into a promise you can await.

challenge icon

Challenge

Easy
  • In passwords.js, make hashPassword(password) return salt:hash: 16 random bytes of salt and a 64 byte scrypt key, both in hex.
  • GET /debug/users/:username shows what signup stored.

Press Run. Send POST /signup with {"username": "ada", "password": "correct horse"}, then the same password for bob, then compare both users.

Try it yourself

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

const scryptAsync = promisify(scrypt);

// Turns a password into the text signup stores.
// For now it keeps the password as typed.
export async function hashPassword(password) {
    return password;
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Auth and Security