# PBKDF2: How Password-Based Key Derivation Works

**Source**: https://quantumsequrity.com/blog/pbkdf2-explained
**Category**: Cryptography Foundations

---

[← Back to Blog](../../blog) Cryptography Foundations

# PBKDF2: How Password-Based Key Derivation Works

11 min read

Every password-protected file you have ever encrypted, every password manager you have ever used, every disk encryption tool you have ever set up, has had to face the same problem. How do you turn a human-friendly password, which is short, low-entropy, and often reused across services, into a cryptographic key that can resist a brute-force attack? The first widely deployed answer was PBKDF2, the Password-Based Key Derivation Function 2. PBKDF2 was published in 2000 as RFC 2898 and updated in 2017 as RFC 8018. For nearly two decades it was the default password-to-key function in most cryptographic libraries. Today it is increasingly considered a baseline rather than a best practice, replaced for new designs by Argon2id and similar memory-hard functions. Understanding PBKDF2, why it was good enough for so long, and why it is no longer the right answer for new systems, is a useful foundation for any password-based encryption decision.

## The Problem PBKDF2 Solves

When a user types a password to encrypt a file, the password itself is not a cryptographic key. A password might be 8 to 20 characters drawn from a small alphabet of letters, digits, and symbols. The total entropy of a typical password is around 30 to 50 bits, far below the 128 to 256 bits needed for modern cryptography.

The naive approach of hashing the password with SHA-256 and using the hash as a key fails because of brute-force attacks. An attacker who captures an encrypted file can try every plausible password, hash each one with SHA-256, and check whether the result decrypts the file. Modern hardware can compute billions of SHA-256 hashes per second, which means a typical password falls in seconds to minutes.

The fix is to make the password-to-key function deliberately slow. If computing the key from the password takes 100 milliseconds, an attacker who wants to try a billion passwords needs over three years on the same hardware. A user who only needs to compute the key once at file open time barely notices the 100 milliseconds.

PBKDF2 achieves the deliberate slowness by repeating an underlying cryptographic operation many times. The user picks a number of iterations, often called the cost factor, and PBKDF2 runs that many iterations of an HMAC operation to derive the key from the password.

## How PBKDF2 Works

PBKDF2 takes four inputs: a password, a salt, an iteration count, and a desired key length. The salt is a random value, typically 16 bytes, that prevents an attacker from precomputing rainbow tables. Each user gets a unique salt, so even if two users have the same password, their derived keys are different.

The core of PBKDF2 is a loop. Start with a value derived from the password and salt. Apply HMAC, with the password as the key, to the current value. Keep doing this for the specified number of iterations. The final value is the derived key.

Specifically, PBKDF2-HMAC-SHA256 with N iterations computes:

T_1 = HMAC-SHA256(password, salt || INT(1))
T_i = T_(i-1) XOR HMAC-SHA256(password, T_(i-1)) for i from 2 to N
DK = T_N

The XOR chain ensures that an attacker cannot precompute the result without doing all N iterations. The key derived from the final iteration is then used as the encryption key.

For longer keys, PBKDF2 runs multiple parallel chains with different INT() prefixes and concatenates the results. This allows PBKDF2 to produce keys of any length, although key lengths beyond a few hundred bits are rarely needed.

The underlying HMAC can be instantiated with any hash function. The most common choices are HMAC-SHA1, HMAC-SHA256, and HMAC-SHA512. SHA1 is now considered too weak for new designs, so SHA256 or SHA512 are the modern defaults.

For comparison with the modern memory-hard alternative, see [Argon2id Explained](argon2id-explained).

## Iteration Count History

The most contested parameter in PBKDF2 is the iteration count. The right value depends on the year, the threat model, and the platform.

In 2000, when PBKDF2 was first standardized, NIST recommended 1,000 iterations. This was sufficient against the hardware of the time.

By 2010, hardware had improved significantly. NIST SP 800-132 recommended at least 10,000 iterations for general use.

By 2017, NIST SP 800-132 was being interpreted to require at least 10,000 iterations as a minimum, with higher counts recommended for sensitive applications. Many real deployments used 100,000 or higher.

By 2023, NIST SP 800-63B-3 recommended at least 10,000 iterations for general use but noted that "more iterations are better" and that current best practice is in the hundreds of thousands or low millions for sensitive applications.

By 2026, the OWASP Password Storage Cheat Sheet recommends at least 600,000 iterations for PBKDF2-SHA256 in new deployments. Some applications use 1 million or higher.

The iteration count needs to be revisited periodically as hardware improves. A count that was strong in 2010 is weak in 2026. This is one of the practical problems with PBKDF2: legacy data stored with old iteration counts becomes increasingly vulnerable over time, and re-encrypting with higher counts is operationally painful.

