11

I've been reading Stack Overflow questions for about 15 minutes now and every single one seems to contradict the previous one I read. Bcrypt, SHA1, MD5, and so on. I currently MD5 my passwords, but I want to make my database more secure in case of a breach.

I know this has been asked a million times, but I can't seem to find a decent answer anywhere else.

Thanks.

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
iamandrus
  • 1,400
  • 2
  • 16
  • 25
  • possible duplicate of [Secure hash and salt for PHP passwords](http://stackoverflow.com/questions/401656/secure-hash-and-salt-for-php-passwords) – Ilmari Karonen Jan 20 '13 at 23:03

6 Answers6

11

The reason you see contradictory answers is because there is no right one. You should use the most secure method that your application can support. More secure = more overhead.

MD5 has been broken and cracked.

According to this article, SHA1 is broken. However it has not yet been cracked.

bcrypt has not (to the best of my knowledge) been found to be broken.

Given enough CPU cycles, any hashing or encryption algorithm can eventually be circumvented. Your decision should balance the security of your data with the performance of your application.

Given those caveats, bcrypt is the defacto standard at this time. It is designed for strength, not speed, and is not known to be broken. For an index of information about bcrypt, see the bcrypt article on Wikipedia.

George Cummins
  • 28,485
  • 8
  • 71
  • 90
  • 6
    MD5, SHA1, and similar hashing algorithms are designed to be *fast*. That's not really what you want when securing passwords. bcrypt is designed to be slow (and, further, it's designed to scale so that as faster processors come out, you can turn up the difficulty) – Eli Jun 24 '11 at 19:45
  • 1
    Bcrypt is the current best practice. – Jacco Jul 08 '11 at 11:30
9

I'd go with bcrypt. It drastically reduces the ability to generate rainbow tables.

http://codahale.com/how-to-safely-store-a-password/

It's important to note that salts are useless for preventing dictionary attacks or brute force attacks. You can use huge salts or many salts or hand-harvested, shade-grown, organic Himalayan pink salt. It doesn't affect how fast an attacker can try a candidate password, given the hash and the salt from your database.

ceejayoz
  • 176,543
  • 40
  • 303
  • 368
  • 2
    You left out the important part: "_Salt or no, if you're using a general-purpose hash function **designed for speed** you're well and truly effed._" – MicE Jun 24 '11 at 19:48
  • 1
    +1 for mentioning the often forgotten Himalayan pink salt. It's the organic part that makes the difference. – Eddie Parker Jun 25 '11 at 02:48
  • After some research into this same question myself it seems the opinion at the minute is bcrypt is the best choice here. – Dale Apr 20 '12 at 21:17
  • So, only if `given the hash and the salt from your database`, the attacker can crack MD5 or SHA1 oe maybe even bcrypt. BUT, if he isn't able to detect what the salt is, can I safely assume that my passwords (actually their salted hashes) are safe from hack attacks? – bad_keypoints Jul 30 '13 at 02:46
  • @ronnieaka No, hashes should not be considered sensitive data. With bcrypt, it **doesn't matter** if an attacker has the password's hash. – ceejayoz Jul 30 '13 at 14:31
2

First of all, MD5 isn't a very good option nowadays. If an attacker would get to your database, and get the MD5 hashes, it is almost certain that he will be also able to crack them. MD5 hashes of weak passwords can be cracked even bruteforce by a casual computer.

You should google some articles about salting your hashes, and use that method combined with a stronger hashing algorithm (at least SHA1), and maybe repeat the process few times.

I am not going to write about salting, as many articles have been already written about it, and also here on Stack Overflow you can find many good discussions about the problem. E.g. Why do salts make dictionary attacks 'impossible'? or How does password salt help against a rainbow table attack?

Community
  • 1
  • 1
Teo.sk
  • 2,619
  • 5
  • 25
  • 30
1

When a user registers, create a random salt using, for example, the following function:

$bytes = 50;
$salt = base64_encode(openssl_random_pseudo_bytes($bytes));

Store this in a database table. The best is to store it in an external database. After this, create a random code and store it together with your salt into the external database. Than store the random code in your users table and it will almost be impossible for an attacker to find your salt.

After this, store your password in, for example, this way:

$password_to_store_in_mysql = hash('sha512', $salt . $user_password);

When a user logs in, get the salt out of the external database en check if the salt and the password match.

Jan Willem
  • 1,280
  • 1
  • 9
  • 9
1

Use MD5, SHA1 or whatever encryption you want with a SALT.

For this example, I'm just going to use MD5 for explanation sake.

So user chooses a password, store that in $password for instance.

Now create a salt that's specific to your application.

$salt = 'my very own salt'; // or maybe make a random string for your salt

Then do

$more_difficult_password = md5($salt . $password);

This way people can't use dictionary attacks by just googling your MD5 string if it ever got compromised somehow.

yoda
  • 10,834
  • 19
  • 64
  • 92
Steve Nguyen
  • 5,854
  • 5
  • 21
  • 39
  • @george You can also use any secret key of your website with salt and password..ie md5($secretkey.$salt.$password) – GitsD Jun 24 '11 at 19:29
  • 1
    You can also keep a default salt thats the same for every user and on top of that a (I like to call it pepper ^_^) user-specific salt in the users table. That way you have a better encryption and if your database ever got hacked it will confuse crackers since you've added another salt throughout your app – Gilly Apr 15 '13 at 09:23
0

You can use secret key of your website and particular salt of every user with your password. Your secret key of your website should be saved in your database and then fetch it and use.

The combination becomes.

$secret = "your key from database";
$salt = "user salt";// make it randomly
$password = $_POST['password'];

$new_pass = md5($secret.$salt.$password);

Now this combinations will store in database.

At the time of login, use again this combination to match.

I think it can help more to secure your application.

Cheers..!!

GitsD
  • 668
  • 2
  • 8
  • 16