# How I think about bcrypt when storing passwords

A beginner-friendly guide to bcrypt, password hashing, salts, cost factors, verification, and why password hashes are different from encryption.

- Date: 2026-09-27
- URL: https://ilham.dev/posts/how-to-hash-passwords-with-bcrypt/
- Markdown: https://ilham.dev/posts/how-to-hash-passwords-with-bcrypt/index.md
- Tags: bcrypt, passwords, security, tools
- Reading time: 3 min


Passwords should not be stored as plain text. If a database leaks, plain text
passwords immediately become everyone else's problem too.

For password storage, I want a password hashing function such as bcrypt. The
[bcrypt](/tools/bcrypt/) tool helps demonstrate how hashing and verification work.

## Hashing is not encryption

Encryption is meant to be reversed with a key.

Password hashing is different. A password hash is meant to be checked, not decrypted.

The login flow is:

```text
user enters password -> hash it -> compare with stored hash
```

The app does not need to recover the original password.

## What bcrypt gives you

bcrypt is designed for passwords. It includes:

- a salt;
- a cost factor;
- a slow hashing process.

Slow is good here. It makes large-scale guessing more expensive.

## What a bcrypt hash looks like

A bcrypt hash may look like this:

```text
$2b$12$...
```

The `12` is the cost factor. Higher cost means slower hashing.

The salt is stored inside the hash string, so you do not need a separate salt column
for normal bcrypt usage.

## Step 1: hash a test password

Open [bcrypt](/tools/bcrypt/) and enter a test password, not a real production
password.

Choose a cost factor. For demos, a low or moderate cost is fine. For production, the
right cost depends on your server and login performance budget.

Generate the hash.

## Step 2: verify the password

Now paste the password and the hash into the verify section.

If the password matches, verification passes.

If you change one character in the password, verification fails.

That is the normal login check.

## Step 3: notice that the same password can produce different hashes

Because bcrypt uses a random salt, hashing the same password twice can produce
different hash strings.

That is expected.

Verification still works because the salt is included in the stored hash.

## Step 4: choose cost carefully

A higher cost makes bcrypt slower. That helps security, but it also uses more CPU on
login.

The practical rule:

> Choose the highest cost that is still acceptable for your login performance.

Do not copy a cost value forever. Revisit it as hardware changes.

## Step 5: still use other protections

bcrypt is important, but it is not the whole security story.

Also use:

- HTTPS;
- rate limiting;
- 2FA for important accounts;
- password reset tokens with expiry;
- breach monitoring if possible;
- unique password rules without forcing weird patterns.

## My bcrypt checklist

When handling passwords, I check:

1. Are passwords never stored as plain text?
2. Is the app using a password hashing function like bcrypt or Argon2?
3. Is the cost factor intentional?
4. Is verification done by comparing password to hash, not decrypting?
5. Are login attempts rate-limited?
6. Are test passwords used in demos, not real ones?

bcrypt is not complicated at the concept level: store the hash, not the password;
verify by hashing the login attempt and comparing safely.
