A hashing function uses an algorithm that is created with several things in mind:
- Any hash generated will have the same length (i.e. a SHA256 hash will
always be 256 bits)
- Using the same hashing algorithm with the same input will always give
the same output
- A tiny change in the original value to be hashed will have a huge
impact on the hashed value
- It is not possible to directly reverse a hash
By only storing the hashed version of a password, it is not possible to directly find the password that goes with it. That way, when the database with user data is stolen, the criminals will only have hashes, but not the actual passwords.
When a password is entered on the client, it is sent over a secure connection (ie. HTTPS). The server then performs the hash function and compares it with stored password hash. (If the hash is performed on the client is easy to resend that hash.)
If they match, it is assumed that the correct password was entered (in theory a different password could have the same hash, but this unlikely to happen).
Which hashing function to use is a tradeoff between security and usability.
The amount of time needed to calculate one hash is of importance: you want a hashing function that can't be solved quickly, because then a brute-force attack becomes feasible, on the other hand you don't want your users to have to wait a minute while the server is checking their password.
Why I say that they cannot be directly reversed is because it is possible to make a dictionary which has all possible passwords and the hashed values that belong to those passwords ("rainbow tables"). A rainbow table is specific to a particular hashing algorith (MD5, SHA-1, SHA-2, etc.)
There are various sites online with rainbow tables, for instance MD5cracker.org for MD5 hashes or crackstation.net for various hash functions.
A possible protection against rainbow tables is the use of salts. The idea is to add a number of extra bytes to the password to make it longer (this does not affect the length of the hash though, since it stays the same length, irregardless of what is being hashed).
A salt is generally added as follows (
+ is concatination):
saltedhash(password) = hash(password + salt)
saltedhash(password) = hash(hash(password) + salt)
Salts are not meant to be kept secret, so they can be stored in the database with the password. To prevent the same passwords to appear as the same hash in the database, use a seperate, random salt for each password.