Skip to content
Password hashing

Generate and verify bcrypt and Argon2id password hashes, in your browser

Two functions in one tool. Generate the hash of a password with bcrypt ($2y$ format) or Argon2id ($argon2id$ format), choosing the cost factor and the memory-hard parameters; or verify whether a password matches an existing hash. The salt is generated automatically on every run and everything happens entirely in the browser: the password is never sent to a server. Built for anyone implementing authentication in PHP, Laravel, Symfony or WordPress who wants to truly understand what password_hash() produces before shipping it.

Generate a hash

Verify a password

Enter a password and an existing hash: the tool recomputes locally and tells you whether they match. Handy for testing your login flow before writing the code.

How to use it

  1. 1

    Pick the algorithm and parameters

    Choose bcrypt for maximum compatibility or Argon2id for the memory-hard algorithm recommended today. For bcrypt set the cost factor (default 12); for Argon2id set memory, iterations and parallelism. The proposed defaults follow the OWASP 2026 recommendations.

  2. 2

    Generate the hash

    Type the password and hit Generate hash. A random salt is created automatically and embedded in the output. The same text produces a different hash on every click, and that is correct: the salt changes each time. The result is ready to drop into a password column in your database.

  3. 3

    Verify a match

    In the second card paste an existing hash and the clear-text password: the tool recomputes using the salt and parameters read from the hash and tells you whether they match. This is exactly what password_verify() does on the server, but here you can try it without writing any code.

  4. 4

    Take the result to production

    Copy the hash and compare it with what your backend generates: they should share the same prefix and structure. In production never copy hashes by hand: use password_hash() / password_verify() in PHP, Hash::make() in Laravel, your framework's native library. This tool is for understanding, testing and debugging, not for replacing your authentication code.

Why bcrypt or Argon2, and not MD5 or SHA

The password never leaves the browser. Hashing a password on a generic online service is a security contradiction: you are sending a clear-text credential to a third party. Here the computation happens entirely inside the tab, in JavaScript and WebAssembly, with no network request at all. You can verify it by opening the Network panel of your developer tools: type a password, generate the hash, and no HTTP request goes out. Once loaded, the page even works offline.

Passwords must not be hashed with fast functions. MD5, SHA-1 and SHA-256 are designed to be blazing fast: a modern GPU computes billions of them per second. Applied to a stolen database, that speed works for the attacker, who can try huge dictionaries of passwords in no time. On top of that, without a salt, identical passwords produce identical hashes and become vulnerable to precomputed rainbow tables. bcrypt and Argon2 do the opposite: they are deliberately slow and tunable, so every attempt costs the attacker time (and, for Argon2, memory too).

The salt is already inside the hash. A bcrypt hash like $2y$12$R9h/cIPz0gi.URNNX3kh2O... is a self-contained package: $2y$ is the version, 12 is the cost factor, the next 22 characters are the salt (128 random bits) and the rest is the actual digest (184 bits). For Argon2id, the output $argon2id$v=19$m=19456,t=2,p=1$salt$hash embeds version, memory/time/parallelism parameters, salt and digest. You do not need to store the salt in a separate column: verifying means reading those parameters back from the hash and recomputing. That is why password_verify() only needs the password and the hash, nothing else.

bcrypt or Argon2id: which one. For a new project the 2026 recommendation is Argon2id, which is memory-hard: it forces the attacker to spend a lot of RAM per attempt, neutralising the advantage of GPUs and ASICs that chew through bcrypt instead. bcrypt is still perfectly valid, it is everywhere (PHP, Laravel, Spring, Node) and has no special dependencies: its historical limit is that it truncates the password at 72 bytes and is not memory-hard. If your stack supports Argon2id, prefer it; if you must stay compatible with a bcrypt ecosystem, an adequate cost factor is still a solid choice.

Practical usage in frameworks

