Use SHA512 http://php.net/manual/en/function.hash.php.
SHA512 is not cracked. I suggest to use a salt: Some random string that you append to the password before hashing. This can protect against precomputed rainbow tables but not against dictionary attacks if the attacker gains access to the database containing passwords and salts.
SHA512(password + salt) --> hash
Store hash and salt in the DB
When checking password, retrieve salt corresponding to user, concatenate it with password, hash it and compare it with stored hash.
Read here: How long to brute force a salted SHA-512 hash? (salt provided)
Thinking back about your question and particularly about your statement "Hashing a password a million times may be safer, but also slower. How to achieve a good balance between speed and safety". Indeed, repeatedly hashing will protect you against dictionary attacks by making it computationally prohibitively expensive to compute all hashes in a dictionary. I am not teaching you anything here. From the first link I gave you, it took around 46 milliseconds to calculate a SHA512 hash, which is relatively long. Out of hand I can think of the following factors that could influence your decision as you are in an arms race setting:
- Increasing computing power (more CPU cores and GPU computations)
- Improved Algorithms over time
- Amount of money available to the attacker
- The value to get out of your site if cracked (if low, it would not be worth the effort)
against
- Amount of CPU power you have at your disposal
As a rule of thumb, I would hash as many times as possible so as to not impact my web site performance. Taking into account the number of logins per seconds, you can roughly calculate the amount of CPU power you can afford to spend without impacting your site performance.
One last comment: Assuming hackers already have access to the table containing the user names and hashed passwords, you might at that point be more worried about all the bad things they can do on your site.