I'm looking at two comparable pieces of software which encrypt data on disk using a passphrase. One uses PBKDF2 to generate the encryption key from a passphrase, while the other uses two rounds of SHA256. What's the difference? Is one preferred over the other?
The difference is that:
- PBKDF2 by design is slow
- SHA256 is a good hash function; it is not slow, by design
So if someone were to try a lot of different possible passphrases, say the whole dictionary, then each word with a digit appended, then each word with a different capitalisation, then two dictionary words, etc. then this process would be much slower with PBKDF2.
But if your passphrase is truly secure, that is very long, pretty random and out of reach of any systematic enumeration process, then it makes no practical difference, except that an attacker may spend more resources trying to break your passphrase (or maybe less if they decide to give up sooner).
Password hashing algorithms such as PBKDF2, bcrypt, and scrypt are meant for use with passwords and are purposefully slow. Cryptographic hashing algorithms are fast. Fast is good in most situations, but not here. Slowing down the algorithm (usually by iteration) make the attacker's job much harder. Password hashes also add a salt value to each hash to make it unique so that an attacker can not attack multiple hashes at the same time.
Attackers will try to recover passwords by performing dictionary and brute-force attacks where they guess passwords by hashing them and comparing them to the stored password to determine if they match. With regular cryptographic hash functions (e.g. MD5, SHA256), an attacker can guess billions of passwords per second. With PBKDF2, bcrypt, or scrypt, the attacker can only make a few thousand guesses per second (or less, depending on the configuration).
This means that every password is much stronger if PBKDF2, bcrypt, or scrypt are used instead of a regular hash function.
In addition, PBKDF2, bcrypt, and scrypt all use large random "salt" values to make sure that each user's password is hashed uniquely. Attacking 100 password hashes will take 100 times longer than attacking one hash. Attacking a million will take a million times longer, etc. With SHA256, the attacker can try to crack thousands or millions of hashes at the same time with very little slow down.
You should always use a password hash or "key derivation formula" for passwords rather than an ordinary cryptographic hash. It's very hard to select passwords that are strong enough to withstand a dedicated cracking effort if they are hashed with something like SHA or MD5. With PBKDF2, bcrypt, or scrypt, passwords can be as short as 7 or 8 characters but with MD5 or SHA, they need to be at least 13-14 characters.
There are good answers above, but the immediate reason is that sha256 isn't salted and two rounds is pitifully weak in the same way that 4 digit passwords are weak, computationally:
- A modern GPU setup can easily compute all of the unsalted 4-digit sha256 hashes (in milliseconds)