Plain PHP. Since 5.5 the standard library offers password_hash($pwd, PASSWORD_BCRYPT, ['cost' => 12]) and, when built with Argon2, password_hash($pwd, PASSWORD_ARGON2ID, ['memory_cost' => 19456, 'time_cost' => 2, 'threads' => 1]). Verification is always password_verify($pwd, $hash). Never concatenate a salt by hand: password_hash() generates one from a secure source. To bump the cost factor over time, call password_needs_rehash($hash, PASSWORD_DEFAULT) at login: if needed, rehash with the new parameters and store it.

Laravel. Hash::make($pwd) to generate, Hash::check($pwd, $hash) to verify, Hash::needsRehash($hash) for upgrades. The algorithm and parameters are configured in config/hashing.php (driver bcrypt or argon2id). Symfony exposes the same idea through the PasswordHasher component and the security.yaml configuration (algorithm: auto picks the best available).

WordPress. For years WordPress used phpass ($P$ prefix, key stretching over MD5): functional but dated. Since WordPress 6.8 (2025), new hashes use bcrypt, with transparent migration on each existing user's next login. If you work on plugins or migrations, always use wp_hash_password() and wp_check_password() rather than reimplementing the algorithm. The universal rule, in any language, is the same: do not write the password hashing function yourself, use the native one and test it. Reference: OWASP Password Storage Cheat Sheet.

Glossary

Technical terms used on this page, briefly explained.

