The first thing we might reasonably want to do is protect passwords from casual observers, such as technical staff who have access to passwords in the database. While your admins are probably people you trust, there's no reason to tempt them, right?
The easiest way to protect passwords from casual observers is to hash the passwords before storing them in the database. That way admins see only hex codes instead of plaintext passwords.
If you recall from the previous section, we mentioned that in general we can't compute the password from the hash. You might wonder then how we accomplish logins. The answer to that is to hash the user's submitted password when he logs in, and then to compare the submitted hash with the stored hash. Because different passwords will almost certainly have different hashes, we can conclude that the authentication was successful if and only if the two hashes match. Sounds great, right?
Not exactly. This scheme does in fact prevent the casual observer from accidentally seeing passwords, and it may even present the newbie attacker from recovering a password. But in jujutsu-like fashion, we can use the for-all-practical-purposes 1-1 nature of the hash function as a tool to defeat it. Let's look at an example, shall we?
So what's going on here? It turns out that there are various online hash databases—essentially lookup tables—that map hashes to the inputs that generated them. Helpful hackers around the world create such databases by precomputing the hashes associated with dictionary words and close variants (in multiple languages, even). Because different passwords map to different hashes, you can create a lookup table for any explicitly given set of passwords. If an attacker has such a hash database at his disposal, it's pretty easy to launch a so-called dictionary attack against a compromised password database. The attacker can either attack passwords one-by-one, or (more commonly), the attacker can simply look for hashes associated with common passwords ('password', 'qwerty', etc.) and do whatever he wants to do with them afterward.
You'll notice that we did not pick the hash for 'I pledge allegiance to the flag'. If you copy the MD5 hash for 'I pledge allegiance to the flag' into a hash databases, chances are that it won't be able to figure out what generated the hash. (And if it does, it's easy enough to manufacture hashes that won't generate a match.) That's because the hash database creator did not precompute a hash for that particular phrase. And we can use that little tidbit to make our hashing scheme more secure, as we're about to see.