Spaces:
Sleeping
Sleeping
| import crypto from 'crypto'; | |
| // Password hashing with Node's built-in scrypt (no external dependency). | |
| // Stored format: `scrypt$<saltHex>$<hashHex>`. | |
| const KEYLEN = 64; | |
| const SALT_BYTES = 16; | |
| export function hashPassword(password: string): string { | |
| const salt = crypto.randomBytes(SALT_BYTES); | |
| const hash = crypto.scryptSync(password, salt, KEYLEN); | |
| return `scrypt$${salt.toString('hex')}$${hash.toString('hex')}`; | |
| } | |
| export function verifyPassword(password: string, stored: string): boolean { | |
| const parts = stored.split('$'); | |
| if (parts.length !== 3 || parts[0] !== 'scrypt') return false; | |
| const salt = Buffer.from(parts[1], 'hex'); | |
| const expected = Buffer.from(parts[2], 'hex'); | |
| let actual: Buffer; | |
| try { | |
| actual = crypto.scryptSync(password, salt, expected.length); | |
| } catch { | |
| return false; | |
| } | |
| // Constant-time compare; lengths match by construction (both KEYLEN). | |
| return actual.length === expected.length && crypto.timingSafeEqual(actual, expected); | |
| } | |