Why Does Bcrypt Produce a Different Hash Each Time?
Bcrypt generates a new random salt for each password hash, so the same password normally produces different stored strings. Verification extracts the salt and cost from the stored hash and recomputes the candidate safely.
Read the parts of a bcrypt result
| Part | Secret? | Purpose |
|---|---|---|
| Password | Yes | User knowledge being verified |
| Salt | No | Makes each stored result unique |
| Cost | No | Controls computation required per guess |
| Pepper, if used | Yes | Adds a separately stored application secret |
Two valid results for one password
$2b$12$randomSaltA...derivedA
$2b$12$randomSaltB...derivedB
The strings should differ because their salts differ. Both can verify the same password. Comparing a newly generated string directly with the database value is the wrong test.
Difference is a security feature, not nondeterminism
A stored bcrypt string contains the format version, cost parameter, salt, and derived result. Because each call should create a fresh salt, two accounts with the same password do not expose that fact through identical database values. An attacker also cannot reuse one precomputed candidate result across every account; each salt requires separate work.
Applications therefore do not hash a login attempt with a brand-new salt and compare the strings. They pass the candidate password and the complete stored bcrypt value to the library verification function. The library reads the embedded parameters, repeats the derivation, and performs the comparison.
Cost, input limits, and migration
The bcrypt cost controls how expensive each guess is and should be tuned to a latency the authentication service can sustain. Raising it also raises defender CPU use, so benchmark on production-class hardware and rate-limit login attempts. Many bcrypt implementations only use the first 72 password bytes; confirm library behavior and use a modern password-storage API. New systems should evaluate Argon2id where available, while existing bcrypt stores can often be upgraded after successful login.
Verify a password without comparing hash text
Use the framework’s password-hash and verify functions rather than assembling bcrypt fields yourself.
Generate salts with the library’s secure default and store the complete returned hash string.
Benchmark the work factor, apply login throttling, and monitor authentication capacity.
Plan rehash-on-login when parameters or password-hashing algorithms need upgrading.
bcrypt mistakes that weaken password storage
- A salt is intentionally stored beside the hash; treating it as an encryption key misunderstands its role.
- Fast general-purpose hashes such as raw SHA-256 are not substitutes for password-hashing functions.
- Do not silently pre-hash passwords before bcrypt without following a reviewed construction; length and null-byte behavior can create new problems.
Salt, cost, and verification questions
Can I recover the password from a bcrypt hash?
Bcrypt is designed for verification rather than decryption. Attackers test guesses, which is why unique passwords, an appropriate work factor, and login controls matter.
Should identical bcrypt hashes ever occur?
They can if the same password, salt, version, and cost are reused, but normal password creation should generate a fresh random salt.
Verify with the right tool and context
Use the Bcrypt Hash Generator only with safe test data. Continue through the security collection.
Specifications and security guidance
OWASP Password Storage Cheat Sheet
Current password hashing, salting, work-factor, and bcrypt guidance.
PostgreSQL pgcrypto documentation
Explains adaptive password hashing, random salts, and verification with crypt.