SHA1 vs md5 vs SHA256: which to use for a PHP login?

160,048

Solution 1

Neither. You should use bcrypt. The hashes you mention are all optimized to be quick and easy on hardware, and so cracking them share the same qualities. If you have no other choice, at least be sure to use a long salt and re-hash multiple times.

Using bcrypt in PHP 5.5+

PHP 5.5 offers new functions for password hashing. This is the recommend approach for password storage in modern web applications.

// Creating a hash
$hash = password_hash($password, PASSWORD_DEFAULT, ['cost' => 12]);
// If you omit the ['cost' => 12] part, it will default to 10

// Verifying the password against the stored hash  
if (password_verify($password, $hash)) {
    // Success! Log the user in here.
}

If you're using an older version of PHP you really should upgrade, but until you do you can use password_compat to expose this API.

Also, please let password_hash() generate the salt for you. It uses a CSPRNG.

Two caveats of bcrypt

  1. Bcrypt will silently truncate any password longer than 72 characters.
  2. Bcrypt will truncate after any NUL characters.

(Proof of Concept for both caveats here.)

You might be tempted to resolve the first caveat by pre-hashing your passwords before running them through bcrypt, but doing so can cause your application to run headfirst into the second.

Instead of writing your own scheme, use an existing library written and/or evaluated by security experts.

TL;DR - Use bcrypt.

Solution 2

I think using md5 or sha256 or any hash optimized for speed is perfectly fine and am very curious to hear any rebuttle other users might have. Here are my reasons

  1. If you allow users to use weak passwords such as God, love, war, peace then no matter the encryption you will still be allowing the user to type in the password not the hash and these passwords are often used first, thus this is NOT going to have anything to do with encryption.

  2. If your not using SSL or do not have a certificate then attackers listening to the traffic will be able to pull the password and any attempts at encrypting with javascript or the like is client side and easily cracked and overcome. Again this is NOT going to have anything to do with data encryption on server side.

  3. Brute force attacks will take advantage weak passwords and again because you allow the user to enter the data if you do not have the login limitation of 3 or even a little more then the problem will again NOT have anything to do with data encryption.

  4. If your database becomes compromised then most likely everything has been compromised including your hashing techniques no matter how cryptic you've made it. Again this could be a disgruntled employee XSS attack or sql injection or some other attack that has nothing to do with your password encryption.

I do believe you should still encrypt but the only thing I can see the encryption does is prevent people that already have or somehow gained access to the database from just reading out loud the password. If it is someone unauthorized to on the database then you have bigger issues to worry about that's why Sony got took because they thought an encrypted password protected everything including credit card numbers all it does is protect that one field that's it.

The only pure benefit I can see to complex encryptions of passwords in a database is to delay employees or other people that have access to the database from just reading out the passwords. So if it's a small project or something I wouldn't worry to much about security on the server side instead I would worry more about securing anything a client might send to the server such as sql injection, XSS attacks or the plethora of other ways you could be compromised. If someone disagrees I look forward to reading a way that a super encrypted password is a must from the client side.

The reason I wanted to try and make this clear is because too often people believe an encrypted password means they don't have to worry about it being compromised and they quit worrying about securing the website.

Solution 3

As Johannes Gorset pointed out, the post by Thomas Ptacek from Matasano Security explains why simple, general-purpose hashing functions such as MD5, SHA1, SHA256 and SHA512 are poor password hashing choices.

Why? They are too fast--you can calculate at least 1,000,000 MD5 hashes a second per core with a modern computer, so brute force is feasible against most passwords people use. And that's much less than a GPU-based cracking server cluster!

Salting without key stretching only means that you cannot precompute the rainbow table, you need to build it ad hoc for that specific salt. But it won't really make things that much harder.

User @Will says:

Everyone is talking about this like they can be hacked over the internet. As already stated, limiting attempts makes it impossible to crack a password over the Internet and has nothing to do with the hash.

They don't need to. Apparently, in the case of LinkedIn they used the common SQL injection vulnerability to get the login DB table and cracked millions of passwords offline.

Then he goes back to the offline attack scenario:

The security really comes into play when the entire database is compromised and a hacker can then perform 100 million password attempts per second against the md5 hash. SHA512 is about 10,000 times slower.

No, SHA512 is not 10000 times slower than MD5--it only takes about twice as much. Crypt/SHA512, on the other hand, is a very different beast that, like its BCrypt counterpart, performs key stretching, producing a very different hash with a random salt built-in and will take anything between 500 and 999999 times as much to compute (stretching is tunable).