bcrypt #
A password hashing function based on the Blowfish cipher, introduced by Niels Provos and David Mazières in 1999. Deliberately slow, with a tunable cost factor. Its 60-character output embeds version, cost and salt. Known limit: it truncates the password beyond 72 bytes. Common prefixes: $2a$, $2b$, $2y$ (PHP's variant).
Argon2 #
Winner of the Password Hashing Competition (2015) and the subject of RFC 9106. Three variants: Argon2d (GPU resistant), Argon2i (side-channel resistant), Argon2id (hybrid, the one to use). It is memory-hard: its parameters are memory, iterations (time) and parallelism. It is the default recommendation for new systems.
Salt #
A random value, unique per password, mixed into the input before hashing. It makes the hash of two identical passwords different and defeats precomputed rainbow tables. In bcrypt and Argon2 the salt is generated automatically and embedded in the hash: it does not need to be stored separately.
Cost factor #
In bcrypt, the parameter (typically 10-14) that sets the number of internal iterations as 2^cost. Each increment of 1 doubles the computation time. It keeps hashing slow enough to discourage brute force, yet fast enough not to degrade the login experience.
Work factor #
A generic term for the parameter that makes a password hashing function expensive: bcrypt's cost, or the memory/iterations/parallelism triple of Argon2 and scrypt. It should be calibrated on the production hardware and raised over time as CPUs get faster.
Memory-hard #
A property of a function (Argon2, scrypt) that requires a lot of RAM to compute, on top of time. It removes the attacker's advantage from GPUs and ASICs, hardware that is extremely fast at computation but limited in memory per core. bcrypt is not memory-hard: this is the key difference with Argon2id.
Rainbow table #
A precomputed table mapping hashes to their clear-text inputs, used to quickly invert unsalted hashes. A per-password unique salt makes it useless: the attacker would have to precompute a table for every possible salt. This is one reason unsalted MD5/SHA are unfit for passwords.
password_hash() #
PHP's native function (since 5.5) for generating secure password hashes. It takes the algorithm (PASSWORD_BCRYPT, PASSWORD_ARGON2ID) and the cost options, generates a secure salt and returns a self-contained string. Use it together with password_verify() and password_needs_rehash().
phpass #
Solar Designer's portable PHP password hashing framework, historically used by WordPress, Drupal and phpBB. In portable mode it applies key stretching over MD5 ($P$ prefix): better than a bare MD5, but superseded by bcrypt and Argon2. WordPress moved to bcrypt in version 6.8.

Frequently asked questions

Do the passwords I type stay in the browser?
Yes, and you can verify it. Open your developer tools (F12), go to the Network panel and start recording: generate or verify a hash and you will see no HTTP request go out. The bcrypt and Argon2 computation runs in JavaScript and WebAssembly inside the tab. No password, no hash and no parameter ever leave your computer. Once loaded, the page even works offline.
Why can't I use MD5 or SHA-256 for passwords?
Because they are too fast and not meant for this purpose. A modern GPU computes billions of MD5 or SHA hashes per second: applied to a stolen database, that speed lets the attacker try enormous password dictionaries in little time. On top of that, without a salt, two users with the same password produce the same hash and become vulnerable to rainbow tables. bcrypt and Argon2 are designed the other way around: slow, tunable and with an automatic salt.
What is the cost factor and how do I choose it?
In bcrypt the cost factor is the exponent that sets the number of iterations: 2^cost. A cost of 12 means 4096 iterations; moving to 13 doubles the time. The idea is to keep hashing slow for the attacker but tolerable at login (roughly 200-500 ms on production hardware). In 2026 a good starting point for bcrypt is 12, with an OWASP minimum of 10. Measure it on your own server and raise it over time.
bcrypt or Argon2id, which is better?
For a new project, Argon2id: it is memory-hard, so it forces the attacker to spend RAM per attempt and neutralises the GPU advantage. bcrypt is still valid, universal and simple to integrate, but it is not memory-hard and truncates the password at 72 bytes. In practice: if your stack supports Argon2id, use it; if you must stay compatible with a bcrypt ecosystem, an adequate cost factor is still a solid and extremely widespread choice.
What is the salt and do I store it separately?
The salt is a random value, unique per password, that makes even identical passwords hash differently and defeats rainbow tables. With bcrypt and Argon2 you do NOT store it separately: it is already embedded in the hash. In the bcrypt output it is the 22 characters after the cost factor; in Argon2id it is the segment between the parameters and the digest. Verification reads it back from there automatically.
Is the hash reversible? Can I recover the password?
No. bcrypt and Argon2 are one-way functions: you cannot go from the hash back to the password. Verifying does not mean decrypting, but recomputing the hash of the candidate password using the salt and parameters read from the stored hash, then comparing the two digests. That is exactly what this tool does in the verify card, and what password_verify() does on the server.
Can I paste a production hash here to verify it?
On this tool yes, because the computation is entirely client-side and offline: no data leaves the browser. In general, though, never paste production password+hash pairs into online services whose code you do not control: you would be sending real credentials to third parties. The safe rule is to verify only on local tools or on environments you know are client-side, like this one.
Why does the same text produce a different hash every time?
Because the salt is random and is regenerated on every computation. This is the correct, intended behaviour: two different hashes of the same password both remain verifiable, because each carries its own salt. If you expected a deterministic output you were thinking of a SHA-style hash, which for passwords is exactly what you should avoid.
Which cost or parameters should I use in production?
For bcrypt: cost 12 as the 2026 default, minimum 10, tuned to stay under 500 ms on your hardware. For Argon2id the OWASP minimum is 19 MiB of memory, 2 iterations and parallelism 1; if the server has RAM and CPU to spare you can go higher (say 46-64 MiB). The key is to measure on the real production machine, not on this browser, and to review the parameters periodically.
How do I integrate bcrypt or Argon2 in my code?
Do not reimplement the algorithm: use the native library. In PHP password_hash() and password_verify(); in Laravel Hash::make() and Hash::check(); in Symfony the PasswordHasher component; in Node libraries such as bcrypt or argon2. At login check password_needs_rehash() (or its equivalent) to gradually upgrade the cost factor without forcing users to change their password.

Who builds these tools?

Maurizio Fonte, senior IT consultant with 20+ years in PHP, Laravel, unmanaged Linux infrastructure, applied cybersecurity and AI/LLM integration. Production backends, legacy code modernization, security audits, custom AI agents and MCP servers: the work behind every tool published here.

About Maurizio Fonte