Password Hashing in the Browser: Why This Isn't Literal Bcrypt, and Why That's the Right Call
This tool generates a salted, adaptive-cost password hash using PBKDF2-HMAC-SHA256, a real and standards-recommended algorithm — but it does not produce the literal $2b$ bcrypt format, because there's no honest way to implement true bcrypt (which relies on a specific Blowfish key-schedule variant) safely from scratch in a browser tool. Rather than fake the output format, this page is upfront about the substitution and why it's still a legitimate choice.
Output format: $pbkdf2-sha256$iterations$salt$hash — self-describing, not bcrypt-compatible.
Why Not Just Implement Bcrypt?
Bcrypt's algorithm (based on a modified Blowfish cipher with an expensive key setup) requires exact, bit-perfect implementation of the Blowfish P-array and S-box initialization constants and the EksBlowfishSetup routine. A subtly wrong implementation wouldn't necessarily error — it would silently produce hashes that look plausible but don't match any reference implementation, which is a far worse outcome than clearly using a different, correctly-implemented algorithm.
PBKDF2 Is a Legitimate Standard, Not a Downgrade
PBKDF2 is specified in NIST SP 800-132 and RFC 8018, and it's the password-hashing algorithm actually used in production systems like Django's default password hasher and WPA2's Wi-Fi key derivation. It shares bcrypt's core properties — a random salt to defeat rainbow tables, and a tunable, deliberately slow cost factor to resist brute-forcing — implemented via the browser's native, security-audited Web Crypto API rather than hand-written code.
What the Cost Factor Actually Buys You
Each increment of the cost factor doubles the number of PBKDF2 iterations, doubling the time needed to compute (or brute-force) a single hash. A legitimate login only pays this cost once per attempt, but an attacker trying millions of password guesses against a stolen hash pays it millions of times — the entire design goal of adaptive password hashing.
Practical Examples
Hashing a New User's Password
What gets stored in the database.
- 1.Password: user's chosen password
- 2.Cost factor: 15 (32,768 iterations)
- 3.Store: $pbkdf2-sha256$32768$
$
Verifying a Login Attempt
Recomputing and comparing.
- 1.Paste the stored hash and the attempted password
- 2.Tool re-derives the hash using the same salt and iteration count
- 3.Match/no-match result
What This Tool Actually Provides
- Real cryptographic salting: CSPRNG-generated per hash
- Real adaptive cost: configurable PBKDF2 iterations
- Native Web Crypto: no hand-rolled crypto primitives
- Self-describing format: algorithm and parameters embedded in the output
When You Need Real Bcrypt Instead
- Verifying existing $2a$/$2b$/$2y$ hashes from another system
- A specific compliance requirement naming bcrypt by name
- Interop with a system that only accepts bcrypt-format hashes
- Use a proper server-side library (bcrypt, bcryptjs) for these cases
Frequently Asked Questions
Does this produce a real $2b$ bcrypt hash?
No, and this is worth being explicit about: browsers have no native bcrypt/Blowfish primitive, and implementing bcrypt by hand from scratch is exactly the kind of custom cryptography that's easy to get subtly wrong in ways that are hard to detect. This tool uses PBKDF2-HMAC-SHA256 instead — a real, standard, NIST-recommended (SP 800-132) password-hashing algorithm with the same core properties (salted, adaptive cost) that's natively available via the browser's Web Crypto API.
Is PBKDF2 actually as good as bcrypt?
Both are legitimate, widely-used password hashing algorithms with adaptive cost factors. bcrypt and Argon2 are generally considered somewhat more resistant to GPU/ASIC cracking attacks than PBKDF2 due to differences in memory-hardness, but PBKDF2 is still an accepted, standards-body-recommended choice — it's what's used by many real systems (including Django's default, and WPA2 Wi-Fi key derivation).
What's the 'cost factor' actually controlling?
It's the number of PBKDF2 iterations, expressed as a power of 2 (like bcrypt's own cost parameter) — higher means slower to compute, which is intentional. A slower hash function makes brute-force password guessing proportionally slower for an attacker, while a single legitimate login only pays that cost once.
Can I verify a real bcrypt hash with this tool?
No — the verify feature only checks hashes in this tool's own $pbkdf2-sha256$ format. To verify or generate real bcrypt hashes, use a server-side library (like bcrypt in Node.js, or password_hash() in PHP) — those exist specifically because bcrypt needs a proper, audited implementation.
Why not just use SHA-256 directly for password hashing?
Plain SHA-256 is designed to be fast, which is exactly the wrong property for password hashing — a fast hash lets an attacker try billions of guesses per second on stolen hashes. PBKDF2 deliberately repeats the hash thousands of times specifically to slow that down, which is the entire point of the cost factor.
Is my password sent anywhere?
No, all hashing happens locally in your browser via the Web Crypto API — nothing is transmitted. That said, avoid pasting real production passwords into any browser tool as a general precaution.