## Salt: Why It Matters

The salt parameter in PBKDF2 prevents two specific attacks. First, rainbow table attacks: precomputed tables of hashes for common passwords. Without salt, an attacker can precompute a rainbow table once and use it against many encrypted files. With unique salts per file, the attacker has to recompute the table for every salt, which destroys the economics of precomputation.

Second, parallelism attacks: if many files share the same password, an attacker who breaks one breaks all of them. Unique salts per file mean each file requires independent work.

The salt should be random, unique per file or per user, and at least 16 bytes long. Shorter salts can be brute-forced themselves. Predictable salts (like the username) provide weaker protection than random salts.

Modern PBKDF2 deployments use cryptographically random salts generated by a CSPRNG. The salt is stored alongside the encrypted file or in the file header, since the salt itself is not secret. The security comes from the salt being unique, not hidden.

## Why PBKDF2 Is Now Considered Weak

The fundamental weakness of PBKDF2 is that it is purely computational, not memory-hard. The computation is just iterated HMAC. An attacker can build specialized hardware, FPGAs or ASICs, that compute HMAC-SHA256 thousands of times faster than a general-purpose CPU. PBKDF2 with 600,000 iterations might take 100 milliseconds on a CPU but only microseconds on a custom ASIC.

This asymmetry between defender hardware and attacker hardware is the main reason PBKDF2 is no longer recommended for new high-security applications. Memory-hard functions like Argon2id force the attacker to use large amounts of memory in addition to compute. Memory is much harder to scale on custom hardware than pure computation, which closes the asymmetry.

The other weakness of PBKDF2 is that the iteration count is a single tunable parameter. There is no built-in way to adapt to different hardware classes or different threat models without changing the count. Memory-hard functions typically have multiple parameters, including memory cost, time cost, and parallelism, which can be tuned independently.

For the modern memory-hard story, see [Argon2id Explained](argon2id-explained).

## Where PBKDF2 Is Still Used

Despite its weaknesses, PBKDF2 remains widely deployed for several reasons.

First, it is in NIST FIPS 140-3 approved cryptographic modules. Argon2id is not yet a NIST FIPS-approved primitive, although NIST is considering it. For applications that need FIPS compliance, PBKDF2 is the only certified password-based key derivation function.

Second, it is universally supported. Every cryptographic library has PBKDF2. Many embedded systems and constrained environments do not support Argon2id, so PBKDF2 is the only option.

Third, it is sufficient for many threat models. If the threat is a casual attacker with consumer hardware rather than a nation-state with custom ASICs, PBKDF2 with high iteration counts is good enough. The asymmetry against custom hardware matters less when the attacker does not have custom hardware.

Fourth, it is required by some specifications. PDF encryption uses PBKDF2 in its file format specification. WPA2 Wi-Fi authentication uses PBKDF2-HMAC-SHA1. Updating these specifications would require coordinated changes across the entire ecosystem.

In practice, PBKDF2 lives on as a baseline that is acceptable but not optimal. Memory-hard functions like Argon2id are recommended for new designs that have the flexibility to adopt them.

## PBKDF2 in QNSQY and Other Production Systems

QNSQY's standard build uses Argon2id, not PBKDF2, for password-based key derivation. The reasoning is that QNSQY is a new product without legacy compatibility constraints, and the threat model includes well-resourced attackers who might invest in custom hardware. Argon2id provides better protection against this kind of attacker.

QNSQY's approved-mode build, built and tested internally and not yet released, uses PBKDF2-HMAC-SHA-512 instead, because NIST's approved password-based key derivation is PBKDF2 (SP 800-132) and Argon2 is not on NIST's approved list.

The contrast illustrates a real tradeoff. Where memory and CPU are available and NIST approval is not required, Argon2id is the stronger choice against custom hardware. Where an approved algorithm is required, or where the platform tightly limits compute time, PBKDF2 may still be necessary.

For applications where you have full control over the runtime environment, prefer Argon2id. For applications where you must use a constrained environment, PBKDF2 with a high iteration count is acceptable. For all applications, the iteration count should be calibrated periodically as hardware improves.

For the broader QNSQY architecture, see [Hybrid Encryption](hybrid-encryption), [AES-256-GCM Explained](aes-256-gcm-explained), and [Argon2id Explained](argon2id-explained).

## PBKDF2 and Post-Quantum Cryptography

PBKDF2 is a symmetric construction built on hash functions. Quantum computing affects it the same way it affects hash functions: Grover's algorithm gives a quadratic speedup against brute-force search, halving the effective entropy of the password.

If your password has 50 bits of entropy and you derive a key with PBKDF2, the effective post-quantum entropy is around 25 bits. This is dramatically below modern recommendations and means a quantum attacker, when one exists, will brute-force PBKDF2-derived keys easily for any user-chosen password.

