1

So, i learned that new in PHP 5.5 is password-hash() which works much like crypt(). Which is more secure (slower) than md5() or sha1(). The result string is algo+hash+salt, which can be passed as-is to password-verify() to verify password. So far i get how it works.

Some doomsday questions that remain:

Q1) What is the name of the result format/protocol/convention?

Q2) What i dont get however, is that all of the salt is included in the database. If a badguy® where to obtain these, he has all the puzzle parts. In the past, i learned to put (part of) the salt outside of the database: in source, of even base it on ram/system/hardware values so its not even on disk. Why is this not facilitated, or how should i? Ofcourse i could do a double hash with a different salt, or is there a better way?

Q3) Also -in the doomsday mindset that security requires- i believe the single-point of failure password_hash() is going to be a high value target, and might facilitate MITM attacks way easier than the more self-contained crypt(). I imagine writing a "bad" algo and setting it as the PASSWORD_DEFAULT algo would be easier than altering crypt(). I have not looked into the PHP backend code/modules however, just speculating.

Considerations welcome. Accepted answer will be the one that gets most up-votes/census for questions 2/3 within a week at most, and has question 1 verifiable correct.

  • Perhaps i should add regarding Q2; i see hacking these selfdescribing hashes can happen more efficient and even fully automated. – Barry Staes Feb 4 '14 at 8:25
  • I'd encrypt the hash with a key stored outside the db rather than keep the salt secret. – CodesInChaos Feb 4 '14 at 8:48
  • @CodesInChaos i wonder why do that using encrypt, and not hash? When do you need to decrypt it? – Barry Staes Feb 5 '14 at 7:48
  • 2
    I'd first hash the password with bcrypt. Then encrypt the hash. That way an attacker who doesn't know the key can't do anything, and an attacker who finds the key still needs to run a password guessing attack against a slow hash. Using encryption over other keying methods has the advantage that you can easily change the key and re-encrypt the data. It's also convenient for scenarios where the key is stored on a separate system, such as a low performance HSM. – CodesInChaos Feb 5 '14 at 8:34
6

What is the name of the result format/protocol/convention?

password_hash() uses the bcrypt algorithm.

PASSWORD_DEFAULT - Use the bcrypt algorithm (default as of PHP 5.5.0). Note that this constant is designed to change over time as new and stronger algorithms are added to PHP. For that reason, the length of the result from using this identifier can change over time. Therefore, it is recommended to store the result in a database column that can expand beyond 60 characters (255 characters would be a good choice).

Source: http://www.php.net/manual/en/function.password-hash.php

Q2) What i dont get however, is that all of the salt is included in the database. If a badguy® where to obtain these, he has all the puzzle parts. In the past, i learned to put (part of) the salt outside of the database: in source, of even base it on ram/system/hardware values so its not even on disk. Why is this not facilitated, or how should i? Ofcourse i could do a double hash with a different salt, or is there a better way?

The only requirement for a salt is for it to be globally unique. It does not have to be kept secret. password_hash() takes care of it for you. Don't do anything fancy and stupid. See: How to store salt?

Q3) Also -in the doomsday mindset that security requires- i believe the single-point of failure password_hash() is going to be a high value target, and might facilitate MITM attacks way easier than the more self-contained crypt(). I imagine writing a "bad" algo and setting it as the PASSWORD_DEFAULT algo would be easier than altering crypt(). I have not looked into the PHP backend code/modules however, just speculating.

What? MITM has literally NOTHING to do with this. The hashing should be done on the server. If an attacker can modify files on your server, he can already do whatever he wants.

  • You might want to mention the (rather small) downside of using bcrypt: since it's CPU-intensive to verify, it might be used in a DOS by sending many fake auth requests and forcing the server to spend a lot of CPU checking them all. – Stephane Feb 4 '14 at 8:22
  • Thanks @Stephane i did not consider CPU usage being that high. – Barry Staes Feb 4 '14 at 8:27
  • @Stephane I don't consider that a downside. Frankly, if that proves to be a problem you need a better CPU. Throttling login attempts should also help. – user10211 Feb 4 '14 at 8:30
  • @TerryChia Thanks to the DoS potential one needs to choose relatively small cost factors for bcrypt, and even then it's tricky. Hashing on the client is actually better than hashing on the server in principle, but for that we'd need a high performance implementation of a password hash on the client. – CodesInChaos Feb 4 '14 at 8:52
  • @Barry Staes Benchmark and adjust the cost setting accordingly. For interactive logins, aim for something like ≤ 100 ms hashing time. – timoh Feb 4 '14 at 9:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.