Security Tools

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.

Derived Key (hex)
Derived Key (Base64)

Check Password Against Stored Hash

Supports Django (pbkdf2_sha256$, pbkdf2_sha1$), passlib ($pbkdf2$, $pbkdf2-sha256$, $pbkdf2-sha512$) and Werkzeug/Flask (pbkdf2:sha256:).

Hash Anatomy
Paste a stored PBKDF2 hash above to see its parts.

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):

PRFOutput sizeOWASP currentOWASP 2023Notes
HMAC-SHA25632 bytes600,000600,000Recommended; also the FIPS-140 choice
HMAC-SHA51264 bytes220,000210,000Fewer iterations because each one is more expensive on GPUs
HMAC-SHA120 bytes1,400,0001,300,000Legacy only; do not choose for new systems
HMAC-SHA38448 bytesNo separate figureRarely used for password storage

Stored hash formats recognised by the verifier:

FrameworkFormatSaltHash encoding
Djangopbkdf2_sha256$<iter>$<salt>$<hash> (also pbkdf2_sha1)Text, used as UTF-8 bytesStandard Base64
passlib$pbkdf2-sha256$<iter>$<salt>$<hash> (also $pbkdf2$ = SHA-1, $pbkdf2-sha512$)Raw bytes, adapted Base64Adapted Base64 (. for +, no =)
Werkzeug / Flaskpbkdf2:sha256:<iter>$<salt>$<hash>Text, used as UTF-8 bytesHex

Published test vectors you can reproduce with this tool:

SourcePRFPassword / SaltIterationsLengthDerived key (hex)
RFC 6070SHA-1password / salt1200c60c80f961f0e71f3a9b524af6012062fe037a6
RFC 6070SHA-1password / salt4096204b007901b765489abead49d926f721d065a429c1
RFC 7914SHA-256passwd / salt16455ac046e56e3089fec1691c22544b605f94185216dde0465e68b9d57c20dacbc49ca9cccf179b645991664b39d77ef317c71b845b1e30bd509112041d3a19783
RFC 7914SHA-256Password / NaCl80000644ddcd8f60b98be21830cee5ef22701f9641a4418d04c0414aeff08876b34ab56a1d425a1225833549adb841b51c9b3176a272bdebba1d078478f62b397f33c8d

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.