KAHIBARO
Discord Login Register

13.2. Password Storage

Why Password Storage Matters

When users create an account, they trust you with their passwords. If you store those passwords incorrectly, a database leak can instantly expose every account.

A backend developer must never store passwords in plain text. Even storing them with "simple encryption" is not enough. Proper password storage uses strong one‑way hashing with additional protections.

NEVER store plain text passwords. NEVER be able to read users' passwords.

In this chapter, you will see how to store passwords safely, what can go wrong, and how to use hashing correctly.


Plain Text Storage and Why It Is Dangerous

What Is Plain Text Storage?

Plain text storage means you keep the password exactly as the user typed it.

Example table in your database:

user_idemailpassword
1alice@example.commysecret123
2bob@example.com123456
3charlie@example.comqwerty

If an attacker gets a copy of this table, they immediately know every user’s password.

Dangers of Plain Text Passwords

Plain text passwords are dangerous because:

  1. Any data leak reveals all passwords immediately.
  2. Developers, admins, or support staff can see user passwords.
  3. Users reuse passwords. Attackers will try the same password on:
    • Email accounts
    • Social media
    • Other websites
  4. Your service loses trust. If users know you stored plain text, your reputation is damaged.

Even if you think your database is "internal" or "safe," you must assume it can be stolen one day.

If you can tell a user their current password, your storage is already wrong.


Why Encryption Is Not Enough

What Is Encryption?

Encryption is a two‑way process:

Example idea (not real code):

text
encrypted_password = encrypt("mysecret123", key)
plain_password = decrypt(encrypted_password, key)

Encryption is used for:

Why Encryption Is Wrong for Password Storage

For login, you never need to know the original password, you only need to verify "does the user know the password?"

If you use encryption:

So encryption turns password storage into "hidden plain text." It does not remove the danger.

Passwords must be stored using one‑way hashing, not reversible encryption.


One‑Way Hashing

What Is a Hash Function?

A hash function turns any input into a fixed‑length output.

Example idea:

text
hash("mysecret123") = "e99a18c428cb38d5f260853678922e03"
hash("hello")       = "5d41402abc4b2a76b9719d911017c592"

Characteristics of a cryptographic hash function:

Common cryptographic hash functions:

AlgorithmTypeNotes
MD5HashObsolete, insecure
SHA‑1HashObsolete, insecure
SHA‑256General hashSecure for many uses, not ideal alone for passwords
SHA‑512General hashSame as above

These general hash functions are too fast for password storage.

Basic Hashing Example

Naive idea:

  1. When user registers:
    • Store hash(password) in database.
  2. When user logs in:
    • Compute hash(input_password) and compare with stored hash.

Example data:

user_idemailpassword_hash
1alice@example.come99a18c428cb38d5f260853678922e03

This is better than plain text, but still unsafe on its own. Attackers can use rainbow tables and brute force attacks.


Salting: Defending Against Rainbow Tables

What Is a Salt?

A salt is a random string that you generate for each password.

You then compute:

$$
\text{stored\_hash} = H(\text{salt} \;||\; \text{password})
$$

Here, $H$ is a hash function and $||$ means "concatenate".

Example:

You store both the salt and the hash.

Table example:

user_idemailsaltpassword_hash
1alice@example.comK9n3!aZ@2#5f16b8...

Why Salting Helps

Without salt, many users share the same hash for the same password:

user_idemailpassword_hash
1alice@example.come10adc3949ba59abbe56e057f20f883e
2bob@example.come10adc3949ba59abbe56e057f20f883e

If e10adc... is known to mean 123456, the attacker instantly knows both passwords.

With salts:

user_idemailsaltpassword_hash
1alice@example.comabcd1234AAAA...
2bob@example.comxyz9876BBBB...

Even if both users chose 123456, their stored hashes are different. There is no single "hash for 123456" anymore, because the salt is different each time.

This prevents precomputed rainbow table attacks, where attackers use large tables of precomputed hash values.

Salt Requirements

A good salt must be:

You do not need to keep salts secret. You can store them in the same table as the hash.


Why Fast Hashes Are Not Enough

Even with salts, using a fast hash algorithm like SHA‑256 is not enough.

Reason: attackers can try billions of guesses per second with GPUs and specialized hardware.

Example idea:

So although salts prevent precomputed rainbow tables, they do not stop mass brute‑force attempts if the hashing is too cheap.

You need functions that are:

Password Hashing Algorithms

Key Idea: Make Hashing Expensive

For password storage, you intentionally make hashing expensive. Not too slow for your users, but slow enough that guessing millions of passwords becomes impractical.

You use special functions called password hashing functions or key derivation functions.

Common choices:

AlgorithmTypeStatus / Recommendation
bcryptPassword hashingVery common, good choice
scryptPassword hashing, memory‑hardStrong, good choice
Argon2idPassword hashing, memory‑hardModern recommended standard
PBKDF2Key derivation, slowerWidely used, acceptable with enough iterations

