Skip to main content

Worked solution: password storage

Keep this answer key separate from the student kit.

From this solution folder run node server.mjs, then open http://127.0.0.1:3000. Stop any other lesson on port 3000 first. Use only the fictional passwords.

The only functional difference from the starter is in password-store.mjs:

export async function storePassword(password) {
return await hashPassword(password);
}

export async function checkPassword(password, stored) {
return await verifyPassword(password, stored);
}

Keep the existing imports. The supplied helper uses Node's async scrypt API, a fresh random 16-byte salt, N=131072, r=8, p=1, a 32-byte derived value and a 256 MiB memory ceiling. Verification accepts only the exact bounded lab format and uses timingSafeEqual for the derived bytes. It does not make the entire authentication flow constant-time.

This avoids requiring third-party packages on Node 22. OWASP recommends Argon2id and provides scrypt as an alternative. See Node's scrypt API.

Stop the server and run node checks.mjs. Expected: all seven pass, exit code 0. The starter passes five and fails storage/salt checks. Random salts mean stored values differ across runs.

Do not deploy this app. Its storage inspector exists only for teaching; there are no production sessions, recovery, persistent storage or deployment controls. Hashing makes guessing costly, not impossible. Restart clears the account; this lesson does not implement migration of existing passwords.

Screenshot preview