PBKDF2 Key Derivation Generator & Verifier
Derive keys and password hashes with PBKDF2-HMAC using your own salt, iteration count and key length, then check a password against a stored Django, passlib or Werkzeug PBKDF2 hash.
Private by design: anything you enter is processed in your browser only. It is never uploaded to or logged on our servers. Keys are derived with your browser's built-in Web Crypto API. Passwords are never included in share links, only the salt, settings and stored hash.
Derive Key
Encoded as UTF-8 before hashing.
Check Password Against Stored Hash
Supports Django (pbkdf2_sha256$, pbkdf2_sha1$), passlib ($pbkdf2$, $pbkdf2-sha256$, $pbkdf2-sha512$) and Werkzeug/Flask (pbkdf2:sha256:).
- Format
- PRF
- Iterations
- Salt
- Hash
About PBKDF2
PBKDF2 (Password-Based Key Derivation Function 2, defined in RFC 8018 / PKCS #5) turns a password into a key of any length by running a pseudorandom function, almost always HMAC, thousands or millions of times over the password and a salt. The iteration count makes every guess expensive for an attacker, and the salt makes each hash unique so precomputed tables do not work. It is used for password storage (Django's default hasher), Wi-Fi WPA2 keys, password managers, and to derive encryption keys from passphrases.
Choosing parameters: use a random salt of at least 16 bytes per password, HMAC-SHA256 or HMAC-SHA512, and the highest iteration count your login latency allows. The OWASP Password Storage Cheat Sheet currently recommends 600,000 iterations for PBKDF2-HMAC-SHA256, 220,000 for HMAC-SHA512 and 1,400,000 for the legacy HMAC-SHA1 (the 2023 edition listed 600,000, 210,000 and 1,300,000). Asking for a key longer than the hash output (for example 64 bytes from SHA-256) runs the whole iteration count again for every extra block, which costs you as much as it costs an attacker, so stored password hashes normally use exactly the digest length.
Verifying stored hashes: Django stores pbkdf2_sha256$iterations$salt$hash with a text salt and a standard Base64 hash. Python's passlib uses $pbkdf2-sha256$iterations$salt$hash, where the raw salt and hash are encoded in an "adapted" Base64 that uses . instead of + and drops the padding. Werkzeug and Flask use pbkdf2:sha256:iterations$salt$hexhash. The verifier detects all three, recomputes the hash with the embedded parameters and compares it with the stored value, which is handy when migrating users between frameworks.
PBKDF2 is not memory-hard, so GPUs and ASICs can test guesses far faster than a CPU. For new systems that do not need FIPS-140 compliance, OWASP prefers Argon2id or scrypt, and bcrypt is still a good choice. To compute plain digests use the hash generator, for message signatures use the HMAC generator, and create test passwords with the password generator. Avoid typing real production passwords into any web page.
Reference Guide
Recommended iteration counts (OWASP Password Storage Cheat Sheet):
| PRF | Output size | OWASP current | OWASP 2023 | Notes |
|---|---|---|---|---|
| HMAC-SHA256 | 32 bytes | 600,000 | 600,000 | Recommended; also the FIPS-140 choice |
| HMAC-SHA512 | 64 bytes | 220,000 | 210,000 | Fewer iterations because each one is more expensive on GPUs |
| HMAC-SHA1 | 20 bytes | 1,400,000 | 1,300,000 | Legacy only; do not choose for new systems |
| HMAC-SHA384 | 48 bytes | No separate figure | Rarely used for password storage | |
Stored hash formats recognised by the verifier:
| Framework | Format | Salt | Hash encoding |
|---|---|---|---|
| Django | pbkdf2_sha256$<iter>$<salt>$<hash> (also pbkdf2_sha1) | Text, used as UTF-8 bytes | Standard Base64 |
| passlib | $pbkdf2-sha256$<iter>$<salt>$<hash> (also $pbkdf2$ = SHA-1, $pbkdf2-sha512$) | Raw bytes, adapted Base64 | Adapted Base64 (. for +, no =) |
| Werkzeug / Flask | pbkdf2:sha256:<iter>$<salt>$<hash> | Text, used as UTF-8 bytes | Hex |
Published test vectors you can reproduce with this tool:
| Source | PRF | Password / Salt | Iterations | Length | Derived key (hex) |
|---|---|---|---|---|---|
| RFC 6070 | SHA-1 | password / salt | 1 | 20 | 0c60c80f961f0e71f3a9b524af6012062fe037a6 |
| RFC 6070 | SHA-1 | password / salt | 4096 | 20 | 4b007901b765489abead49d926f721d065a429c1 |
| RFC 7914 | SHA-256 | passwd / salt | 1 | 64 | 55ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783 |
| RFC 7914 | SHA-256 | Password / NaCl | 80000 | 64 | 4ddcd8f60b98be21830cee5ef22701f9641a4418d04c0414aeff08876b34ab56a1d425a1225833549adb841b51c9b3176a272bdebba1d078478f62b397f33c8d |
Example input
Password: correct horse battery staple Salt: seasalt2026tb (text) PRF: HMAC-SHA256, 600,000 iterations, 32 bytes Stored: pbkdf2_sha256$1500000$seasalt2026tb$9cbQp/s09aNPFdlLid4XC2MUg/mKe2d52vBuVJNOusQ=
This sample loads automatically when you open the tool. Use Load Sample to bring it back.
Frequently Asked Questions
PBKDF2 (Password-Based Key Derivation Function 2) turns a password and a salt into a key by running HMAC many thousands of times. The repetition makes each guess slow for an attacker, which protects stored passwords and password-derived encryption keys.
Use as many as your login latency allows. OWASP currently recommends 600,000 iterations for PBKDF2-HMAC-SHA256. For new systems, Argon2id or bcrypt are usually better choices.
A unique random salt per password means identical passwords produce different keys, which defeats precomputed rainbow tables. Store the salt next to the hash; it does not need to be secret.
Related Tools
All Security Tools →SSH Key Generator & Fingerprint Tool
Generate Ed25519 or RSA SSH key pairs in your browser and ca...
Secrets & PII Scrubber
Mask API keys, tokens, passwords, emails, phone numbers, car...
Credit Card & IBAN Validator
Check credit card numbers with the Luhn algorithm and detect...
Crop Image Tool
Crop image files with exact x/y coordinates and output dimen...
Watermark on Image
Apply text or image watermark overlays to photos and graphic...
Meme Creator Online
Upload an image and place styled text anywhere to create mem...