3

I'm storing username and password in a MySQL database and have them hashed using MD5. However, I'm only using the standard PHP function without any modification. Now, I read that MD5 is broken. How are you doing it? Do you run it several times through a different hash mechanism or add some form of salt?

Frank Vilea
  • 8,323
  • 20
  • 65
  • 86

9 Answers9

12

I'm amazed how people jump on the bandwagon of "damn, it's broken, I won't use it!", don't do the same mistake.

You can't make the MD5 better. Even using SHA-1 is vulnerable to same type of attacks as MD5. Using bcrypt will use A LOT more CPU than MD5 and SHA algorithms.

MD5 is designed to be fast, same as SHA. bcrypt isn't and it allows for more permutations, which makes it harder for someone to try to decrypt the original string.

You need to know why MD5 is considered "broken".

  • Because it's fast to calculate a rainbow table of passwords up to 6 characters in length.

Using today's computing power, one can create an array of characters and MD5 all permutations and map them to the original string. That's how you get a rainbow table. If someone downloads your database and then compares passwords to their rainbow table - they can obtain users' original password. Reason why this is dangerous is because people use same passwords for many things - including paypal and other money processing service. That's why you use so-called salt. That makes it even harder to obtain the original string, so salting your users' passwords (let's say by reversing them and MD5-ing the reversed input) will make it harder for the attacker to revert the hash to original string.

  • Because of collisions.

What's a collision? If you give hashing function two different strings and it returns the same hash - that's a collision. How does it translate to web and hashing passwords for logins? If you have the same hash for user1/password1 and user2/password2 - they could log on as someone else. That's where collisions play the role in security.

Reason why MD5 is considered broken is because MD5 returns same hash for strings that differ in small percentage. And it's not easy to calculate what that string might be! From mathematical point of view - yes, it's "broken" because if your string has 100 chars and it differs from other string in 10 chars (10% difference) - you get the same hash.

What applies for MD5 applies for ALL hashing algorithms. In the end, all of them don't have infinite number of possible hashes. However, some of them (like MD5) have less possible hashes and execute faster.

In the end, if someone got to your database - you have a bigger problem than using MD5 instead of bcrypt or SHA1.

Michael J.V.
  • 5,499
  • 1
  • 20
  • 16
  • Thanks Michael, I liked your answer best because I was thinking exactly the same thing as I learned more and more about hashes today. If sb is able to get to the DB, they probably also have access to the PHP files which means no matter how smart you think you are, they got you big time. In the end I used SHA-512 with some salts because speed really matters to me and it seemed to be fast. – Frank Vilea May 13 '11 at 11:48
  • I used SHA-512 because the string being put out is 128 characters long which makes it less likely to be matched - though probably not impossible. – Frank Vilea May 13 '11 at 11:50
  • 2
    For anyone else reading this, in PHP you simply use: hash("sha512", 123); You can add salts as you please. – Frank Vilea May 13 '11 at 11:50
  • I've been thinking about this response for a little while and I can see a flaw in the logic. A password should be stored in a way that NO ONE can possibly reverse engineer it or create an input that matches the hash. When you say "if someone got to your database - you have a bigger problem" that's really only half the issue. Passwords should be stored so that anyone who might have legitimate access to a database (developers working on the app for instance) cannot reverse engineer/match it. Because of this the balance of Security vs Speed should fall much more on Security. – Dormouse May 14 '11 at 11:00
  • 1
    `MD5` is **not** broken because it's *fast*. It's supposed to be fast. That's the chief feature of a cryptographic hash function. It's broken because there are both known collisions, and attack vectors to generate collisions. But it's not because *returns the same hash for strings that differ in small percentage*. That's not even true for non-engineered collisions. – ircmaxell May 14 '11 at 13:51
  • I think you're not reading my answer correctly, I didn't put quotes for no reason around certain words, nor did I claim MD5 is broken. Line you quoted was there to outline the point, I'm sorry if you couldn't understand it, I thought it was clear on everything as I was trying to outline the point without using complex, confusing words. Sadly, some people you can never satisfy, even when the answer is fine. – Michael J.V. May 16 '11 at 08:39
  • I think the collision problem is naturally avoided when two users on the same system didn't have the same username. using unique username (such as emails ... in nowadays websites and mobile apps) will make it impossible to have the same username+password couple. – a.boussema Oct 12 '14 at 06:51
  • I can't believe I just decrypted an md5 encrypted string on http://www.md5online.org/ It looks like md5 is really broken – lomse Oct 21 '14 at 09:52
