I am trying to hash the password using SHA256 with random salt and random key in php and storing back hash value with salt and key used. I want to know does this provide adequate safety?

The following is code:

function hashpwd($string, $salt, $KEY)
    if(strcmp($KEY, '')==0)
        $KEY=openssl_random_pseudo_bytes(32); //key used for encryption and decryption
    if(strcmp($salt, '')==0)
        $salt= openssl_random_pseudo_bytes(32);
    $string = $salt.$string;
    $pwd = hash_hmac("SHA256", $string, $KEY);
    //echo "$salt".$pwd."<br>";
    return base64_encode($salt).base64_encode($KEY).$pwd;

Should I use double salt?

Note: Running on PC not sure of affording multiple iterations of hashing.


I changed the code to following, used password_hash() with BCRYPT and 5000 rounds:

function hashpwd($password)
        $strong = FALSE;
        while (!$strong){
            $salt = openssl_random_pseudo_bytes(32,$strong);
        $pwd = rtrim(password_hash($password, PASSWORD_BCRYPT, array('rounds'=> 5000, 'salt'=> $salt)));
        return $pwd;

Is the above code good enough?

I am not questioning the security of BCRYPT, My question was to know which of the two codes was better to use.

  • 4
    Is there a reason why you're rolling your own password hash instead of using something sensible like crypt() or password_hash()? – Mark Jun 19 '15 at 5:33
  • @Mark I needed hashing with key, so chose hmac. If you suggest crypt() over hmac, will go for it. – Abhishek V Jun 19 '15 at 5:40
  • 1
    HMAC stands for "message authentication code", not for "secure password storage code". Please drop your code and use bcrypt, pbkdf2 or scrypt, which are all password-based key derivation functions. – Steve Dodier-Lazaro Jun 19 '15 at 10:33
  • @SteveDL I have added edited code also – Abhishek V Jun 19 '15 at 11:26

You can definitely use multiple iterations of hashes; I can use thousands to hundreds of thousands of iterations even on my smartphone!

For PHP in particular, look at the password_hash() and password_verify() functions, per the PHP.net Password Hashing FAQ. Use the PASSWORD_BCRYPT mode, and set the cost as high as your hardware can handle and still provide response times the user is willing to accept - you can usually use a reasonable fraction of a second, since good password hashing is single-threaded.

Please read Thomas Pornin's canonical answer to How to securely hash passwords? before you try any password hashing. To summarize:

  • Never use a single pass of any hashing algorithm.
  • Never roll your own, which is what your example 2 is (and example 1 as well, if + means concatenation).
  • Username stored in the clear
  • Salt generated per user, 8-16 random bytes, stored in the clear
    • in pure binary or encoded into Base64 or hex or whatever you like.
  • Use BCrypt, SCrypt, or PBKDF2
  • Use as high an work factor/cost/iteration count as your CPU's can handle during expected future peak times.
  • For PBKDF2 in particular, do not ask for more binary output bytes than the native hash produces. I would say not less than 20 binary bytes, regardless.
    • SHA-1: output = 20 bytes (40 hex digits)
    • SHA-224: 20 bytes <= output <= 28 bytes (56 hex digits)
    • SHA-256: 20 bytes <= output <= 32 bytes (64 hex digits)
    • SHA-384: 20 bytes <= output <= 48 bytes (96 hex digits)
    • SHA-512: 20 bytes <= output <= 64 bytes (128 hex digits)
  • For PBKDF2 in particular, SHA-384 and SHA-512 have a comparative advantage on 64-bit systems for the moment, as 2014 vintage GPU's many attackers will use have a smaller margin of advantage for 64-bit operations over your defensive CPU's than they would on 32-bit operations.

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.