SHA512 => aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
Crypt/SHA512 => $6$rounds=5000$usesomesillystri$D4IrlXatmP7rx3P3InaxBeoomnAihCKRVQP22JZ6EY47Wc6BkroIuUUBOov1i.S5KPgErtP/EN5mcO.ChWQW21

So the choice for PHP is either Crypt/Blowfish (BCrypt), Crypt/SHA256 or Crypt/SHA512. Or at least Crypt/MD5 (PHK). See www.php.net/manual/en/function.crypt.php

Solution 4

Use SHA256. It is not perfect, as SHA512 would be ideal for a fast hash, but out of the options, its the definite choice. As per any hashing technology, be sure to salt the hash for added security.

As an added note, FRKT, please show me where someone can easily crack a salted SHA256 hash? I am truly very interested to see this.

Important Edit:

Moving forward please use bcrypt as a hardened hash. More information can be found here.


Edit on Salting:

Use a random number, or random byte stream etc. You can use the unique field of the record in your database as the salt too, this way the salt is different per user.

Solution 5

What people seem to be missing is that if the hacker has access to the database he probably also has access to the php file that hashes the password and can likely just modify that to send him all the successful user name password combos. If he doesn't have access to the web directory he could always just pick a password hash it, and write that into the database. In other words the hash algorithm doesn't really matter as much as system security, and limiting login attempts also if you don't use SSL then the attacker can just listen in on the connection to get the information. Unless you need the algorithm to take a long time to compute (for your own purposes) then SHA-256 or SHA-512 with a user specific salt should be enough.

As an added security measure set up a script (bash, batch, python, etc) or program and give it an obscure name and have it check and see if login.php has changed (check date/time stamp) and send you an email if it has. Also should probably log all attempts at login with admin rights and log all failed attempts to log into the database and have the logs emailed to you.

Share:
160,048
Tony Stark
Author by

Tony Stark

Updated on October 12, 2020