6

Add a salt to each password stored that's not equal for every password

dynamic
  • 46,985
  • 55
  • 154
  • 231
  • Do you mean I should create let's say 3-5 different salts and then simply also note a number with it to retrieve which salt has been used? Or do you create a different salt for every password? How do you retrieve it in that case? – Frank Vilea May 13 '11 at 10:42
  • 1
    @Frank the same way you store the username and hash, add another column to your table. – Nick May 13 '11 at 10:46
1

Simply use MD5("yoursite.com".$string);

MD5 is not decryptable. The only possible way to crack it is through hash tables that brute force everything. If you add a random string that only you know they cant crack it.

Craig White
  • 13,492
  • 4
  • 23
  • 36
  • This is not true, given the pigeonhole principle any given hash can be produced by an infinite amount of possible inputs. It has been proven possible to calculate other possible matching inputs for a hash with MD5. Something a salt won't protect you from. – Dormouse May 13 '11 at 10:44
1

If you're worried about password security then you should use SHA1() (or alternative) rather than MD5(). Whilst MD5 is not decryptable, it can be beaten by either rainbow tables or matching the hash.

Salts will work against rainbow table but not against matching the hash which has been achieved with MD5.

Dormouse
  • 5,130
  • 1
  • 26
  • 42
1

There are a couple of things you should do.

  1. Use SHA instead of MD5. SHA is more cryptographically secure than MD5. The more bits the better!
  2. Use a salt. This makes rainbow table attacks more difficult.
  3. Strengthen your key by calculating the hash like as follows:

:

function strenghtened_hash( $password, $salt, $n ) {
    $crypted = sha( $password . $salt );
    for( $i = 0; $i < $n; $i++ ) {
        $crypted = sha( $crypted . $password . $salt );
    }
    return $crypted;
}

Now you should be in good shape!

stevevls
  • 10,675
  • 1
  • 45
  • 50
  • Thanks stevevls, is this computation very intense on the CPU? Because I would have to do it everytime sb logs in, wouldn't I? – Frank Vilea May 13 '11 at 10:48
  • How expensive it is depends on how many times you do the hash. If your server isn't heavily loaded, you can easily do a bunch of iterations. If you're worried, start with 16 and see where it takes you. – stevevls May 13 '11 at 10:50
1

You might be better off using using bcrypt for password storage to prevent rainbow-table attacks in case the bad guys get hold of your DB.

At the very least, dump MD5 (although computationally fast, not very secure these days) and use something a little more secure like SHA256 with a long salt.

Jay Sidri
  • 6,271
  • 3
  • 43
  • 62
0

Switch to a different hash mechanism (you can do it incrementally as people log in) and definitely use a (different for each user) salt!

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
0

You can use a thing called a salt. It means that you also save this salt into you database. It's a random string which is more or less long and is unique for each user.

Then, to check the password, you do something like this:

<?php 
     $crypted = md5($salt.$passwordFromForm);

     if($crypted == $passwordFromDB) {
         // user logged on
     }
?>
j_freyre
  • 4,623
  • 2
  • 30
  • 47
-1

You can make MD5 or any hashing function more strong by a method called "loop-hashing" i wrote about , read it here ,Good method to encrypte data, , using a loop "for" or "while" to encrypte password a lot of times with a random generated key number , really it's strong and so easy , so won't be scare from crackers again , no one can crack an encrypted "loop-hash" at the moment with the available databases .

Nikhil
  • 16,194
  • 20
  • 64
  • 81