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!

2

4 Answers 4

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));
7
  • 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! May 11, 2015 at 8:37
  • @LoganWayne - I would suggest to use the password_hash() 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. May 11, 2015 at 8:40
  • So I would rather use password_hash() than PBKDF2? I'm now testing the password_hash(). May 11, 2015 at 8: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 for earlier versions. May 11, 2015 at 8:45
  • 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. :) May 11, 2015 at 8: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.

3
  • Thanks! I'm gonna be using PBKDF2 on my next project. ;) May 11, 2015 at 8:41
  • @LoganWayne it's actually easy to migrate your passwords as well if you want to secure them. May 11, 2015 at 8:42
  • 1
    Thank you for explaining why using the userid as a salt is bad! May 11, 2015 at 12:52
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.

1
  • 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! May 11, 2015 at 8: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.

1
  • 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. May 11, 2015 at 15:31

Not the answer you're looking for? Browse other questions tagged .