Hash and verify passwords with bcrypt, scrypt, Argon2id and PBKDF2 entirely in your browser — generate PHC-format strings, check a candidate password against an existing hash, and inspect the parameters hidden inside it. Nothing is uploaded.
For test passwords only. Real user passwords should never be pasted into any web page. This tool runs entirely in your browser — the strings never leave your tab — but a real breach begins with a single paste.
Mode
Algorithm (PBKDF2 is on the Password KDF tab of the HMAC page too — here it is aimed at password storage)
Password (UTF-8 encoded; leave empty if you really mean the empty password)
Stored hash (paste any $2a$/$2b$/$2y$ bcrypt, $argon2id$, $scrypt$ or $pbkdf2-sha256$ string — PHP password_hash() output works)
The defaults on this page sit at or above every minimum. For production pick Argon2id first, scrypt or bcrypt if it is unavailable, PBKDF2 only for FIPS-compliance reasons.
PHP interop — password_hash($pw, PASSWORD_BCRYPT) emits $2y$10$...: paste it into Verify with the candidate password and this page answers exactly what password_verify() would. PASSWORD_ARGON2ID output ($argon2id$v=19$m=65536,t=4,p=1$...) verifies too. PHC strings from passlib, django-argon2 and crypto.scrypt wrapping also parse.
Self-test
Re-runs the page engine against public vectors: the crypt_blowfish test suite for bcrypt, node/OpenSSL-generated scrypt and Argon2id strings, the PBKDF2 vectors from RFC 6070 and the public SHA-256 set, plus generate-then-verify roundtrips in every algorithm and negative tests (wrong password must fail, malformed strings must be rejected). Nothing is sent anywhere.
Password hashing explained from scratch
In one sentence: a password hash is deliberately slow (and preferably memory-hungry) so that stealing the database does not let an attacker try billions of guesses per second — the opposite goal of a fast hash like SHA-256, which is built for speed.
Why not just SHA-256 the password?
SHA-256 on a modern GPU runs at billions of guesses per second. A 8-character password has well under 1013 combinations — hours of GPU time, minutes on a big rig. Password hashing functions (KDFs) fight this with cost parameters: bcrypt repeats its core 2cost times, PBKDF2 iterates HMAC hundreds of thousands of times, scrypt and Argon2id additionally demand megabytes of memory per guess so GPUs (fast but memory-poor per core) lose their advantage. A salt — random, stored in the clear inside the hash string — stops precomputed rainbow tables and forces every guess to be computed fresh for each user.
The four algorithms on this page
Algorithm
Year
Hardness
Signature format
Watch out for
bcrypt
1999
CPU (2cost key setups)
$2b$12$ + 22-char salt + 31-char hash
72-byte password limit (everything past 72 is silently ignored); NUL byte ends the password in the original C implementation
PBKDF2
2000 (RFC 2898/8018)
CPU (iterations)
$pbkdf2-sha256$i=600000$ + salt + hash (passlib style)
no memory cost — GPUs and ASICs love it; only iteration count is tunable
scrypt
2009 (RFC 7914)
CPU + memory (128·N·r bytes)
$scrypt$ln=14,r=8,p=1$ + salt + hash
N must be a power of two; memory grows linearly with r
Argon2id
2015 (PHC winner, RFC 9106)
CPU + memory (m KiB, t passes)
$argon2id$v=19$m=19456,t=2,p=1$ + salt + hash
Argon2i (data-independent) vs Argon2d (data-dependent) vs Argon2id (hybrid) — always pick id unless you know why not
Memory-hardness vs compute-hardness
A GPU has thousands of cores but each core has access to only a little fast memory. A KDF that needs 19 MiB of working set per guess limits an attacker to as many parallel guesses as they have 19-MiB chunks of memory — which is why Argon2id at 19 MiB can be stronger in practice than bcrypt at cost 15 despite taking less wall-clock time on your laptop. PBKDF2 has no answer to this: its only dial is iteration count, and silicon scales that linearly.
Reading a PHC string
The modular-crypt / PHC format is self-describing: in $argon2id$v=19$m=19456,t=2,p=1$ICEiIyQlJicoKSorLC0uLw$WTGpK4hf... the fields are algorithm, version, parameters (m = memory in KiB, t = passes, p = lanes), base64 salt, base64 hash. bcrypt predates the standard and uses its own compact form: $2b$ variant, 12 cost, then salt and hash in bcrypt's custom base64 alphabet (./A-Za-z0-9). This page's Verify accepts all of these and shows the parsed fields — paste any hash you find and see what it decomposes into.
Common mistakes
Fast hash for passwords. MD5/SHA-1/SHA-256 password columns fall to commodity GPUs at billions of guesses per second. Use the Hash Generator for files and data; use this page's algorithms for passwords.
Sharing a salt. One salt for all users means equal passwords have equal hashes and rainbow tables come back. Every hash here gets a fresh 16-byte random salt.
Ignoring bcrypt's 72 bytes."a"*100 and "a"*72 hash identically — the tail is dropped. This page warns at the input box when the password exceeds 72 bytes. Argon2 has no such limit.
Comparing hashes with == in your own code. Verification must be constant-time; the page engine does that internally (it recomputes and compares the stored bytes), but if you copy the approach, use a constant-time compare.
Tuning parameters on a fast dev machine. Target ~250–500 ms of hashing on your production users' median hardware, not your workstation. The Benchmark button shows what this browser actually experiences.
Rehashing on every login check. Verify first; only rehash (e.g. to raise the cost) after a successful verify, and store the new string. The PHP function password_needs_rehash() exists for exactly this.
FAQ
Which one should I pick? Argon2id with at least OWASP minimums. If the runtime does not offer it: scrypt, then bcrypt (cost so that hashing takes ≥250 ms). PBKDF2 only where certification requires it.
Why is a random salt shown in the output string? The salt is not a secret — it is stored in clear inside the PHC string on purpose, so verification needs nothing but the string and the candidate password. Its job is uniqueness, not secrecy.
Does the variant matter ($2a$ / $2b$ / $2y$)? For ASCII passwords they produce identical hashes; $2a$ is the 1990s original, $2b$ fixed a rare sign-extension bug (2014), $2y$ is PHP's marker that the fix is present. Verify accepts all three.
How long should a hash take? Roughly 250–500 ms per login on server hardware. Under 100 ms and offline cracking is cheap; over 1 s and users complain before security improves.
Can I verify a hash produced elsewhere? Yes — paste it and give the candidate password. Known-good formats: PHP password_hash (bcrypt $2y$ and Argon2id), Python passlib, django's argon2 hasher, and the scrypt string format used by Tarsnap's scrypt tool.
What does the "benchmark" button do? It hashes the current password once with each algorithm at page-default parameters and reports wall-clock time in this browser — a feel for cost differences, not a rigorous measurement.