-1

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.

EDIT:

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

function hashpwd($password)
{
        $salt='';
        $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()](http://php.net/manual/en/function.crypt.php) or [password_hash()](http://php.net/manual/en/function.password-hash.php)? – Mark Jun 19 '15 at 05: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 05: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
  • possible duplicate of [Do any security experts recommend bcrypt for password storage?](http://security.stackexchange.com/questions/4781/do-any-security-experts-recommend-bcrypt-for-password-storage) – Steve Dodier-Lazaro Jun 19 '15 at 11:51
  • @ please see the [PHP password_hash manual page](https://php.net/manual/en/function.password-hash.php) examples which are also linked to in my answer and Mark's comment; rounds is not a supported option for BCRYPT, cost is. Additionally, there is no need to generate your own salt; password_hash() is designed to automatically generate a cryptographically secure salt for you, which is the intended method of operation. As the man page says, "It is strongly recommended that you do not generate your own salt for this function." – Anti-weakpasswords Jun 19 '15 at 11:58
  • cost parameter did throw the error, so referred PHP password hash manual, it mentioned rounds as parameter when constant used. – Abhishek V Jun 19 '15 at 12:16
  • @Abhishek V - can you please share a link to that particular man page, as my link above is different. Also, just to be sure, please time 5000 rounds and 500000 rounds, and make sure that more rounds actually takes longer :) – Anti-weakpasswords Jun 20 '15 at 03:19

1 Answers1

2

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.
Anti-weakpasswords
  • 9,850
  • 2
  • 24
  • 52