密码哈希安全性

I have a few questions concerning password hashing. I found hash_hmac a pretty good function to hash passwords but a few questions remain.

From another stackoverflow questions someone responded with:

return hash_hmac('sha512', $salt . $user['password'], $this->site_key);

My initial question concerns how hmac uses the key, on wikipedia it seems that the hmac function would prepend the key to every piece of message before hashing it, does the key itself not act as a salt then? Can I then drop the $salt and just use a user specific key instead? hash_hmac('sha512', $user['password'], $this->user_key)

The big question remains the generating of the $salt (or the $user_key from first question). I don't like to store the used salt in the database if I would generate them using rand(). What would then be a good way to generate a user specific salt?

Update

If I would store the salt in the database, is it safe to use:

$user_key = $user['salt'] . $this->site_key;
return hash_hmac('sha512', $user['password'], $user_key);

Use a random per user salt and store it together with the hash in the database. Combine it was a per-site secret that's in your config-file. That way an attacker needs to gain access to both the database and the config-file before he can start to crack passwords.

To hash passwords securely I recommend combining three ingredients:

  1. A good Key-Derivation-Function. It's similar to a plain hash, but it's slow and takes a salt. bcrypt and PBKDF2 are common choices.
  2. A random per user salt. The main purpose of this is that it's different for each user. You store it together with the hash in the database. No problem if the attacker gets it.
  3. A per-site secret. The purpose of this is that getting access to the database is not enough to crack passwords. The attacker needs access to the config file too. And even if he learns the per-site secret the scheme is still as secure as if you had used no secret at all.

Use bcrypt!

The classic text on safely storing passwords:

http://codahale.com/how-to-safely-store-a-password/

Quote from the article:

Salts Will Not Help You

Bonus!

using bcrypt is simpler than finagling your own bs and likely incorrect salting scheme.

DON'T EVER IMPLEMENT YOUR OWN CRYPTOSYSTEM OR SOURCE OF ENTROPY