What Is Key Derivation, and Why Can't You Just Hash a Password Once?
Learn what key derivation is, how password-based key derivation functions work, and why a single SHA-256 hash is not enough for secure password storage.
Imagine an attacker steals a database containing user password hashes. The application never stored the original passwords, which sounds reassuring. The attacker only has values that look like this:
5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
That value is not the password itself. It is a SHA-256 hash of the password password.
At first glance, that seems safe. Hashing is one-way, so the attacker cannot simply decrypt the value. But the attacker does not need to decrypt it. They can guess passwords, hash each guess, and compare the result. If hashing is fast, they can do that billions of times.
This is the problem key derivation functions are designed to solve. A password should not be hashed once with a fast general-purpose hash. It should be processed with a deliberately expensive password hashing or password-based key derivation function that slows attackers down.
What Is Key Derivation?
Key derivation is the process of taking some starting secret and turning it into one or more cryptographic keys.
That starting secret might be:
- A password entered by a user
- A master key stored in a secure system
- A shared secret created during a protocol handshake
- A passphrase used to unlock an encrypted file
The output is usually a key suitable for a specific cryptographic purpose, such as encrypting data, authenticating messages, or verifying a password.
Password or Secret
|
v
Key Derivation Function
|
v
Derived Key
The important detail is that a password is not usually a good encryption key by itself. Human passwords are uneven, memorable, reused, and often much less random than they appear. Key derivation bridges the gap between human-friendly secrets and machine-friendly cryptographic keys.
What Is a KDF?
A KDF, or key derivation function, is an algorithm that derives cryptographic key material from an input secret.
Some KDFs are used with high-entropy secrets, such as keys generated by secure random number generators. Others are designed specifically for passwords, where the input is often low entropy and vulnerable to guessing.
That distinction matters. Password-based KDFs must defend against attackers who can try many guesses offline. They are intentionally slower than ordinary hash functions, and modern ones may also require significant memory.
Common password-focused KDFs and password hashing algorithms include:
- Argon2id: a modern memory-hard choice for new password storage
- scrypt: a memory-hard password-based key derivation function
- bcrypt: an older adaptive password hashing algorithm still common in production systems
- PBKDF2: a widely supported password-based KDF specified in RFC 8018
OWASP’s Password Storage Cheat Sheet recommends strong, slow password hashing algorithms such as Argon2id, bcrypt, scrypt, or PBKDF2 instead of fast hashes like SHA-256 for password storage.
Why Not Just Hash a Password Once?
Because cryptographic hash functions are designed to be fast.
SHA-256 is excellent when you need a stable fingerprint for data. It is useful for file verification, checksums, digital signatures, blockchain systems, and many other security-sensitive workflows. But speed is a liability for password storage.
If a server can compute a SHA-256 hash very quickly, an attacker with stolen hashes can do the same thing very quickly. They can run huge lists of likely passwords through SHA-256 and compare the outputs against the stolen database.
That is the core issue:
Fast for your server
also means
fast for the attacker
For general data integrity, speed is usually good. For password storage, speed helps the wrong side once hashes are stolen.
If you want the broader distinction between integrity checking and cryptographic hashes, see what is a checksum?. Password storage uses some of the same one-way ideas, but the threat model is different.
The Offline Attack Problem
Password hashing is mostly about protecting users after something has already gone wrong.
In an online login attack, the attacker submits guesses to your application. You can rate-limit requests, lock accounts, require multi-factor authentication, block suspicious IP addresses, and monitor abuse.
In an offline attack, the attacker has copied the password hash database. Your application is no longer in the loop. There are no login rate limits. There are no account lockouts. The attacker can use their own hardware and guess as fast as the hash allows.
That is why a single fast hash is so dangerous. It turns a database breach into a high-speed guessing problem.
A Simple Example
Suppose Alice and Bob both use the password summer2026.
If a system stores a plain SHA-256 hash with no salt, both users get the same stored value:
summer2026 -> SHA-256 -> same hash every time
An attacker only needs to hash summer2026 once to identify every account using that password. They can also use precomputed lookup tables that already contain hashes for common passwords.
Now compare that with a password KDF that uses a unique salt:
Alice password + Alice salt -> KDF -> Alice hash
Bob password + Bob salt -> KDF -> Bob hash
Even though the password is the same, the stored outputs are different. The attacker must attack each hash separately.
What a Salt Does
A salt is a unique random value generated for each password. It is stored alongside the derived password hash.
The salt does not need to be secret. Its job is to make identical passwords produce different stored hashes and to prevent attackers from reusing precomputed tables across many accounts.
A stored password record often contains the algorithm, parameters, salt, and derived hash together:
algorithm: argon2id
memory: 19456 KiB
time: 2
parallel: 1
salt: random per-user value
hash: derived password hash
This is why two users with the same password should still have different password hash records.
Salt is not a magic shield against weak passwords. If a user chooses password123, an attacker can still guess it. Salt simply prevents the attacker from doing some of the work once and reusing it everywhere.
What a Work Factor Does
A work factor controls how expensive the password hashing process is.
With PBKDF2, the work factor is usually an iteration count. With bcrypt, it is a cost parameter. With Argon2id and scrypt, the cost includes memory settings as well as CPU effort.
The idea is simple: make each guess cost enough that large-scale cracking becomes expensive, while keeping legitimate login attempts fast enough for real users.
One SHA-256 hash:
extremely fast
Password KDF:
password + salt + work factor
repeated or memory-hard computation
much slower per guess
That slowdown may feel small for one user logging in. It becomes enormous when multiplied across billions of attacker guesses.
Why Memory Hardness Matters
Modern password cracking often uses GPUs or specialised hardware because they can perform many simple operations in parallel. Fast hashes are especially vulnerable to that kind of scaling.
Memory-hard functions make each guess require not only CPU time but also memory. That changes the economics of cracking. If each guess requires a meaningful amount of memory, attackers cannot pack as many guesses into the same hardware.
Argon2 was designed with this in mind. RFC 9106 describes Argon2 as a memory-hard function for password hashing and related applications. OWASP generally recommends Argon2id where available because it balances resistance to different classes of attacks.
This does not make weak passwords safe. It makes each guess more expensive, which is exactly what password storage needs.
Password Hashing vs Key Derivation
The terminology can be confusing because password hashing and key derivation overlap.
When you store a password for login verification, you usually store the output of a password hashing algorithm. The application later derives the value again from the submitted password and compares it with the stored value.
When you encrypt a file from a passphrase, you may use a password-based KDF to derive an encryption key. That key is then used with an encryption algorithm such as AES, which is covered in AES-128 vs AES-256.
The workflows are different, but the motivation is similar: raw passwords are poor cryptographic material, so the system derives something safer and more structured from them.
Hashing Is Not Encryption
Password storage should not be reversible.
Encryption protects data so it can be decrypted later with the right key. That is appropriate when the original data must be recovered. Password verification usually does not require recovering the password. It only requires checking whether the user knows it.
That is why password storage uses one-way password hashing rather than encryption. If an attacker steals an encrypted password database and later steals the encryption key, they may recover the original passwords. With properly designed password hashing, there is no decryption key to steal.
The system verifies a login like this:
User enters password
|
v
Apply same KDF settings and salt
|
v
Compare derived result with stored result
If the values match, the password is correct. The application never needs to know the original stored password because it should not have one.
Why SHA-256 Is Still Good, Just Not Here
Saying “do not use SHA-256 alone for password storage” does not mean SHA-256 is broken.
SHA-256 is a strong cryptographic hash function for many purposes. It is commonly used to verify files, build signatures, identify content, and represent binary data as stable digests. Those digests are often shown in hexadecimal, which is why Base64 vs hex encoding becomes relevant when developers need to display or transmit raw bytes.
The issue is fit for purpose. SHA-256 is fast and deterministic. Password storage needs a function that is salted, adaptive, and deliberately expensive.
For passwords, “fast and deterministic” is not enough.
What About Hashing Many Times Yourself?
You might wonder: if one SHA-256 hash is too fast, why not just run SHA-256 a million times?
That idea is close to what PBKDF2 does, but implementing it yourself is still the wrong move.
Real KDFs specify details that are easy to get subtly wrong: salt handling, output length, internal pseudorandom functions, parameter encoding, comparison behavior, and interoperability. They have also been reviewed and implemented across many platforms. PBKDF2, for example, is standardised in RFC 8018 and discussed in NIST’s SP 800-132 guidance for password-based key derivation.
If you need password storage, use a well-maintained password hashing library. Do not invent a custom scheme.
How Verification Works in Practice
A password hash record stores enough information to verify future logins:
$argon2id$v=19$m=19456,t=2,p=1$<salt>$<hash>
That string includes:
- The algorithm name
- The algorithm version
- The cost parameters
- The salt
- The derived hash
When the user logs in, the application parses those settings, runs the submitted password through the same algorithm, and compares the result.
This format has a practical benefit: you can upgrade parameters over time. If a user logs in with an older, weaker cost setting, the application can verify the password and then rehash it with stronger current settings.
Choosing a Password KDF
For new systems, Argon2id is usually the preferred choice when your platform supports it well. It was designed for modern password hashing and can be configured to require both CPU and memory.
scrypt is also memory-hard and remains a solid option where Argon2id is not available.
bcrypt is widely deployed and still acceptable in many existing systems, but it has older design constraints, including common input length limits. It is often a reasonable legacy choice, but not usually the first pick for a brand-new system if Argon2id is readily available.
PBKDF2 is widely supported and remains important in environments that require FIPS-validated cryptographic modules. It can be safe with a high enough iteration count, but because it is not memory-hard, it is generally less resistant to highly parallel cracking hardware than Argon2id or scrypt.
The best choice depends on your platform, compliance requirements, performance budget, and operational maturity. The worst choice is almost always a custom password hashing design built from a fast hash.
Good Password Storage Practices
Secure password storage is a system, not one function call.
Good practice includes:
- Use Argon2id, scrypt, bcrypt, or PBKDF2 through a reputable library
- Generate a unique random salt for every password
- Store the algorithm and parameters with the hash
- Tune the work factor for your server capacity
- Revisit parameters over time as hardware improves
- Use constant-time comparison for verification
- Add rate limits and multi-factor authentication for online attacks
- Never store plaintext passwords
- Never design your own password hashing algorithm
These controls complement password quality. A strong KDF helps protect the stored hash, while good password entropy makes the underlying secret harder to guess. For that side of the problem, see password entropy explained.
Where Peppers Fit
A pepper is an additional secret value used during password hashing. Unlike a salt, a pepper is shared across many records and must be kept secret, usually outside the main database.
Peppering can add defense in depth. If an attacker steals only the database, but not the pepper, cracking becomes harder. However, peppering also introduces operational complexity. The pepper must be generated, stored, rotated, and protected carefully. If it is lost, password verification may fail for every user.
OWASP discusses peppering as an optional additional control, not a replacement for a proper password hashing algorithm, unique salts, or strong work factors.
Why This Matters for Users
Users do not see key derivation directly. They see a login form.
But password storage choices affect what happens after a breach. If a site stores passwords with a fast unsalted hash, attackers may recover large numbers of passwords quickly. If users reused those passwords elsewhere, the breach spreads into other accounts.
If a site uses strong password hashing with unique salts and sensible parameters, attackers still have the hashes, but each guess costs more. Strong, unique user passwords become much harder to recover.
That is why password managers matter so much. They let users create unique high-entropy passwords for every site. The site still needs good password storage, but the user’s password is no longer easy to guess in the first place.
Key Derivation Beyond Passwords
Key derivation is not only about password storage.
Modern protocols derive separate keys for separate purposes. A secure connection may derive one key for sending data, another for receiving data, and additional keys for authentication. Separating keys limits the damage if one use case is compromised and avoids reusing the same key in incompatible ways.
This is similar in spirit to certificate chains: the security comes from structure, not just from one impressive-looking cryptographic object. Real systems need the right relationships between secrets, keys, algorithms, and trust decisions.
Password-based key derivation is simply the version most developers encounter first because every login system has to deal with human passwords.
Common Mistakes
Using SHA-256 directly. SHA-256 is too fast for password storage. Use a password hashing algorithm or password-based KDF.
Using the same salt for everyone. A salt should be unique per password record.
Treating the salt as secret. Salts can be stored with the hash. They need uniqueness, not secrecy.
Choosing parameters once and forgetting them forever. Hardware improves. Password hashing parameters should be reviewed and upgraded over time.
Building a custom scheme. Password storage has many sharp edges. Use established libraries and formats.
Confusing encoding with security. Base64 or hex can represent a hash, but neither makes a password safer.
Related Reading
If you are working through cryptography and authentication topics, try these topics:
- Password entropy explained: why some passwords are much harder to guess than others
- What is a checksum?: how hashes and checksums help detect changes in data
- AES-128 vs AES-256: how derived keys are eventually used with encryption algorithms
- Base64 vs hex encoding: why cryptographic outputs are often displayed as text
- Certificate chains explained: another example of security depending on structure and trust
For external guidance, start with OWASP’s Password Storage Cheat Sheet, RFC 9106 for Argon2, and RFC 8018 for PBKDF2.
Frequently Asked Questions
What is key derivation? Key derivation is the process of taking an input secret, such as a password or master key, and producing cryptographic key material from it. With passwords, key derivation helps turn a human-memorable secret into something safer for verification or encryption.
Why can’t I just hash a password with SHA-256 once? SHA-256 is designed to be fast. That makes it useful for many security tasks, but dangerous for password storage because attackers with stolen hashes can test guesses extremely quickly. Passwords should use a slow, salted password hashing algorithm or password-based KDF.
Is a salt the same as a pepper? No. A salt is a unique random value stored with each password hash. A pepper is a separate secret value stored outside the password database. Salts are essential; peppers are optional defense in depth.
Which password hashing algorithm should I use? For new systems, Argon2id is usually preferred when supported by your platform. scrypt is also strong. bcrypt remains common for existing systems. PBKDF2 is often used where broad compatibility or FIPS-validated implementations are required.
Does key derivation make weak passwords safe?
No. A KDF makes each guess more expensive, but it cannot make password123 a strong password. Users still need unique, high-entropy passwords, ideally generated and stored by a password manager.
Conclusion
Key derivation turns passwords and other secrets into cryptographic key material. For password storage, the goal is not just to produce a one-way value. The goal is to make offline guessing expensive after a database breach.
A single fast hash like SHA-256 is the wrong tool for that job. It is too quick, too easy to parallelise, and too friendly to attackers testing large password lists. Proper password hashing uses unique salts, adjustable work factors, and, where possible, memory-hard algorithms such as Argon2id or scrypt.
The rule of thumb is simple: use fast hashes for fingerprints, signatures, and integrity workflows; use password hashing algorithms or password-based KDFs for passwords. When human secrets are involved, slowing the attacker down is the whole point.
Written by the Workshelve team, who write practical explainers on data integrity, networking, and developer tooling.