The fix is the same as in the classical world: use a strong password (high entropy, randomly generated, long) rather than a human-memorable one. A 20-character random password from a 70-character alphabet has around 122 bits of entropy, leaving 61 bits of post-quantum entropy. Combined with PBKDF2's iteration count, this is acceptable.

For users who want to use memorable passwords with quantum-attack resistance, the answer is to use a password manager that generates strong random passwords and stores them under a single high-entropy master password. The master password protects the manager's vault, and the random passwords protect individual services.

For the post-quantum context, see [What Is Post-Quantum Cryptography](what-is-post-quantum-cryptography) and [Harvest Now, Decrypt Later](harvest-now-decrypt-later).

## When to Use PBKDF2

The narrow case for PBKDF2 in new designs is:

You need NIST FIPS 140-3 compliance, which currently does not certify Argon2id.

You are running in a constrained environment (browser, embedded system, restricted serverless platform) where Argon2id memory requirements cannot be met.

You are interoperating with legacy systems that require PBKDF2.

In all other cases, Argon2id is preferable for new designs. The transition is not urgent for existing PBKDF2 deployments with high iteration counts, but new code should default to Argon2id.

When using PBKDF2:

Use HMAC-SHA256 or HMAC-SHA512, not HMAC-SHA1.

Use at least 600,000 iterations as of 2026, more for sensitive applications.

Use a unique random 16-byte salt per derivation.

Plan to revisit the iteration count every few years as hardware improves.

## Frequently Asked Questions

**Is PBKDF2 broken?**
No. PBKDF2 is not broken in the sense of having a cryptanalytic attack against the construction. It is weakened by the availability of custom hardware that runs HMAC-SHA256 thousands of times faster than general-purpose CPUs. This makes brute-force attacks more effective than they would be against memory-hard functions like Argon2id.

**How many iterations should I use?**
As of 2026, OWASP recommends at least 600,000 iterations for PBKDF2-SHA256 in new deployments. For very sensitive applications, 1 million or more is reasonable. The right number depends on how much CPU time you can afford per legitimate password verification.

**Is PBKDF2-SHA1 still safe?**
SHA1 has known cryptographic weaknesses, but the way HMAC is constructed, those weaknesses do not directly compromise HMAC-SHA1 in PBKDF2. WPA2 Wi-Fi still uses PBKDF2-HMAC-SHA1. For new designs, prefer PBKDF2-SHA256 or PBKDF2-SHA512.

**Should I migrate from PBKDF2 to Argon2id?**
For new designs, yes. For existing deployments with high iteration counts and well-controlled threat models, the urgency is lower. The migration is not free: you need to re-derive keys for all users, which often means asking them to re-enter their passwords. Plan the migration when you have a natural opportunity, like a major version update.

**What is the difference between PBKDF2 and bcrypt?**
PBKDF2 uses iterated HMAC. bcrypt uses iterated EksBlowfish, a Blowfish variant with an expensive key schedule. Both are computational rather than memory-hard, but bcrypt has marginally more resistance to GPU-based attacks than PBKDF2-SHA256. Both are now considered baselines rather than best practices, with Argon2id preferred for new designs. See [bcrypt Explained](bcrypt-explained) for the full picture.

## Sources

1. IETF RFC 8018. "PKCS #5: Password-Based Cryptography Specification Version 2.1." 2017. https://datatracker.ietf.org/doc/html/rfc8018
2. NIST SP 800-132. "Recommendation for Password-Based Key Derivation, Part 1: Storage Applications." 2010. https://csrc.nist.gov/pubs/sp/800/132/final
3. NIST SP 800-63B. "Digital Identity Guidelines: Authentication and Lifecycle Management." 2017 with updates. https://pages.nist.gov/800-63-3/sp800-63b.html
4. OWASP. "Password Storage Cheat Sheet." 2025 update. https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html
5. IETF RFC 9106. "Argon2 Memory-Hard Function for Password Hashing and Proof-of-Work Applications." 2021. https://datatracker.ietf.org/doc/html/rfc9106
6. NIST FIPS 140-3. "Security Requirements for Cryptographic Modules." 2019. https://csrc.nist.gov/pubs/fips/140/3/final

## Related Articles

- [Argon2id Explained](argon2id-explained)
- [bcrypt Explained](bcrypt-explained)
- [AES-256-GCM Explained](aes-256-gcm-explained)
- [Harvest Now, Decrypt Later](harvest-now-decrypt-later)
- [Hybrid Encryption](hybrid-encryption)

---

### Protect Your Data Before Q-Day Arrives

QNSQY's NIST-standardized post-quantum encryption protects files against both current and quantum-era threats.

[Try QNSQY](../../pricing)
