Problem
Currently, password hashing uses the username as the salt with SHA-512:
sha512(username + password)
This has security weaknesses:
- Predictable salt: Usernames are public and known to attackers, making precomputed attacks easier.
- No uniqueness guarantee: If a user changes their password, the salt remains the same.
- Weak algorithm: SHA-512 is a general-purpose hash — too fast for password hashing, vulnerable to GPU brute-force.
Proposal
- Add a dedicated
salt column to the users table (random bytes per user, generated via crypto.randomBytes).
- Replace SHA-512 with
crypto.scrypt (built into Node.js, no extra dependency needed).
- scrypt is intentionally slow with a configurable cost factor.
- scrypt is memory-hard, resistant to GPU/ASIC attacks.
- Store the scrypt-derived hash in the
password column and the random salt in the salt column.
Migration Plan
- Add the
salt column to the users table (nullable initially).
- During login, check if the user has a
salt value:
- No salt (legacy user): verify with the old
sha512(username + password) scheme. On success, re-hash with scrypt + random salt, and store both.
- Has salt (migrated user): verify with scrypt.
- Once all active users have been migrated, make the
salt column non-nullable and remove the legacy fallback.
Affected Files
apps/server/auth/src/tasks/check-user-task.ts
modules/server/database/src/tables/user-table.ts
modules/universal/classes/src/User.ts (add optional salt field)
- Database schema (add
salt column to users table)
🤖 Generated with Claude Code
Problem
Currently, password hashing uses the username as the salt with SHA-512:
This has security weaknesses:
Proposal
saltcolumn to theuserstable (random bytes per user, generated viacrypto.randomBytes).crypto.scrypt(built into Node.js, no extra dependency needed).passwordcolumn and the random salt in thesaltcolumn.Migration Plan
saltcolumn to theuserstable (nullable initially).saltvalue:sha512(username + password)scheme. On success, re-hash with scrypt + random salt, and store both.saltcolumn non-nullable and remove the legacy fallback.Affected Files
apps/server/auth/src/tasks/check-user-task.tsmodules/server/database/src/tables/user-table.tsmodules/universal/classes/src/User.ts(add optionalsaltfield)saltcolumn touserstable)🤖 Generated with Claude Code