2

I'm attempting to get my head around password security and salts/hashing, especially relating to PHP (with a view to storing info in MySQL).

With the following basic code, I'd like to know if I've grasped the concept or failed spectacularly!

<?php

$password = "password";
$iterations = 59999;
$salt = openssl_random_pseudo_bytes(16);

$hash = hash_pbkdf2("sha256", $password, $salt, $iterations, 20);
echo "hash_pbkdf2 (passord + salt + iteration count) = ", $hash;
echo "<br>";
echo "hash_hmac (above hash + password) =", hash_hmac('sha256', $hash, $password);

?>

What I'd like to know is;

  • Is openssl_random_pseudo_bytes the best way of creating a CSPRNG salt?
  • I realise that the salt and the two generated hashes would need to be stored in MySQL, but are two hashes needed? Is this overkill or a backwards way or combining the iteration aspect I require, along with a secure/recommended HMAC-SHA256 generated hash?
  • Is any of this secure by 2018 standards?
Gary
  • 107
  • 10
  • http://php.net/manual/en/faq.passwords.php you also might want to read https://stackoverflow.com/questions/17380234/hash-pbkdf2-vs-password-hash-php-functions – Raymond Nijland Feb 19 '18 at 12:23
  • @RaymondNijland I'm not sure either of those two help answer my questions ... after reading many, many things online (not specific to PHP), I'm led to believe an HMAC-SHA256 hash is the most secure but I don't believe the hash_pbkdf2 PHP function has the option to use it, just the "basic" SHA256 hash ... which is why I'm hashing things twice in my code ... – Gary Feb 19 '18 at 12:41
  • When you use `hash_pbkdf()` with SHA256, that means it internally uses HMAC-SHA256. But that doesn't really mean anything ... Statements like "HMAC-SHA256 hash is the most secure" are patently false. So is the one that Blowfish is better. It all depends on *how* they are used and in what context. – Narf Feb 19 '18 at 12:58
  • HMAC-SHA256 isn't that secure because it can be eazy implemented to run on GPU's so that GPU's can extremely fast bruteforce the hashes. .. password_hash defaults to Blowfish. Blowfish which is designed it can't run efficient on GPU's – Raymond Nijland Feb 19 '18 at 12:59
  • To clarify on my previous comment, both SHA256 and Blowfish are cryptographic *primitives*. They're building blocks; neither is enough to securely hash a password on its own (but it is true that you need less rounds with Blowfish than with SHA256). – Narf Feb 19 '18 at 13:04

1 Answers1

2
  • Is openssl_random_pseudo_bytes the best way of creating a CSPRNG salt?

It should be sufficient on most systems, but not always and you're not using it in a way that prevents the bad cases, so no - it's not. The best tool for the job is random_bytes().

However, you shouldn't be generating the salt on your own anyway; read below.

  • I realise that the salt and the two generated hashes would need to be stored in MySQL, but are two hashes needed? Is this overkill or a backwards way or combining the iteration aspect I require, along with a secure/recommended HMAC-SHA256 generated hash?

You certainly don't need 2 hashes. In particular, I have no idea why you thought you may need the HMAC. The sample code doesn't even show how you'd use that.
In fact, the iterations number in PBKDF2 refers to how many HMAC rounds it does internally, so you're kinda just increasing the iterations count by one with that (although not quite in the same way). The reason why it needs so many iterations in the first place is because HMAC keys are not like user passwords. A key is supposed to be like a salt - random, unpredictable, raw binary data; a password is commonly easy to remember by a user, so it doesn't have the same level of entropy.

  • Is any of this secure by 2018 standards?

Technically, the PBKDF2 part on its own is secure when guaranteed a cryptographically secure salt. Note that I say it is technically secure and with a conditional ...

All hash_-prefixed functions are part of a generic hashing extension, yet hash_pbkdf2() is the only function in there that can create a secure password hash, and not without external aid.
Hashing has a lot of appliances and password hashing is only one of them. Creating the hash is one part, the salt - another, validation - a third; etc.

What you should be using is PHP's dedicated Password Hashing extension (refer to How to use password_hash for more info on usage), which is made specifically for what you need and is secure by design for its purpose - meaning it automates absolutely everything possible, from salt and hashing to time-safe validation.

Narf
  • 14,600
  • 3
  • 37
  • 66