// Password hashing using Node's built-in scrypt + a per-hash random salt. // // No external dependency (bcrypt would need a native build step). scrypt is // memory-hard and well suited for interactive logins. Hash format: // ":" (salt is 16 bytes, hash is 64 bytes) const crypto = require('crypto'); const KEYLEN = 64; function hash(password) { const salt = crypto.randomBytes(16).toString('hex'); const out = crypto.scryptSync(password, salt, KEYLEN).toString('hex'); return `${salt}:${out}`; } function verify(password, stored) { if (typeof stored !== 'string' || !stored.includes(':')) return false; const idx = stored.indexOf(':'); const salt = stored.slice(0, idx); const expected = stored.slice(idx + 1); if (!salt || !expected) return false; let computed; try { computed = crypto.scryptSync(password, salt, KEYLEN).toString('hex'); } catch (e) { return false; } if (computed.length !== expected.length) return false; // Constant-time compare to avoid timing side channels. return crypto.timingSafeEqual(Buffer.from(computed), Buffer.from(expected)); } module.exports = { hash, verify };