Skip to content

security: migrate password hashing from triple-SHA-256 to bcrypt#547

Open
xpoes123 wants to merge 1 commit into
qbreader:mainfrom
xpoes123:security/bcrypt-password-migration
Open

security: migrate password hashing from triple-SHA-256 to bcrypt#547
xpoes123 wants to merge 1 commit into
qbreader:mainfrom
xpoes123:security/bcrypt-password-migration

Conversation

@xpoes123

@xpoes123 xpoes123 commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Account passwords were stored as a triple-SHA256 digest using a single global salt (server/authentication.js:35). SHA-256 is a fast, general-purpose hash with no per-user salt and no tunable work factor, making the stored credentials cheap to crack at scale on GPU hardware if the database is ever exposed.

Problem

saltAndHashPassword applied sha256(sha256(sha256(salt + password + salt))) and stored the base64 result. A single compromised global salt means every password hash can be attacked in parallel with identical setup, and fast hashing hardware significantly reduces the effort required.

Changes

  • server/authentication.jssaltAndHashPassword is now async and delegates to bcrypt.hash at cost factor 12. The old triple-SHA-256 body is preserved as a private legacyHashPassword helper. checkPassword distinguishes formats by prefix: bcrypt hashes always begin with $2; legacy base64 digests never do. A matching legacy hash is re-hashed to bcrypt and written back transparently. updatePassword is now async.
  • routes/auth/signup.js — awaits the now-async saltAndHashPassword.
  • package.json / package-lock.json — add bcryptjs@^2.4.3.

bcryptjs (pure JS) was chosen to avoid native build steps; the native bcrypt package can be swapped in later without changing call sites. Callers in routes/auth/login.js, routes/auth/edit-password.js, and routes/auth/reset-password.js already awaited checkPassword/updatePassword and required no changes.

Risk & testing

Existing users are not locked out. checkPassword accepts the legacy triple-SHA-256 hash and on a successful match immediately re-hashes to bcrypt and writes it back, so accounts roll over silently on next login. Once every row in the database has a $2-prefixed hash, legacyHashPassword can be deleted.

The soft migration path was verified by inspection: the prefix check is correct, updatePassword is awaited inside the upgrade branch, and signup.js correctly awaits the now-async saltAndHashPassword. No live database is required to test the hashing logic itself.

@xpoes123 xpoes123 changed the title security: migrate password hashing to bcrypt (soft migration) security: migrate password hashing from triple-SHA-256 to bcrypt Jun 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant