Skip to main content

PBKDF2 Hash Generator

Derive cryptographic keys from passwords using PBKDF2 with configurable iterations, salt and hash function.

Reviewed by · Last reviewed

Deriving a Key from a Password

  1. Type the password into the password field. This is the low-entropy human secret you want to stretch into a full cryptographic key.
  2. Choose the salt strategy. Leave "Auto-generate" on to get a fresh 16-byte random salt from crypto.getRandomValues on every run, or paste a specific hex salt when you need to reproduce a previously stored hash for verification.
  3. Set the iteration count. 100,000 is the minimum OWASP floor for PBKDF2-HMAC-SHA-256; 600,000 is the 2023 OWASP recommendation; 1,300,000 matches 1Password\'s current production setting.
  4. Pick key length and hash function. 32 bytes (256 bits) paired with SHA-256 is the correct default for deriving AES-256 keys; 64 bytes with SHA-512 if you need a longer output split into multiple subkeys.
  5. Click "Generate Hash". The derived key hex appears alongside the salt hex. Both are needed for verification - store them together, same as a bcrypt string stores cost, salt, and hash in one field.

How PBKDF2 Turns a Weak Password into a Strong Key

PBKDF2 is specified in RFC 8018 section 5.2 (PKCS #5 v2.1) and approved by NIST SP 800-132. The construction takes password P and salt S and computes F(P, S, c, i) = U_1 XOR ... XOR U_c where U_1 = HMAC(P, S || INT(i)) and U_j = HMAC(P, U_{j-1}). The iteration count c forces an attacker to repeat the HMAC chain for every candidate; the salt prevents rainbow-table precomputation. The implementation uses crypto.subtle.importKey('raw', passwordBytes, 'PBKDF2', false, ['deriveBits']) then crypto.subtle.deriveBits({ name: 'PBKDF2', salt, iterations, hash }, keyMaterial, keyLength * 8). The browser\'s native crypto (BoringSSL, NSS) runs HMAC-SHA-256 at around 200MB/sec, so 600,000 iterations takes around 100 milliseconds. That delay is the point: multiplied by billions of candidate passwords, offline brute force becomes infeasible.

When PBKDF2 Is the Right Call

  • Storing user passwords in a system that needs to survive a database dump. Salt + iteration-hardened hash means the LinkedIn 2012 scenario (6.5M passwords, 90+ percent recovered) becomes infeasible.
  • Deriving an encryption key from a user passphrase for client-side file encryption (1Password vault unlock, Bitwarden key derivation, LastPass vault key).
  • Building a WPA2/WPA3-Personal pre-shared key: PBKDF2-HMAC-SHA-1 with 4096 iterations is the IEEE 802.11 spec.
  • TLS pre-shared key derivation for IoT devices that cannot afford the complexity of Argon2.
  • Signed cookie keying where the server wants to rotate the encryption key from a master passphrase without storing the passphrase.
  • Regulatory compliance with FIPS 140-3 validated cryptographic modules - PBKDF2 is explicitly approved; Argon2 is not yet on the FIPS-approved list.

Iteration Counts, Salt Reuse, and Deployment Pitfalls

The most common PBKDF2 mistake is hardcoding iteration count at deploy time and never updating it. The 2010 OWASP recommendation was 10,000 for SHA-1; by 2023 it was 600,000 for SHA-256 because GPUs got 60x faster. If your app still uses 10,000 iterations in 2026, a rented RTX 5090 cracks a 10-character password in hours. The fix is an upgradeable cost parameter stored alongside the hash; on successful login, if the stored count is below current policy, re-derive and update. Second pitfall: salt reuse - if every user gets the same salt, rainbow tables become viable. Salt must be per-user and at least 16 bytes from a CSPRNG. Third: middleware that truncates passwords at 72 bytes (bcrypt habit) or at Unicode boundaries causes collisions between different long passwords. NIST SP 800-132 requires at least 8-byte salt; modern consensus is 16 bytes.

RFC 8018 PBKDF2, NIST SP 800-132, and the Password-Hashing Landscape

PBKDF2 is the elder statesman: RFC 2898 (2000) then RFC 8018 (PKCS #5 v2.1, 2017), approved by NIST SP 800-132. Its weakness relative to modern alternatives is parallelism: HMAC alone is trivially GPU/ASIC parallelizable. bcrypt (1999) introduced sequential memory patterns that punish GPU porting. scrypt (RFC 7914) added memory-hardness - 128MB RAM per guess makes cracking rigs expensive. Argon2 (PHC winner 2015, RFC 9106) is state of the art with three variants: Argon2d, Argon2i, and Argon2id (OWASP 2024 recommendation). OWASP\'s 2024 cheat sheet ranks them Argon2id > scrypt > bcrypt > PBKDF2. PBKDF2 remains acceptable because it is in every stdlib and FIPS-approved; use Argon2id when you can.

PBKDF2 in the Browser vs CLI vs Native Libraries

The Web Crypto deriveBits path here produces identical output to openssl kdf -kdfopt digest:SHA256 -kdfopt pass:"mypassword" -kdfopt hexsalt:... -kdfopt iter:600000 -keylen 32 PBKDF2 or hashlib.pbkdf2_hmac("sha256", password, salt, 600000, 32) in Python. The browser implementation has one practical advantage: it runs on the user\'s device, so the password never touches the server - exactly the architecture 1Password and Bitwarden use for vault unlock. For server-side password verification, use bcrypt, argon2, or phc-crypto libraries rather than hand-rolling PBKDF2. Never roll your own in pure JavaScript: naive implementations leak timing through non-constant-time === comparison.

Frequently Asked Questions

Why does the tool take a noticeable moment to finish at 600,000 iterations?

That pause is the entire security property. PBKDF2-HMAC-SHA-256 at 600,000 iterations on a typical laptop runs in roughly 100-300 milliseconds. An attacker with a GPU cluster still has to spend proportional time per candidate password; even at 1,000 GPUs that is hundreds of thousands of candidates per second per device, but a 16-character random password has 10^30 possibilities. The delay is calibrated so legitimate login feels instant while offline cracking is economically infeasible. If your app feels sluggish at 600k iterations, the fix is a server-side worker or WebWorker thread, not lowering the iteration count.

How many iterations should I actually use in production in 2026?

OWASP's 2024 password-storage cheat sheet recommends 600,000 iterations for PBKDF2-HMAC-SHA-256, 210,000 for PBKDF2-HMAC-SHA-512, and 1,300,000 for PBKDF2-HMAC-SHA-1 (if you are stuck with it). Large consumer vaults run higher: 1Password uses 650,000, Bitwarden defaults to 600,000 and allows users to raise it, LastPass moved to 600,000 after the 2022 breach. Target 500ms of derivation time on your worst legitimate client device and let that pick the number; 600k is a sensible starting point.

Is auto-generated salt truly random?

Yes. The salt is 16 bytes from crypto.getRandomValues, which the browser binds to the OS CSPRNG (getrandom on Linux, BCryptGenRandom on Windows, SecRandomCopyBytes on macOS). This is the same randomness source used for TLS session keys and is suitable for cryptographic salt. 16 bytes (128 bits) is well above NIST SP 800-132's 8-byte minimum and collision-free across any realistic user population - you would need to generate 2^64 salts before a collision is likely.

Can I verify a previously stored PBKDF2 hash with this tool?

Yes. Disable auto-generate salt, paste the hex salt from your stored record, set iterations and hash algorithm to match exactly, and enter the candidate password. If the derived hash matches the stored one byte-for-byte, the password is correct. Parameters must match exactly: SHA-256 vs SHA-512 produces different output; 99,999 vs 100,000 iterations produce different output; 32-byte vs 64-byte key length produces different length output. For constant-time comparison in production code, never compare hashes with a simple equality check; use a crypto library's timing-safe compare.

Why is PBKDF2 still considered okay when Argon2 exists?

PBKDF2 is good enough for most threat models and is in every language's standard library plus the Web Crypto API. Argon2 is better because its memory-hard design (128MB RAM per guess at default settings) makes GPU and ASIC attacks roughly 1000x more expensive. If your stack supports Argon2id (Node: argon2 package, Python: argon2-cffi, Go: golang.org/x/crypto/argon2, PHP: built-in) use it. PBKDF2 remains the right choice when you need FIPS 140-3 compliance (Argon2 is not yet FIPS-approved), when you are deriving keys in a browser (Argon2 is not in Web Crypto), or when you must interoperate with legacy protocols like WPA2.

Is my password sent anywhere?

No. crypto.subtle.importKey wraps the password bytes into a CryptoKey object that stays inside the browser's crypto module. deriveBits runs locally in the native crypto implementation. No fetch, no XHR, no service-worker intercept. Disconnect the network after the page loads and the tool keeps working. If you are hashing a password for a production system, remember that the plaintext still has to reach your server via HTTPS - the hash-at-rest design only protects against database leaks, not network compromise.

Why HMAC inside PBKDF2 instead of bare hash?

HMAC (RFC 2104) is a keyed-hash construction that defeats length-extension attacks on Merkle-Damgard hashes. PBKDF2 uses the password as the HMAC key and the salt as the message, iterating to build up the derived key. Using raw SHA-256(password || salt || counter) would be vulnerable to length extension. RFC 8018 specifies HMAC for good reason.

Can I use the output hex directly as an AES key?

Yes. 32 bytes of PBKDF2 output is a valid AES-256 key. Convert the hex to a Uint8Array and pass it to crypto.subtle.importKey with algorithm AES-GCM. This is exactly how the companion AES tool on this site derives its key from a password. Do not use one PBKDF2 output as both an encryption key and an HMAC key - derive two subkeys by setting key length to 64 bytes and splitting, or use HKDF.

More Security & Privacy