In very simplistic terms:
Hashing takes input of any size and generates a "checksum" for it. Whether the input is the letter "a" or the "Complete works of Shakespeare", the resulting hash will be of the same length. For MD5, such a hash can be represented as a string of 32 characters. You can test this using any online MD5 hash genarator.
Notice that
- The same input (password) will generate the same hash every time.
- Similar inputs (e.g. "password" and "Password") will generate very different hashes.
Now instead of storing a password in a database, a hash of that password can be stored. To check the password, the value entered into the input field is simply hashed again. If it generates the same hash as what is stored in the DB, then the password is assumed to be correct, and the actual password will never actually be stored in the database.
I say assumed since there is a theoretical possibility that two different inputs can generate the same hash, although that is highly unlikely in the context of entering a password (for some actual crash-examples, see this question under Crypto.StackExchange).
Rainbow tables and reversing hashes
A rainbow table is basically a list of typical passwords for which the hashes have been calculated. Example using MD5:
5f4dcc3b5aa765d61d8327deb882cf99 => password
dc647eb65e6711e155375218212b3964 => Password
You can easily query such lists using any of a number of so-called md5 decryptors (Again, just to be clear: They are not really decrypting anything - just matching a hash to a list of known values).
If someone can access your database and get your list of password hashes, then such a list might be used to infer the passwords for some of your users if
- Their passwords are relatively simple
- You are not salting your passwords.
Salting basically means adding some extra piece of information before generating a hash, so that the resulting hash will be less likely to appear in a rainbow list. As an example, imagine you hash not just your password, but the combination of username and password; password
will generate the hash 5f4dcc3b5aa765d61d8327deb882cf99
which will probably be in every rainbow table, while khkhkkPassword
will generate be2d1a6255d12f44b8a44f25aea41516
, which will probably not by in any of them.
Those are the basics, and the principles described here for MD5 should be the same for other algorithms. Note however that MD5 has been considered insecure for a long time, and that other more robust options should be used. There are several options, and in many cases there will be tools or libraries and best practices available for whatever programming language or framework you are working with, which can help simplify the choice and implementation.