php users passwords protection

2019-08-28 21:23发布

问题:

i'm testing several combinations of sha1 and md5:

<?php
$test = 'fail test';
echo nl2br ("Text: $test\n");
echo nl2br ("md5: ".md5($test)."\nsha1: ".sha1($test)."\nsha1(md5): ".sha1(md5($test))."\nmd5(sha1): ".md5(sha1($test)));
?>

Output:

Text: fail test
md5: 748410d0085967c496d54dd8fcbecc96
sha1: d730125e8cb8576459173655148fb6896ef44c09
sha1(md5): faa3ebeecfec45e509e93e6b245a69e2a78785ea
md5(sha1): b48e89b85c350c91eb302c1de96d4249

Which one better, or maybe user something else ? If yes, what then ?

回答1:

Hashing a hash adds no extra security. (In fact, it might make it worse if the person has a hash-of-hash lookup table.)

The best hash will be the one that is computationally the most expensive to perform without any vulnerabilities. I would hash passwords with at least sha-256.

Always hash your passwords with a salted key. This key should be unique per password. It doesn't need to be stored privately. The purpose of a salted password is that the hacker who gained access to your database cannot simply compare the hash with a known list of hashes that correspond to common passwords. Instead, he must try to brute force the password by trying every possible password.

By using a unique salt per password, you guarantee that each hash in the database is different, even if they use the same password.

To salt a password, simply create a random string of characters and append it to the password. Here's a sample hash with a 48-bit salt and sha-256:

function make_password($password)
{
  # random 48-bit salt (8 chars when base64 encoded)
  $salt = base64_encode(pack('S3', mt_rand(0,0xffff), mt_rand(0,0xffff), mt_rand(0, 0xffff)));

  return $salt.hash('sha256', $salt.$password);
}

function check_password($password, $hash)
{
  $salt = substr($hash, 0, 8);
  return hash('sha256', $salt.$password) == substr($hash, 8);
}

$password = 'password';
$hash = make_password('password');

echo $hash."\n";

var_dump(check_password('password', $hash));
var_dump(check_password('wrong', $hash));

Every time you run it, the hash will be different. To validate a password, you select the row where the username matches, and then call check_password($password_from_user, $hash_from_db).

Here's a sample output:

AzrD1jZzc693714a43ad5dfd4106c0a620ef23ff9915070711fa170a6670b8164862b496
bool(true)
bool(false)

You can use a larger salt or a stronger hashing algorithm if you prefer. But at minimum, I would use something like the above.



回答2:

Both of them are cryptographic hash functions that operate 1-way only, the main difference being that MD5 output size is 128 bits whereas SHA-1 is 160 bits. In brief, I don't see they are much different to use despite MD5 is more common these days.

Curiously, I can't really see how md5($text) is different from md5(sha($text)) when they all encrypted to a 32 character-long string, what about md5($text."token") for example?

And, what do you mean by better? Is it more good looking or more security? See bcrypt if you prefer security :) Wikipedia: http://en.wikipedia.org/wiki/Bcrypt



回答3:

You should salt your passwords, ALWAYS. This doesn't stop brute force through a login form but if someone managed to get the details, it would be much harder to crack (rainbow tables would be useless unless they manage to get your salt too)

Essentially, if you adding onto the original data or mangling in a controlled way, it will make security a little better. No-one can ever reverse a hash but they can find other inputs thats match the hash. Mangling the user input will make it harder to login for the hackers.

for example, if a user's pass is 123456, if you add a salt of "salt" to it so it becomes 123456salt, the MD5 of this would be 207acd61a3c1bd506d7e9a4535359f8a. A hacker could crack this to become 123456salt but when it comes to using that on your login form, your code will add salt again and the login will fail.



标签: php security