PBKDF2 Generator
Turn a password and salt into a PBKDF2 key with SHA-256, SHA-512 or SHA-1 and any number of iterations, or use scrypt or HKDF. Check the result against a key or a stored password hash. Everything runs in your browser.
PBKDF2-HMAC-SHA256("password", "salt", 600000) = 669cfe52…
Hash
Derived key
Type a password to see its key.
Everything is worked out in your browser. Your password is never sent anywhere.
How to generate a PBKDF2 key
- Type the password. Click the eye to see what you typed.
- Enter the salt, and say whether it is plain Text, Hex or Base64. For a new password, click Random to make one.
- Pick the hash (SHA-256 unless something else asks for another) and the number of iterations. The iterations box starts at OWASP's recommended count for SHA-256, SHA-512 and SHA-1.
- The key appears as soon as you stop typing. Copy it as hex or Base64, or as a ready-made Django password hash when the settings fit.
To check a password against a hash you already have, paste the hash into Check against a key or stored hash. A Django (pbkdf2_sha256$…) or Werkzeug/Flask (pbkdf2:sha256:…) hash carries its own salt and iterations: click Use these settings and type the password.
Worked example: password and salt
Take the password password and the salt salt, and run 600,000 iterations of HMAC-SHA256 for a 32-byte key. (Real salts should be random; these short ones make the example easy to repeat.)
Step 1: The settings
Step 2: The key in hex (64 characters)
Step 3: The same key in Base64
Step 4: As Django stores it
Result: 669cfe52…. Click Example in the tool to load these settings. You get the same key from code:
# Python
hashlib.pbkdf2_hmac('sha256', b'password', b'salt', 600000).hex()
// Node.js
crypto.pbkdf2Sync('password', 'salt', 600000, 32, 'sha256').toString('hex')
// PHP (length is in hex characters: 64 = 32 bytes)
hash_pbkdf2('sha256', 'password', 'salt', 600000, 64)PBKDF2 settings explained
PBKDF2 runs the password and salt through HMAC over and over, then hands back as many bytes as you ask for. Change any one of these four settings and you get a completely different key:
| Setting | What it does | What to choose |
|---|---|---|
| Hash | The hash used inside HMAC on every round. | SHA-256. SHA-512 is fine too; SHA-1 only to match an old system. |
| Salt | Makes the key different for every user, even when two people pick the same password. | At least 16 random bytes, new for every password. Store it next to the key. |
| Iterations | How many rounds to run. More rounds make every guess slower for an attacker. | 600,000 for SHA-256, 220,000 for SHA-512 (OWASP). |
| Key length | How many bytes come out. | The hash's own size: 32 bytes for SHA-256, 64 for SHA-512. Or what your cipher needs, such as 32 for AES-256. |
How many PBKDF2 iterations should I use?
As many as your server can afford while logging someone in. Each iteration costs an attacker the same as it costs you, so the count is what decides how many guesses per second they can make. OWASP's current minimums are:
| PBKDF2 with | Minimum iterations | Notes |
|---|---|---|
| HMAC-SHA256 | 600,000 | The usual choice. |
| HMAC-SHA512 | 220,000 | Fewer rounds because each SHA-512 round does more work. |
| HMAC-SHA1 | 1,400,000 | Only for older systems that need it. |
Frameworks go further: Django 6.1 uses 1,500,000 iterations of SHA-256 and Werkzeug (used by Flask) 1,000,000. The tool shows how long each key took, which gives a rough idea of the cost: aim for a few hundred milliseconds on the computer that will check the passwords. Older guides that say 1,000 or 10,000 iterations are out of date; computers have got far faster at guessing.
If you are matching an existing system, use whatever count it used. A stored hash only checks out with its original settings; to move to a higher count, re-hash each password the next time its owner logs in.
Why doesn't my PBKDF2 key match?
Because one setting is different, even slightly. Here is the worked example's key with one thing changed each time:
| What is different | Key starts with | What to do |
|---|---|---|
| Nothing: the worked example | 669cfe52… | This is the reference. |
| Salt 73616c74 read as text instead of hex | b3efcae6… | Set the salt to Hex. As hex it is the bytes of “salt”, which gives 669cfe52…. |
| 100,000 iterations | 0394a2ed… | Use the count the other system used. |
| SHA-512 instead of SHA-256 | 8abe2c1b… | Pick the same hash. |
| A space after the password | 0b701ba1… | Remove it; the tool warns about it. |
| 64-byte key instead of 32 | 669cfe52… (twice as long) | Same start, so only the length differs. The tool spots this. |
| PHP hash_pbkdf2 with length 32 | 669cfe52… (half as long) | PHP counts hex characters, not bytes. Use 64 for a 32-byte key. |
| Key written in Base64 | Zpz+Ukgh… | Same key. Switch the output to Base64. |
The salt is the most common culprit. Many libraries store it as hex or Base64 but feed the decoded bytes to PBKDF2, while Django and Werkzeug use the salt text itself. If a salt looks like hex, the tool asks whether you meant hex. Also check that the password is UTF-8: older .NET code that uses Encoding.Unicode turns the same text into different bytes.
PBKDF2 vs bcrypt, scrypt and Argon2
All four slow down password guessing; they differ in how hard they are to speed up with graphics cards and custom chips. For storing passwords, OWASP's order is Argon2id first, then scrypt, with bcrypt for older systems and PBKDF2 where FIPS-140 approved algorithms are required. HKDF is not on the list at all, because it is not meant for passwords.
| Function | Best for | Good to know |
|---|---|---|
| PBKDF2 | Passwords where FIPS-140 compliance matters; encryption keys from passwords. | Built into every browser and language. Needs very high iteration counts because graphics cards run it fast. |
| bcrypt | Existing systems that already use it. | Only the first 72 bytes of a password count. Work factor of at least 10. |
| scrypt | Passwords when Argon2id is not available. | Uses memory as well as time: N = 2^17, r = 8, p = 1 needs 128 MiB. Pick it in the tool above. |
| Argon2id | New password storage. | OWASP minimum: 19 MiB of memory, 2 iterations, 1 thread. |
| HKDF | Making several keys from one secret that is already random. | Fast on purpose. The info field gives each key its own purpose. Pick it in the tool above. |
Frequently asked questions
Can PBKDF2 be decrypted?
No. PBKDF2 is one-way: there is no key that turns the result back into the password. The only attack is guessing passwords and running PBKDF2 on each guess, which is exactly what a high iteration count makes slow.
Is the salt secret?
No. The salt is stored in plain sight next to the key, as Django and Werkzeug do inside the hash string. Its job is to be unique, so that one password list cannot be used to attack every user at once. What matters is a fresh random salt for every password.
What should I store with a PBKDF2 password hash?
Everything needed to repeat the calculation: the hash, the number of iterations, the salt and the key. A single string such as pbkdf2_sha256$600000$<salt>$<key> keeps them together and lets you raise the iterations later without breaking old passwords.
Is my password sent anywhere?
No. PBKDF2 and HKDF run in your browser's built-in cryptography, and scrypt runs in a background worker on your device. Nothing you type leaves your computer. Even so, don't paste live production passwords into any website.
Sources
- RFC 8018, PKCS #5: Password-Based Cryptography: the definition of PBKDF2
- OWASP Password Storage Cheat Sheet: iteration counts, scrypt and Argon2id settings, and the order to choose them in
- NIST SP 800-132: recommendation for password-based key derivation, including salt length
- RFC 7914, The scrypt Password-Based Key Derivation Function: scrypt and its N, r and p settings
- RFC 5869, HKDF: HMAC-based key derivation for secrets that are already random
- Django: Password management: the pbkdf2_sha256$iterations$salt$hash format
Related Tools
SHA-1 hashes of text or files, and Git object IDs.
SHA-256, SHA-384 and SHA-512 hashes of text or files.
Generate salts for encryption and hashing.
Break secrets into verifiable shares.