Any of these is far better than a raw hash like SHA‑256 alone.

Do not design your own password hashing algorithm. Use a well tested, standard one like bcrypt, scrypt, Argon2, or PBKDF2.

bcrypt

Example bcrypt hash string:

text
$2b$12$9C8p4pY/.gQ1qrnOZwZQBuTVqYsZQkUpY..sh1BfXZ4VtaxGE7C2q

You do not manage the salt manually. The library handles it.

scrypt and Argon2

They are considered very strong for password storage.


How Password Verification Works

The main idea:

  1. At registration or password change:
    • Take the plain text password.
    • Use a password hashing algorithm (argon2, bcrypt, etc.).
    • Store only the hash output (which also encodes the salt and parameters).
  2. At login:
    • Take the user’s input password.
    • Run the same hashing algorithm with the stored parameters.
    • Compare the resulting hash with the stored hash.
    • If they match, the password is correct.

You never decrypt anything. You only recompute and compare.


Example: Using bcrypt in Practice

The exact code depends on the language and framework. This is a conceptual example in Python style, which you can adapt.

Registration Flow

  1. User sends:
json
{
  "email": "alice@example.com",
  "password": "MySuperSecret!"
}
  1. Your backend:
python
import bcrypt
plain_password = "MySuperSecret!".encode("utf-8")
hashed = bcrypt.hashpw(plain_password, bcrypt.gensalt())  # gensalt chooses salt and cost
print(hashed)  # something like b"$2b$12$9C8p4pY/.gQ1qrnOZwZQBuTVqYsZQkUpY..sh1BfXZ4VtaxGE7C2q"
user_idemailpassword_hash
1alice@example.com$2b$12$9C8p4pY/.gQ1qrnOZwZQBuTVqYsZQkUpY..sh1BfXZ4VtaxGE7C2q

You store only this string, not the plain password and not a separate salt.

Login Flow

  1. User sends:
json
{
  "email": "alice@example.com",
  "password": "MySuperSecret!"
}
  1. Your backend:
python
stored_hash = b"$2b$12$9C8p4pY/.gQ1qrnOZwZQBuTVqYsZQkUpY..sh1BfXZ4VtaxGE7C2q"
plain_password = "MySuperSecret!".encode("utf-8")
if bcrypt.checkpw(plain_password, stored_hash):
    # Password correct
else:
    # Password incorrect

bcrypt extracts the salt and cost from the stored hash, then compares in a safe way.


Handling Password Changes

When a user changes their password:

  1. Verify current password using the existing stored hash.
  2. If correct, hash the new password using your password hashing function.
  3. Replace the old hash with the new one.

Old password is gone forever. You cannot retrieve it.


Upgrading Hash Algorithms

You might start with one algorithm and later choose a stronger one. For example:

You cannot convert old hashes directly, because hashing is one‑way. Instead, you upgrade gradually.

Typical strategy:

  1. Store information about which algorithm and parameters were used, usually encoded in the hash string.
  2. On login:
    • Verify using the appropriate algorithm for the stored hash.
    • If login succeeds and the hash uses an old algorithm or weak parameters:
      • Rehash the password with the new algorithm.
      • Store the new hash.

Example flow:

Over time, as users log in, their password hashes get upgraded without forcing everyone to reset passwords at once.


Common Mistakes in Password Storage

Here are patterns to avoid.

1. Storing Plain Text or Reversible Encryption

Bad:

If someone has database + key, they have every password.

2. Using Fast Hashes Alone

Bad patterns:

Even if salted, fast hashes are easy to brute force.

3. Custom or Obscure Algorithms

Bad idea:

Security is hard. Use standard, tested algorithms implemented by experts.

4. Short or Non‑Random Salts

Avoid:

Use secure random salts, unique per password, and let libraries manage them when possible.


Practical Recommendations

For beginner backend developers, follow these simple rules.

Password Storage Rules

  1. Never store plain text passwords.
  2. Never use reversible encryption for passwords.
  3. Always use a password hashing function such as bcrypt, scrypt, Argon2, or PBKDF2.
  4. Always use salts. Prefer libraries that manage salts for you.
  5. Configure hashing to be slow enough to resist brute force, but still fast enough for users.
  6. Plan for algorithm upgrades over time.

Suggested Algorithms

If your environment supports it:

For example:

Example: Data Model for User Passwords

A typical users table might have:

ColumnTypeDescription
idinteger PKUser identifier
emailstringUnique email address
password_hashstringFull password hash (algorithm + params + salt)
created_attimestampCreation time
updated_attimestampLast update time

You do not need separate columns for salt or algorithm if you use formats that encode them inside the hash string, such as bcrypt or Argon2.


How This Fits With Other Authentication Topics

In the broader authentication system you will:

But all of that depends on this fundamental step: store passwords correctly and safely.

Once your password storage is secure, you can build the rest of your authentication system with much more confidence.

Views: 6

Comments

Please login to add a comment.

Don't have an account? Register now!