0

I was wondering if it was possible/wise to use password_hash twice for my users passwords on my website.

So let's say this:

  • User registers on my site, they enter a password, we will call this input.

  • During account creation, their password is $firstHash = password_hash($input, PASSWORD_BCRYPT) (For example sake, lets say this hashes to "thisFirstHash"

  • Once their password is hashed, it is hashed again $firstHash = password_hash($firstHash, PASSWORD_BCRYPT) (For example sake, lets say this hashes to "thisSecondHash")

  • This second hash is what is stored to the database, so now when they log in, the server has to decrypt a hashed hash.

  • When the user logs in, they enter their password again, we will again call this input

  • the server then has to reencrypt the input to compare with the saved hash $loginHash1 = password_hash($input, PASSWORD_BCRYPT)

  • The server compares the new loginHash1 variable with the saved hash password_verify($loginHash1,"thisSecondHash")

  • If the first hash matches, compare the second hash

  • password_verify($input,"thisFirstHash")

I couldn't quite get this to work properly in my small testing environment, I suspect it has something to do with the randomized salt being different during the login phase when rehashing the input.

So my questions are,

  1. Is it possible to do this?
  2. Is it beneficial to do this?
  • 8
    Please dont __roll your own__ password hashing. PHP provides [`password_hash()`](http://php.net/manual/en/function.password-hash.php) and [`password_verify()`](http://php.net/manual/en/function.password-verify.php) please use them, I might want to use your site one day And here are some [good ideas about passwords](https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet) If you are using a PHP version prior to 5.5 [there is a compatibility pack available here](https://github.com/ircmaxell/password_compat) – RiggsFolly Aug 03 '16 at 20:12
  • 8
    No - it is not wise and adds nothing to your security. – Jay Blanchard Aug 03 '16 at 20:12
  • Maybe if you string reverse the first hash result, then base64 encode it, then hash that.... Remember arbitrary number of steps is the key to security – Ray Aug 03 '16 at 20:14
  • 4
    If you want to make the hash stronger increase the `cost` as per example 2 of http://php.net/manual/en/function.password-hash.php – RiggsFolly Aug 03 '16 at 20:14
  • The question you should be answering is, "what am I trying to secure"? – Jay Blanchard Aug 03 '16 at 20:15
  • There is nothing wrong with re-hashing the password each time they login, so the hashes saved in the database are always changing regardless of whether or not the user changes their password. But I definitely wouldn't try to hash a hash. – mister martin Aug 03 '16 at 20:15
  • @JayBlanchard I was really just curious about it, and wanted to see if it could be done. – I Am Groot Aug 03 '16 at 20:17
  • @RiggsFolly `password_hash()` and `password_verify()` are what this whole post is about, I never mentioned anything about making my own hashing functions or anything. – I Am Groot Aug 03 '16 at 20:18
  • @mistermartin how and why is that beneficial? It sounds like a good idea, I just would love to know more. – I Am Groot Aug 03 '16 at 20:18
  • You can't get this to work, because [hashing is not encryption](http://stackoverflow.com/questions/4948322/fundamental-difference-between-hashing-and-encryption-algorithms). – Don't Panic Aug 03 '16 at 20:20
  • 4
    Please dont bite me if this i not penny accurate, but by default the cost is 10 and that basically means `password_hash()` rehashes 10 times so increasing the hash cost does what you want without any real effort on your behalf – RiggsFolly Aug 03 '16 at 20:22
  • @IAmGroot It just helps prevent stale hashes from hanging around forever. If your database were compromised, it may throw the attacker off in thinking that passwords are always changing even though they aren't. – mister martin Aug 03 '16 at 20:24
  • 1
    [Proper Password Hashing with PHP](http://jayblanchard.net/proper_password_hashing_with_PHP.html) – Jay Blanchard Aug 03 '16 at 20:43
  • Suggested reading: https://paragonie.com/blog/2015/04/secure-authentication-php-with-long-term-persistence – War10ck Aug 03 '16 at 20:44
  • 3
    It would actually not be possible to doubly `password_hash` a password unless you provided a fixed salt for the first iteration as when verifying the password you would need to hash with the same salt or else the second hash would be different and not match up. – Jonathan Kuhn Aug 03 '16 at 20:50

2 Answers2

2

The password_hash() function already does repeatedly hash the password, this is called key-stretching and is done to make brute-force attacks more difficult. So there is no point in using BCrypt twice.

The reason why it doesn't work in your case, is because password_hash() adds a random salt which becomes part of the resulting hash. This salt is necessary to verify the password, but with calling the function twice you loose the first salt.

martinstoeckli
  • 23,430
  • 6
  • 56
  • 87
1

The whole point of the password hashing API is to make it simple to implement secure hashing. Adding complexity as you are will not add any security, and it makes your code more difficult to debug. Use one password_hash and one password_verify. PHP's PASSWORD_DEFAULT is chosen to be very strong already:

To hash

$hash = password_hash($cleartext, PASSWORD_DEFAULT)

To verify

$isCorrect = password_verify($cleartext, $hash);

If you're not happy with PHP's very strong defaults, you can look into the cost setting. But it's really not needed. The docs say:

password_hash() uses a strong hash, generates a strong salt, and applies proper rounds automatically. password_hash() is a simple crypt() wrapper and compatible with existing password hashes. Use of password_hash() is encouraged.

BeetleJuice
  • 39,516
  • 19
  • 105
  • 165