Backend

Password Hashing Explained for Backend Developers

Learn password hashing basics for backend systems, including salts, slow hashes, peppers, verification, resets, storage risks, and common mistakes.

Password hashing is how backend systems store passwords without storing the original password value.

If a database leaks, password hashes should make it expensive for attackers to recover the original passwords.

Quick answer

Never store plaintext passwords.

When a user creates or changes a password, the backend should hash it with a password-specific hashing algorithm and a unique salt. During login, the backend hashes the submitted password using the stored parameters and compares the result.

Password hashing is different from encryption. Encryption is reversible with a key. Password hashing is designed to be one-way.

Use a modern password hashing algorithm with configurable cost. Avoid fast general-purpose hashes such as plain SHA-256 or MD5 for password storage.

Hashing vs encryption

Encryption protects data by making it unreadable without a key. If you have the key, you can decrypt the data.

Password storage should not work that way. A backend does not need to recover the original password. It only needs to verify that a submitted password matches the stored password record.

That is why password storage uses one-way hashing.

Login verification usually looks like this:

stored record = algorithm + cost + salt + password_hash
candidate hash = hash(submitted_password, stored salt, stored cost)
allow login when candidate hash matches stored hash

The original password should not be logged, returned, emailed, or stored.

Why fast hashes are bad for passwords

General-purpose hashes are designed to be fast.

Fast is good for checksums, file integrity, and some data structures. Fast is bad for password storage because attackers can try many guesses quickly after a database leak.

Password hashing algorithms are intentionally slower and configurable. They are designed to make offline guessing more expensive.

The exact algorithm choice depends on the platform, security requirements, and available libraries, but the core principle is stable:

  • Use a password hashing algorithm, not a plain fast hash.
  • Use a unique salt per password.
  • Use a cost factor that can increase over time.
  • Store the algorithm and parameters with the hash.

What salts do

A salt is random data generated for each password hash.

The salt does not need to be secret. It prevents attackers from using one precomputed table for many users and ensures that two users with the same password do not get the same stored hash.

Example storage shape:

user_id: 42
password_algorithm: password-hash-v1
password_salt: random-per-user-value
password_hash: derived-hash-value
password_updated_at: 2026-06-30T10:00:00Z

Do not reuse the same salt for every user. Do not confuse a salt with a pepper.

What peppers do

A pepper is an additional secret value used during password hashing or verification.

Unlike a salt, a pepper must be kept secret and should not be stored in the same database as the password hashes.

A pepper can reduce damage if the database leaks but the application secrets remain safe. It also adds operational responsibility: secret storage, rotation planning, incident response, and careful deployment.

For many small systems, using a strong password hashing library correctly is more important than adding a pepper too early.

Password verification flow

A safe login flow should avoid leaking too much information.

At a high level:

1. Find the account by email or username.
2. If the account exists, verify the submitted password against the stored hash.
3. Apply rate limits and lockout or risk controls carefully.
4. Return a generic failure message for invalid credentials.
5. On success, create a session or issue tokens.

Avoid messages such as “email exists but password is wrong” on public login forms. They can help attackers enumerate accounts.

Read JWT vs Session Authentication for what happens after password verification succeeds.

Password resets

Password reset tokens are part of the password security story.

A reset token should be random, short-lived, single-use, and stored safely. If a reset token is stored server-side, store a hash of the token rather than the raw token value. That way, a database leak does not directly expose active reset links.

After a password reset, consider invalidating existing sessions or refresh tokens, especially for sensitive applications.

Read Access Token vs Refresh Token for token lifecycle tradeoffs after login.

Common mistakes

The first mistake is storing plaintext passwords. This should never happen.

The second mistake is hashing passwords with plain SHA-256, SHA-1, or MD5. These are too fast for password storage.

The third mistake is using one global salt for all passwords. Salts should be unique per password.

The fourth mistake is logging passwords, reset tokens, or credential headers during debugging.

The fifth mistake is returning detailed login errors that reveal which accounts exist.

The sixth mistake is building a custom password hashing scheme instead of using a reviewed library from the platform ecosystem.

Practical recommendation

Use the authentication library or framework support that correctly handles password hashing for your stack.

If you own the implementation, keep the design boring:

  • Hash passwords only with a password hashing algorithm.
  • Generate a unique salt for every password.
  • Store algorithm and cost parameters.
  • Use constant-time comparison where the library provides it.
  • Rate-limit login and password reset attempts.
  • Avoid detailed credential failure messages.
  • Rehash passwords when users log in if your cost settings need upgrading.

Password hashing is only one layer. You still need TLS, secure sessions, authorization checks, CSRF and XSS defenses, monitoring, and a safe reset flow.

Read Authorization vs Authentication for where password verification fits in the broader auth model, and MFA Explained for Web Apps for the next authentication layer after passwords. Read Secret Management Explained before adding peppers or credential rotation workflows. Read JWT vs Session Authentication for session and token choices after login.

For browser risks around authenticated users, read CSRF vs XSS and SameSite Cookies Explained. For the full security sequence, browse the Backend Security Learning Path.

Browse the full Topics map when you want to connect this guide with adjacent backend security, authentication, and API design content.