7

I've been using the sha1() function to hash password before inserting it into my database. But I have this procedure so that it just won't be the password to be hashed.

My page would register a user along with their password. After submission, it would enter first the username into the database, then get the unique ID of that username. Then the system will combine it with the password.

$password = $userid.$password;

Then use sha1() to hash the password:

$password = sha1($password);

Then update the password in the database with that ID.

I used the user id like a salt.

Question

Is this a good technique? Though the only users of the system are the other department of our company, I think that it is enough for them in my opinion.

And what if I have a major project in the future that would required better security of password, will this be enough? Thanks!

Logan Wayne
  • 191
  • 1
  • 6
  • 4
    possible duplicate of [How to securely hash passwords?](http://security.stackexchange.com/questions/211/how-to-securely-hash-passwords) and/or [Is it a good idea to use the user's username as a salt when hashing a password like hash(username_str + password_str)?](https://security.stackexchange.com/questions/69421/is-it-a-good-idea-to-use-the-users-username-as-a-salt-when-hashing-a-password-l) – tim May 11 '15 at 11:39
  • Please keep in mind that using PHP will mean that the password will be sent to the server to encrypt or verify. The problem with this is that it will only protected by `https://`. You might as well use Javascript to send a hash to the server to hash the way your answer mentioned. This will add a second layer of security and prevent you from having access to the password at all or from keeping it in any memory on the server. – Alec O'Connor Jun 15 '17 at 14:42

4 Answers4

15

No a salt should not be derrived from other known parameters, a salt should be globally unique. So the best you can do is to generate a really random salt for each password. Todays operating systems have a "random source", on a deterministic computer it is the best you can do to read form this random source (DEV_URANDOM).

Beside this, the SHA-* hash family is not appropriate to hash passwords, because this algorithms are ways too fast and therefore can be brute-forced too easily (3Giga SHA1/s). Instead you should use a slow key-derivation function with a cost factor, like BCrypt, PBKDF2 or SCrypt.

For PHP there exists a dedicated function to hash passwords, it is designed in a way, so it can change the algorithm in future if necessary, but can still verify old hashes:

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_DEFAULT);

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

// This way you can define a cost factor (by default 10). Increasing the
// cost factor by 1, doubles the needed time to calculate the hash value.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT, array("cost" => 11));
martinstoeckli
  • 5,189
  • 2
  • 27
  • 32
  • I'm now further studying and simply implemented an example in my local computer the PBKDF2. I would use it in my next project! Thanks! – Logan Wayne May 11 '15 at 08:37
  • @LoganWayne - I would suggest to use the [password_hash()](http://www.php.net/manual/en/function.password-hash.php) function instead, it generates a BCrypt hash which is difficult to use on GPUs. And btw. it is also much easier, it takes care of generating a safe salt and is future proof. – martinstoeckli May 11 '15 at 08:40
  • So I would rather use `password_hash()` than PBKDF2? I'm now testing the `password_hash()`. – Logan Wayne May 11 '15 at 08:42
  • @LoganWayne - Yes that is what i would recommend, it is implemented in fast native code in PHP 5.5 and later, but there also exists a [compatibility pack](https://github.com/ircmaxell/password_compat/blob/master/lib/password.php) for earlier versions. – martinstoeckli May 11 '15 at 08:45
  • Will having only the `cost` in the `$options` be enough for security? I'm using the second example. – Logan Wayne May 11 '15 at 08:49
  • @LoganWayne - I assume that your question targets the password_hash() function. Yes you can either use no parameters, or a cost factor alone, it is not a good idea to pass a salt though, because the function already generates a safe one. Added an example in the answer. – martinstoeckli May 11 '15 at 08:54
  • 1
    Yeah. I'm trying the second example in the `password_hash()` where it sets the cost manually. Thanks for this! It has less code than using PBKDF2. :) – Logan Wayne May 11 '15 at 08:57
6

There are two things wrong with what you are doing with what you are doing:

  • your algorithm in it's simple form is fast and thus not suited for password hashing. (the properties you want in a password hashing algorithm is it being fast enough to run once, but slow if you need to run it several times as well as being unfriendly when being run on FPGA/ASICs or GPUs.
  • Your salting is bad. A salt should be globally unique, meaning it should have a level of randomness which is so uncommon, that no chance exists that it has occured as salt before anywhere in the world. This is to prevent attacks where several databases have been leaked, as it's likely that users will re-use their username. Therefore it's bad practice to use a username as salt, as why it may be unique to your database, it will not be to another database using the same principle.

There are currently three accepted algorithms: bcrypt, scrypt and pbkdf2.

Lucas Kauffman
  • 54,229
  • 17
  • 113
  • 196
3

A drawback of SHA1 is that it is fast, so it is easier to create rainbow tables and brute-force it. Adding a salt helps, but if the password is weak, then "number + weak password" may well be in the rainbow tables along with the password.

PHP provides built-in password mechanisms. When you use these, the crypt function automatically generates a salt for you that is stored with the hashed password+salt.
This is the recommended way of using (salted) password hashes in PHP.

S.L. Barth
  • 5,504
  • 8
  • 39
  • 47
  • I've read about lookup rainbow tables and brute-force before and yeah.. I think my procedure is weak and would still be cracked by those two. Thanks for this! – Logan Wayne May 11 '15 at 08:36
-1

Simply storing password using sha1/md5 or any hashing function is not a good practice. Many sites are providing dictionary to crack these password.

Solution is to use a powerful salt to add in password, then convert it to sha1 hash. You are using very basic or a kind of simple padding.

You can use rand, time stamp, double hashing as salt. Performance wise it will cost you little more, but your app will be secured.

  • 2
    Even correctly salted SHA is not a good way to store passwords because SHA algorithms are so fast, as other answers have pointed out. – Aron Foster May 11 '15 at 15:31