First not encryption creating Message Digest using the hash functions.
your question:
but can't you just encrypt (hash) your
password using, say, MD5 and then,
say, SHA-1 (or any other, doesn't
matter.)
if the hash function does not provide any of these properties, it does not matter how many times you hashed, also the attacker can hash n times to get the collisions.
For any given code h, it is computationally infeasible to find
such x that H(x)=h, this property is
called one way or preimage resistant.
For any given block x ,it is computationally infeasible to find y≠x
with H(y)=H(x).This property is
referred second preimage resistant or
weak collision resistant
It is computationally infeasible to find any pear (x,y) such that
H(x)=H(y). This is called Strong
collision resistant.
So as The Rook mentioned, the passwords are stored by adding different salt values for each users. The dictionary gets longer and also computational overhead and time gets longer for the attacker if she exploits the password file.
Let's say attacker has the hashed values of the passwords, and starts reading from the dictionary file and compares with the hashed values if matches then pasword is cracked, if salt is used then read from the dictionary and add some salt value then try to find a match.However this should be done for each user. So the complexity that salt adds is (from wikipedia)
Assume a user’s (encrypted) secret key
is stolen and he is known to use one
of 200,000 English words as his
password. The system uses a 32-bit
salt. The salted key is now the
original password appended to this
random 32-bit salt. Because of this
salt, the attacker’s pre-calculated
hashes are of no value. He must
calculate the hash of each word with
each of 2^32 (4,294,967,296) possible
salts appended until a match is found.
The total number of possible inputs
can be obtained by multiplying the
number of words in the dictionary with
the number of possible salts:
if H(password+salt)(in system)=H(Your password+salt) (login process)
login else
print<<error