Comments

  • Tony Stark
    Tony Stark over 3 years

    I'm making a php login, and I'm trying to decide whether to use SHA1 or Md5, or SHA256 which I read about in another stackoverflow article. Are any of them more secure than others? For SHA1/256, do I still use a salt?

    Also, is this a secure way to store the password as a hash in mysql?

    function createSalt()
    {
        $string = md5(uniqid(rand(), true));
        return substr($string, 0, 3);
    }
    
    $salt = createSalt();
    
    $hash = sha1($salt . $hash);
    
  • Tony Stark
    Tony Stark over 14 years
    also, i'm very new at this: are sha1, sha256, and md5 all the 'hashes' you refer to?
  • Johannes Gorset
    Johannes Gorset over 14 years
    Yes. I'm referring to SHA1, SHA256 and MD5 and a series of other hashes that are optimized for speed. You don't want to use a hash optimized for speed to secure a password. There are many good articles discussing why, and I like this one in particular: chargen.matasano.com/chargen/2007/9/7/…
  • Tony Stark
    Tony Stark over 14 years
    is there a bcrypt function in php...? (that might be a totally newb question)
  • Johannes Gorset
    Johannes Gorset over 14 years
    It's included in the "crypt" function since PHP 5.3. If you have an earlier version, I'd look into the "phpass" framework for the next best thing.
  • arbales
    arbales over 14 years
    But their optimized for speed, meaning that they enable brute-force hacking.
  • Kyle Rosendo
    Kyle Rosendo over 14 years
    Fact remains, this is to secure a password. By using a hash with a salt, then add a 3 attempt limit on the website, you substantially slow down the hackers attempts (even brute forcers). Using any pure encryption, you now have another problem - securing the key. If the key is found, your entire database is compromised (if no salt is added). Hashes however, you will never get the original password out of the system, and thats how it should be.
  • Johannes Gorset
    Johannes Gorset over 14 years
    As noted, the problem with the MD and SHA-series is that they are optimized for speed. It is inevietable that hashes of this nature become increasingly insecure as computing evolves.
  • Kyle Rosendo
    Kyle Rosendo over 14 years
    Anything becomes increasingly bad/insecure/etc as computing evolves. By the time SHA512 etc. are hacked, there will be more secure algorithms available. This is the nature of computing in any case.
  • Tony Stark
    Tony Stark over 14 years
    what is a good way to make a salt in php? have example code? i imagine i shouldn't just pick something like 'giraffe'
  • Johannes Gorset
    Johannes Gorset over 14 years
    @Kyle Rozendo Brute-force attacks are not exclusive to the login system of your website. The real risk lies in a compromised database. It does not take long to generate dictionaries (complete with salts) for MD/SHA hashes.
  • Johannes Gorset
    Johannes Gorset over 14 years
    @Kyle Rozendo You are incorrect. Bcrypt does not become insecure as computing evolves, which is exactly why you should use it.
  • Kyle Rosendo
    Kyle Rosendo over 14 years
    No no. Use a random number, or random byte stream etc. You can use the unique field of the record in your database as the salt too, this way the salt is different per user.
  • Kyle Rosendo
    Kyle Rosendo over 14 years
    @FRKT - If your database is reached, you are screwed in any case. Before you secure anything, your entire internal network should be bullet proof.
  • Tony Stark
    Tony Stark over 14 years
    so do i use rand() or something to make a random number?
  • Tony Stark
    Tony Stark over 14 years
    so if i were to implement crypt in PHP, I would just call crypt on my password i want for the admin, store that in a mysql DB, and then just run crypt() on the password entered on the login page and make sure they are equal, right?
  • Johannes Gorset
    Johannes Gorset over 14 years
    @Kyle Rozendo: "Bullet proof"? You should know there's no such thing in this industry. Either way, passwords encrypted with bcrypt remain little more than a hash even if your database is compromised. There's no reason to use MD/SHA if bcrypt is available.
  • Kyle Rosendo
    Kyle Rosendo over 14 years
    Sure, but you are absolutely missing the point. If they have access to the database, they don't actually need the password anymore - it is irrelevant. You will be finished.
  • Tony Stark
    Tony Stark over 14 years
    i only have 1 person in my DB (1 admin). so the unique ID would be 1. that's not a very good salt, right? maybe i'm extremely ignorant on this, but i thought that the longer the salt was, and the more random, the better?
  • Johannes Gorset
    Johannes Gorset over 14 years
    @Kyle Rozendo: It is absolutely relevant, seeing that most users use the same password for multiple services.
  • Johannes Gorset
    Johannes Gorset over 14 years
    @hatorade: The longer the salt, the more secure the password.
  • Kyle Rosendo
    Kyle Rosendo over 14 years
    @FRKT - Firstly, the hashed password will not ever be able to be recovered if hashed with a salt (I use GUID salts). @hatorade - If its still early days in the design, try use a GUID field as your ID. Not certain how to do it using MySQL though, but in MSSQL it provides some very nice benefits.
  • Tony Stark
    Tony Stark over 14 years
    so, if my password is 'zebra': crypt(zebra) -> store this in DB. At login page, user types in 'zebra', and i just check 'crypt('zebra') = stored_hash_for_this_user
  • Johannes Gorset
    Johannes Gorset over 14 years
    @hatorade: Any random and long value will do.
  • Tony Stark
    Tony Stark over 14 years
    in other words, i don't put a salt anywhere, it just adds one for me if i use that syntax?
  • Kyle Rosendo
    Kyle Rosendo over 14 years
    I am not fighting you on the merits of bcrypt, or the pitfalls of hashes. I am simply saying that an assumption such as "are easily cracked" is completely silly. Every single form of security can and will be broken. The one thing I definitely give you is that you are definitely making life hard enough for a hacker to go elsewhere.
  • President James K. Polk
    President James K. Polk over 14 years
    FRKT is dangerously oversimplifying about the "ease" of cracking the MD5/SHA* hashes compared with bcrypt. However, bcrypt sounds like the right tool for the job, whereas the programmer has to understand about salting and iteration counts with the MD5/SHA*.
  • President James K. Polk
    President James K. Polk over 14 years
    @FRKT: PKCS5 has been around for about 15 years now and recommends salting and iteration counts. Blowfish has also been optimized for speed, even though bcrypt deoptimizes it. Essentially, bcrypt is about the same as salting/iterating the MD5/SHA* hashes.
  • Johannes Gorset
    Johannes Gorset over 14 years
    @GregS: You're right that MD5/SHA* passwords that have been hashed multiple times with an unique salt become harder to crack (in fact I'm inclined to agree with you that it would no longer be "easy"), but the fact remains that bcrypt is the better option simply because it's slow as hell and MD5/SHA* isn't.
  • stan
    stan over 14 years
    Tell me an instance where SHA256 has been hacked?
  • Johannes Gorset
    Johannes Gorset over 14 years
    @Stanislav Palatnik I don't know that SHA256 has, but that's besides the point; bcrypt is a better choice.
  • stan
    stan over 14 years
    @FRKT : unless you are developing mission critical applications, you can use SHA512(I'll give in and say SHA256 will not give me peace of mind with sensitive applications). SHA512 will not be cracked by the time SHA3 comes out. Then you can switch to SHA3 hashing.
  • Johannes Gorset
    Johannes Gorset over 14 years
    @Stanislav Palatnik SHA512 is a good alternative. Don't get me wrong; I'm not saying a stretched and salted SHA512 hash is insecure. It's secure. Even so, the fact remains that bcrypt is more secure, and so I see no reason not to use it.
  • Mathias Nielsen
    Mathias Nielsen over 13 years
    @Johannes Gorset, I realize this a very old thread, but choosing a solution that is slow by design may be a good idea for security, but come on. These things get run every time someone logs on to the site. Unless it's a banking app or something similar, salted hash should be plenty good.
  • Mathias Nielsen
    Mathias Nielsen over 13 years
    @Johannes Gorset, Also, the article you linked, as well as what others have mentioned. Using a unique salt and then storing it in the DB really doesn't seem to help alot. If the DB is breached, the unique salts will also be stolen and neatly available alongside the hashed passwords, how does that stop anyone for more than a couple of minutes?
  • Nico Burns
    Nico Burns over 13 years
    @Mathias Nielsen - it means that the hacker has to repeat their hack for each user, rather than running the same one for all users in the table which is obviously quicker.
  • Johannes Gorset
    Johannes Gorset over 13 years
    @Mathias Nielsen: A couple of minutes? Try a couple of years. :-)
  • fredden
    fredden over 12 years
    <a href="openwall.com/phpass/">PHPass</a> is a good library for this sort of thing.
  • Brad Proctor
    Brad Proctor almost 12 years
    Actually, pbkdf2 is preferable to bcrypt. unlimitednovelty.com/2012/03/dont-use-bcrypt.html
  • Cypher
    Cypher over 11 years
    Huh. bcrypt is better because it's slow? Does that apply to operating systems as well? What a silly argument.
  • Johannes Gorset
    Johannes Gorset over 11 years
    @Cypher: bcrypt is designed to be slow in the interest of being equally slow to crack.
  • CᴴᴀZ
    CᴴᴀZ over 10 years
    Well stated. Cyber Security shall be preferred over hashing techniques, they not only save your data but also keep the Server defense ready.
  • James McMahon
    James McMahon over 10 years
    This is really misinformed. Of course securely hashing passwords in the database doesn't improve security at an application level or database level. It's not a catch all for security. You want to securely hash user password in your database for 2 reasons; first the customer is trusting you with their password, which they may or may not use on other sites, so you want to make sure this is not recoverable, even if you db is compromised, second, you want to remove liability in case of security breach. I don't know of any lawsuits offhand, but leaking passwords makes your company look really bad.
  • Richard
    Richard almost 10 years
    This is bad advice. If someone steals your database and gets all your hashed passwords, even if they have also compromised other parts of your database, it can still be important to prevent them cracking the passwords and logging on. (Think of a banking website, for example.) Speed-optimized algorithms enable attackers to test many candidates against the stolen hashes until they find a match. Algorithms like bcrypt and scrypt make slow and expensive to test candidates against the hash, even if they know what algorithm you use. So they give better protection if someone steals the hashes.
  • ceejayoz
    ceejayoz about 9 years
    "If your database becomes compromised then most likely everything has been compromised including your hashing techniques no matter how cryptic you've made it." That's why bcrypt is so important. With bcrypt, it doesn't really matter if someone has the hashes. With a fast hashing algorithm like SHA1/MD5, it does.
  • ceejayoz
    ceejayoz about 9 years
    "What people seem to be missing is that if the hacker has access to the database he probably also has access to the php file that hashes the password..." This isn't true. One of the most common vulnerabilities is SQL injection, which would give read/write ability to the database but zero access to the PHP code.
  • Aage
    Aage about 9 years
    @JohannesGorset The Matasano article link is dead, here's a live one: securityfocus.com/blogs/262
  • Scott Arciszewski
    Scott Arciszewski about 9 years
    Do you mind if I edit your answer to suggest password_hash() and password_verify()?
  • magallanes
    magallanes over 8 years
    If you have access to the code then you can modify and store all the password that the user is sending in a plain text. So no, if the code is compromised then GAME OVER.
  • magallanes
    magallanes over 8 years
    Even if i am using a weaker encryption, practically no system can holds a brute attack for more than 1 million of tries per second.
  • Shylor
    Shylor over 8 years
    The issue with using MD5 with a salt is that computers can create a brute force attack on the one password with super fast speeds. shylor.com/2015/09/14/php-5-5-secure-password-hashing
  • UncaAlby
    UncaAlby almost 8 years
    I think the point some of you are missing is that it doesn't matter if the password is 1000% secure when all the other data is clear-text. E.g., if the entire database is compromised, then the hacker now has all the clear-text credit card numbers. Yes, many people use the same password on different web-sites, but they've already been told ad nauseum not to do that, so it's no longer our problem. If the database itself contains sensitive info, and its compromise is a concern, then encrypt the entire database, as strongly as you think is necessary.
  • UncaAlby
    UncaAlby almost 8 years
    Three failed logins, and you're locked out. Period, end of story. Even super stupid passwords like "1234" are secure, if the hacker happens to first try "password", "pa$$word" and "passw0rd" (lock out!). How the user regains access now becomes your security sticking point, and what you do depends on the size of your user base. 200 users? Have them telephone in for help.
  • Wildcard
    Wildcard over 7 years
    Does this answer fail to make sense to anyone else, or is it just me?
  • Admin
    Admin almost 6 years
    Simple password hashing is fine, it is up to the firewall to keep the server safe .. and by "firewall" i mean a reactive firewall that blocks/slow-down brute-force (a human can only type THAT fast) .. this contest is pointless .. .. "what if some hacker broke in and now has everything" (face-desk) - if a hacker got into your server - it's over. Passwords are cracked mostly because they are too darn simple, or the software devs are too darn lazy to think like a cyber-criminal.
  • LexLythius
    LexLythius almost 6 years
    @argon Please read again. The whole purpose of hashing passwords is so that when your login DB is compromised (and it will at some point) you don't immediately leak all of your users' passwords, which are most often reused by users across different sites—otherwise a simple delay after input would do. And the "game over if they got in your server" is a moot point, because they don't need to get inside your server. The most common vulnerability hackers use has been SQL injection (see the Linkedin case), then they bruteforce the hash. That's why you need salting and stretching.
  • Admin
    Admin almost 6 years
    if the security requirement is really so intense, then storing passwords elsewhere may be a good idea. There are many ways to protect your data (and source-code) -for "if/when" ... .. -but hashing passwords up to a "gazillion bits" is only as secure as: the password creator/guest-system, the data transmission, and the humans servicing the server hardware. .. that being said: I'm NOT saying hashing is useless, however I am saying that if your solution is just more complicated hashes then I'm afraid it's not going to work in the near future, regarding quantum computers.
  • Victor Stoddard
    Victor Stoddard over 5 years
    Recursive hashing adds work/cost to any hacking attempts. The more iterations, the harder to crack, so even fast hashes like SHA256 could be used. Iterations must be random and can be made public. password_hash() shows the cost in the hash itself.
  • LexLythius
    LexLythius over 5 years
    @VictorStoddard Yes, you can roll your own hashing scheme and provide tunable key stretching. But why would you want to do that instead of using already existing, much more thoroughly scrutinized algorithms that experts have created and made available for exactly this purpose?
  • Victor Stoddard
    Victor Stoddard over 5 years
    @LexLythius password_hash() is the industry standard and I'm not suggesting replacing it. I'm stating that fast hashing algorithms, like sha256, could be slowed down by adding a cost -- in this case it's recursive hashing. This was common before password_hash() was developed.
  • dsturbid
    dsturbid almost 5 years
    This answer may have been based on pragatism in 2011, but now, strong password hashing algorithms are so accessible these days in PHP (bcrypt/Argon2) there is no reason not to use them on a greenfield project. We have a responsibility to our users not to play fast and loose with their data
  • Dharman
    Dharman over 4 years
    @scott I think one of the links is missing, what was it meant to be? CSPRNG
  • mehov
    mehov about 4 years
    In case anyone's wondering, here's the dead link from the very first comment archived in it's original state as of 2011: chargen.matasano.com:80/chargen/2007/9/7/enough-with-the-rai‌​nbow-tables-what-you‌​-need-to-know-about-‌​s.html