Using Multiple Hashes in PHP - php

Am working on a project & am keen to keep password-storage secure from the start. In the idea phase, but this is roughly what I intend to use.
class Crypto {
public function hash1($string, $salt) {
return hash('sha512', $string . $salt);
}
public function hash2($string, $salt) {
return hash('sha512', $salt . $string);
}
public function compareToHash($string, $salt, $hash1, $hash2) {
return($this->hash1($string, $salt) === $hash1 && $this->hash2($string, $salt) === $hash2);
}
}
As you can see I am trying to avoid collisions. Is this an effective way, it seems awfully simple and I wonder if I am missing something.
Thanks.

Since you plan on password protecting possibly a website, let me explain that you will need to make sure to send a password from the client already encoded or else any sniffer will find the real password, and you know how people usually use password, right? The same on many, many accounts.
I would suggest taking a look at a post I stubled upon some time ago, and preserved a link for it, for it explains all the problems with hashing and password protection: http://www.codinghorror.com/blog/2007/09/rainbow-hash-cracking.html
Shortly - use the strongest (and sha1 is not strong any more) password encoder as it is possible. Not the fastest one. Let the hacker loose valuable time trying to break in. So much, that breaking in will become unattractive.
Hope it will help, and good luck.

That is pretty basic. I'd check out the Password Storage Cheat Sheet from OWASP. There are also lots of password hashing libraries already created and vetted.
I'd take a look at the Portable PHP Hashing Framework by OpenWall. It creates very secure hashes and performs an appropriate number of iterations as well. It's pretty widely used too.
If you are hashing with SHA512, there isn't anything special you need to do at the time for collision avoidance, I remember reading recently that finding collisions is still not feasible for some time still.
The two primary things I would focus on are secure salts (20+ bytes) and to iterate the hash at least 64,000 times to increase the attack time.

The first rule of password security: If you're not sure if something is secure, then the odds are it isn't.
Since you're just starting out writing your password routines, my advice is to stop now.
PHP5.5 (due out Feb/Mar 2013) will come with a set of new functions designed specifically for dealing with passwords with the best practice security in mind. When 5.5 is released, these functions will become the only recommended method of handling passwords in PHP.
The good news is that you don't have to wait or upgrade to 5.5 in order to use these functions -- they've been back-ported to run in 5.3 and 5.4, so you can use them now. Download the library from here: https://github.com/ircmaxell/password_compat
Reference article: http://www.h-online.com/open/news/item/PHP-5-5-should-reduce-password-sloppiness-1707835.html

If you want to make your password storage secure from the start, you should not use sha512 or any other fast hash algorithm, instead use a key derivation function like BCrypt.
The problem with fast algorithms is, that you can calculate 80 Mega sha512-hashes per second with common hardware (in 2012). That makes it possible to brute-force a whole english dictionary with about 500000 words, in a few milliseconds! Other algorithms are even faster.
BCrypt was especially designed to hash passwords, and is therefore slow (needs some computing time). With a cost factor you can adapt the needed time to future (and therefore faster) hardware.
Using BCrypt can be as easy, as using the sha512 hash. It's recommended to use a well established library like phpass, and if you want to understand how it can be implemented, you can read this article, where i tried to explain the most important points.
Your scheme with two separate hashes will not increase security, because collisions with sha512 are never the problem. In the worst case it even weakens security, because you have to store both hashes, so an attacker has two related informations about the hashed password.

Related

Password hashing methods

Im creating a PHP based CMS (using MVC architecture). I'd like to hash the user passwords stored in the DB. I have read many artices and tutorials about this topic, but I've faced opposing opinons/points of view and suggestions. Im a bit confused. Im looking for the best way to implement password hashing. These are the concepts/methods I've met:
First of all many people mix up the 1-way hashing and the 2-way encryption. If i'm not mistaken the 2-way encryption is the thing about the assymetric encryption with public-private keypairs, And it is for securing the data and make it only readably by the ones who know the other key (the secret key). So this is what we don't care about now.
PHP provides many functions to making hashes, some of them directly uses a hashing alogrithm on the given data (md5(), sha1(), sha256(), ripemd160() etc.) some of them accepts the given data and a supported algorithm and generates the hash (hash(), hash_init(), hash_hmac() etc.)
What is the difference between the loads of hashing/crypting methods? (hash_pbkdf2(), crypt(), bcrpyt, password_hash() and the others mentioed above)
as I learned it is a good practice to use salts in your hash, but it is a bad idea to hash multiple times (even so many tells it is good). Some functions use salt others use key...
Question 1:
Could someone clarify what is the difference between eg.: md5('myPassword'); and hash('md5', 'myPassword'); (I know md5 is an easy to hack method and is not recommended to use to store passwords)
Question2:
And what is the difference between the key and the salt? So what is the difference between hash_hmac('sha1', 'myPassword', 'HaCK_MeIF_youCAN'); and sha1('myPassword'.'HaCK_MeIF_youCAN');?
(notice that hash_hamc calls its 3rd argument 'key')
Question3:
Is multiple hashing really a bad practice?
Like:
hash = sha512(password)
for i in range(10000):
hash = sha512(hash) + salt
return hash
Question4:
What should be the best method to hash my passwords?
Since this is an important and sensitive issue and I think others not familiar with the topic like me would like to make this hash thing clear and would like to get accurate and reliable answers once and for all, I ask you to answer just in case you are an IT security expert or you have any certification or degree in this topic! (For self-proclaimed security experts who acquired their knowledge on the internet: The fact you have done hundreds of systems/websites with hashed passwords doesn't mean that they are secure!)
And one last request: simple (beginner) webprogrammers aren't aliens nor theoretical mathematicians. So please try to explain in some human-like english :)
There are a lot of questions about password hashing on Stack Exchange already, so this is basically a duplicate question, but as you don't know what to trust I'll give you some pointers.
Re: Question 1: Probably they are just different interfaces for the same code. (I haven't checked though. If you want to be sure put the same input in both and compare the output. Or just look up the documentation or in the source code.)
Re: Question 2: A key is a private piece information that you normally should never publish (except for public keys in asymmetric cryptography). Usually there are no keys in password hashing. A salt is a piece of public information that is random and is meant differentiate your password hashing from every other precomputed hash table in the world. It is the main defense against rainbow tables.
HMAC (basically m,k⟼Hash(k||Hash(k||m)) for the concatenation operation ||) was designed to be a so called message authentication code. It is (ab)used for many other purposes though, because of its versatile design if instantiated with a good cryptographic hash function. In this case using the salt as key and the password as message in HMAC is really not that different from Hash(password||salt).
Re: Question 3: No, it is a good practice. The main attack scenario of password storage is that your database is compromised (and often all password data is published if your are significant enough that people will care). Most non technical folk (and apparently even some with IT background) often reuse their passwords (which is a bad practice even if everyone would get their password hashing strait). Thus with your database breach a lot of accounts of a lot people suddenly have known login information if you save the passwords as plaintext. To prevent this you want to use a oneway function on the passwords. Unfortunately passwords have very few entropy most of the time (because nobody likes to remember cryptographically secure passwords) and thus if you use a fast hashing function you can try out every likely password and compare the hash against the one in the database. As extreme example, lets assume I only use the password cat or dog and you have the sha1 hash of my password: 8f6abfbac8c81b55f9005f7ec09e32d29e40eb40 generated by echo $password | sha1sum. Exercise for the reader: which password have used?
To alleviate this problem you want to use a slow hashing function so that trying out every likely password takes a lot of time. One way to slow down the hashing is to iterate the hashing a few thousand (or even few hundred thousand) times. There are other slow hashing concepts like bcrypt, though, that do not just iterate hashing.
Re: Question 4: An in depth discussion can be found on security.stackexchange.com: https://security.stackexchange.com/questions/211/how-to-securely-hash-passwords . The tl,dr version is CodeInChaos's comment: Just use password_hash, it is mostly fool proof. A resource for the advance topic of pepper in addition to salt can be found here: https://security.stackexchange.com/a/3289/10727 .
I will try to answer some of your questions, but first a word about encryption. The problem of encryption is that it is two-way, the password can be retrieved if you know the key. Storing only a hash (one-way) will protect passwords better, because the passwords cannot be retrieved even if all code (including a key) is known.
Question 1 & 2:
It is important that you avoid all fast hashing algorithms, this includes MD5, SHA*. Because they are so fast, they can be brute-forced too easily. It is e.g. possible to calculate about 8 Giga MD5 hashes per second with common hardware.
Question 2:
A salt should be randomly generated for each password, but is not secret and can be stored plaintext with the password in the database. A key (sometimes called pepper) should be kept secret and is not stored in the database.
Question 3:
Multiple hashing is a good thing, but only if done correctly. Appropriate algorithms like BCrypt and PBKDF2 do it in a safe way, and they have a cost factor that determines the number of iterations. This cost factor can be adapted for future and faster hardware.
Question 4:
At the moment the best you can do is to use the PHP function password_hash() to create a BCrypt hash. There also exists a compatibility pack for earlier versions. I wrote a tutorial about safely storing passwords, where i tried to answer this questions a bit more indepth and in a hopefully understandable form, so you mave have a look at it.

Password Hashing, BCrypt to SHA1/MD5

I have been looking at upgrading the password hashing security of one of my applications as I have been reading up about brute force attacks being considerably faster then they used to. Currently I am using sha1(md5($password)) and I see the benefits of using bcrypt + salt. My question is, Would it be any more secure if I were to do the following:
Scenario 1:
$password -> sha1 -> bcrypt -> sha1
// This would enable me to keep all existing passwords and just
// regenerate all the hashes without waiting for the user to re login
Scenario 2:
$password -> bcrypt -> sha1
// I would have to add an extra column for the new hash until every
// user has logged in but the hash will still be sha1.
Would any of these two increase the security of the hash at all? I am no cryptographic master, far from it, I would just like a simple explanation as to if it would work, if not, and why.
Thanks
EDIT
After a little more reading, it seems that bcrypt is favoured because of its slowness in that i makes the cpu/gpu work longer before the hash is generated.
In the case of sha1 vs bcrypt, sha1 is roughly 300000 times faster then bcrypt. Which begs the question, if bcrypts advantage is slowness, surely a recursive hashing function which uses sha1 300000 times would be as secure as bcrypt?
I made this function as an example:
function bsha1($data, $salt) {
$hash = $data;
for ($i = 0; $i < 300000; ++$i) {
$hash = sha1($hash . $salt);
}
Provide it with a salt and itll return a sha1 hash where every iteration is a hashed hash and salt. This takes approximately the same ammount of time as bcrypt. Would this be as secure?
You best upgrade to password_hash().
As it is likely you are not using PHP 5.5 yet (I assume maybe you are already for testing purposes at this time), you can use the PHP userland implementation of password_hash() also written by Ircmaxell for PHP 5.3+.
To upgrade the password hashes on login, you fetch the hash from the database and test first against the new hashing. If it returns FALSE, you test against the old hashing. If that returns TRUE, you re-hash the password with the new new hashing and store it back into the database.
Combining or chaining multiple hashes after each other - and I fear I read that in your question - is a total stupidity you should never consider. Hash algorithms are not compatible to each other and using a hash on a hash that way is doing it wrong: sha1(md5($password)) and the like effectively reduce the output space which makes it easier to attack - something you want prevent in the future.
So take the new password hashing API that there is in PHP and sleep well.
neither scenario gives you much of a security margin over just bcrypt. That said, bcrypt is absolutely the way to go as far as a hashing algorithm that will resist brute forcing, as with a sufficiently high cost factor, it will take a much longer time to hash than any SHA-based hashing scheme.
Saying all that, Scenario 1 may be the way to go, as you are able to secure your db now instead of piecemeal as users log in. Despite what M8R-1jmw5r says in his/her answer, combining hashing algorithms doesn't give you any extra security, but it also won't really impact your security negatively.
You can use any standard hashing algorithm, but being standard hashing function they can be backtracked and there is a potential security risk.
You better go with any hash functions but combine it with salt with your personal keys. here is link
http://www.php.net/manual/en/faq.passwords.php#faq.passwords.fasthash
Short answer is yes it would help. However the long answer is no because SHA-1 and MD5 are just weak hashing algorithms now. It would be better for you to just go with SHA-2 algorithms or even wait a little longer and go directly to SHA-3.
The problem is in the hashing function. Three layers will definitely stop someone, but honestly most of the time one layer is enough to get most people to not even bother. If someone is very intent on getting in I would use SHA-2 at the very least other wise you should be fine with what you have.
EDIT::
Ok so to clarify the above. Using SHA1 with Bcrypt is not necesarilly the best way to go. I would use SHA-2 algorithms with bcrypt instead, this would give you more security than using the SHA-1. Also by layers I mean the Bcrypt is one Hash pass the SHA-1 is one Hash pass the second SHA-1 is another Hash pass. I really don't understand why this is wrong? Sorry for the difference in semantics about the layers.
EDIT2::
$Password -> Bcrypt -> SHA-2 or Bcrypt(SHA-2($Password)) Where SHA-2 is one of the SHA-2 family of hashing algorithms.
Code to be more clear than Bcrypt with SHA-2 instead of SHA-1.

Bcrypt(4) (=4 iterations) versus SHA512 or something different with unique salt per password?

Background:
I want to add a login to my small site, which is an online php application, which I'd like to build to be able to bear much user activity in the future.
Before I look further into implementing LightOpenID I want to add a normal login. The book I was learning from is called Head First PHP & MySQL (2008) and the final code of the chapter uses SHA('$user_password') as part of the mysql query.
As I take interest in Jeff Atwood's writing I'm well aware of bcrypt as of scrypt. But seen as there's no php implementation of scrypt and having no dedicated server to run it, I decided to at least look into implementing bcrypt for now.
However I'm not completely naive, I know I should watch out not to overextend my very humble hosting resources. The php app itself should always come first before anything else concerning resources.
Andrew Moore's method seems nice (though I'll have to see how to implement it on php 5.2.17 which my host uses) and it comes with a tip for hardware speed:
You should select a number of rounds that results in 200-250 ms of
work. Part of the reason why bcrypt is secure is that it is slow. You
must ensure to have a number of rounds that keeps that characteristic.
– Andrew Moore
Another user states that for him running microtime() gives 0.314 for Bcrypt(9), which thus would be near optimal.
The question:
Seen as I only have very humble resources at my disposal and I'd like to make the best of them, leaving most for the php app itself, am I still better off using Bcrypt(4) instead of something else?
Bcrypt(4) returns true almost instantly, but does it still keep that characteristic Moore talks about?(Would that be the part concerning RAM that makes it harder for GPU bruteforcing?) Or would SHA512 or something else actually be as fast but more secure at this point?
I'd expect Bcrypt(4) to win in this situation, but the hell do I know right? :p
Security is always about what you are trying to secure.
If you are more concerned about your resources than about your security, bcrypt(2) is already overkill. No hacker will ever try to break that for a normal application, having easier target sites like LinkedIn and many others, which just use functions from the sha family, with a single iteration, and unsalted. They will go for the 'low hanging fruit'. Or they could keep trying to hack your application, just not in the password encryption part.
SHA-512 is not much more secure than SHA-1 as password hashing algorithm [1], it has not been designed for that purpose. They can still be used as primitives for creating secure cryptographic algorithms though, but that's something no single person should do. To be considered secure, crypto algorithms must be public to be peer reviewed, and must pass the test of time. And obviously, must be designed for what you are going to use them. MD5, SHA-X, etc. are cryptographic algorithms, but weren't designed for storing passwords.
Just add or remove rounds to your bcrypt. In this case I would use 1 or 2. Also keep in mind that 1 round != 1 iteration. They are increased exponentially. If you read about how bcrypt works, you will see that there is much more to it than just iterations. For example, you mentioned 'unique salt per password'. Bcrypt already has that.
[1] For other things it's obviously more secure
You should look at security of the system, not just of bcrypt.
Certainly, if you want to store passwords, bcrypt or PBKDF2 is the way to proceed. Make sure you use a sufficiently large, random salt per user or password. Then try to maximize the number of iterations. If that's small, then it is small, but any iteration more is better than nothing.
Note that this does little against eavesdropping or man in the middle attempts (MitM). You should use SSL for that; the password or the hash (if you do the hashing client side) can be replayed otherwise.
Furthermore, if you want to protect against brute force attacks (attackers trying the most common passwords) you should create (or copy) a good password management scheme. Limit the amount of incorrect logins and try to let the users create strong passwords. Also limit the amount of information you return to your user regarding incorrect logins, that user may be the attacker.
Or would SHA512 or something else actually be as fast but more secure at this point?
Slowness is a major feature of password hashing algorithms (of which, bcrypt is one, but SHA-512 by itself is not) - the slower your algorithm is (relative to other algorithms), the harder it is for an attacker to brute force passwords based on the hashes. From this perspective, a single round of SHA-512 is less suitable than bcrypt for the purpose of securely storing passwords, because it is considerably faster.
In my opinion, the best approach to take is to pick a password hashing algorithm (bcrypt, PBKDF2, scrypt) and then tune the work factor to give you the best tradeoff between speed and security, given the computing resources available to you and the characteristics of your system. A higher work factor = more secure, but also more resource-intensive.
The good news is that users typically use your login function infrequently compared to other functions, so the impact of a slower/resource intensive login function is generally not a big problem.

Is it useful to loop an hmac hash?

I need to store a password in a database, and I used to store an sha1 hash of a salted password alongside a random salt, which was looped, like so:
$salt = sha1(microtime().mt_rand());
for ($i=0; $i < 4000; $i++) {
$password = sha1($password.$salt);
}
(In my example, $password and $salt were stored inside the db).
I recently discovered the hash_hmac() function, which apparently is a much more secure function than a simple SHA1 hash. I plan on using it with the same pattern (the salt being the secret key), but I was wondering if it was worthwile to loop it like in my previous example. If anyone could give me some insight, that'd be much appreciated.
Yes.
What you're doing here is known as key stretching and it multiplies the time an attacker has to take to check each candidate password against a hash. In your example, it increases the time by 4000x. The specific threat you are protecting against here is when an attacker gets hold of your hashes (such as what happened with LinkedIn, Last.fm and eHarmony recently) and can devote as much CPU power as he can afford to cracking them.
Rather than rolling your own, if this is anything other than a research project, you should use a well-known and publicly tested function like bcrypt(), PBKDF2() or scrypt().
The number in that loop should be much higher than 4000 and since your attacker will be using a C loop rather than a PHP loop, you won't be able to do as many in a reasonable time as he will. Even in a PHP loop, I can do 500,000 in 0.3 seconds. The above hashing algorithms solve this problem since they will be implemented in C. (Not all of them may be available in PHP.) It seems bcrypt is in 5.3 but it's called CRYPT_BLOWFISH. Details on how to use it are on the crypt() page.
hash_hmac() is not a more secure hashing algorithm but rather is used for a different purpose. See the end of Thomas' answer here. Algorithms like MD5 and the SHA family are general purpose hashing algorithms that are normally used as part of a more specific algorithm for a particular purpose. For instance, some of the above password hashing algorithms use general purpose hashing algorithms many times. has_hmac() asks you which general purpose hashing algorithm you would like to use.

What function to use to hash passwords in MySQL?

I have a user table in my mysql database that has a password column. Currently, I use the MD5 algorithm to hash the users' password for storage in the database. Now I like to think that I am a security conscience person. I noticed while reading the MySQL docs that they don't recommend MD5 or the SHA/SHA1 hashing methods, but don't offer an alternative.
What would be the best way to hash my passwords in MySQL? A function that is natively supported in both PHP and MySQL would be ideal and necessary with my current implementation.
Thanks!
It's not necessarily that you shouldn't use MD5, as much it's that you shouldn't use just MD5, as this leaves you vulnerable to rainbow-table attacks (a rainbow table is a table of precomputed hash values - if your password is even remotely common or simple, the attacker needs merely to look up the hash and he knows your plaintext password.)
At the very least you should add a salt to every password so that any existing rainbow table is useless, forcing the attacker to generate an entire new rainbow table just for your database of passwords.
Better still is to use a different salt for every password in your database, say the username it's associated with, so that an attacker can't even generate a rainbow table for your whole database and has to crack each entry separately.
MD5 is also a very fast algorithm. Speed is the enemy when it comes to cracking - the longer it takes to generate a hash, the longer it takes for each attempt a hacker makes. Something simple like hashing the plaintext 100 times with a new additional salt each time would be barely perceptible (if at all) to a user logging in to your site, but it would increase the time it takes to brute-force a password by the same 100 times.
Far, far more detail here: http://www.codinghorror.com/blog/archives/000953.html
MD5 is considered to be weak by today's standards. It would still take some work to crack a hash made with MD5, but it's several times easier than guessing the password by brute-force. Ideally, cracking a hash should not be easier than brute-force.
SHA1 is also considered easier to crack than guessing the password by brute-force.
I actually contributed a patch to MySQL to surface the SHA224, SHA256, SHA384, and SHA512 functions from OpenSSL. These are recommended by NIST for password hashing (actually SHA256 and higher).
My patch was finished by MySQL engineers, and is included in MySQL 6.0.5 and later, if I recall.
If you use an earlier version of MySQL (and who doesn't), then you can probably use an implementation of strong hashing functions in your host language. PHP has the hash() function for example. You can do the hashing in your application and save the resulting message string to the database.
Don't forget to do salting, too!
This question is 7 years old. In that time we have progressed in computing to where MD5 and SHA1 are now easily broken by modern computers. These should be avoided now.
With PHP 5.5 came the introduction of password_hash, which uses the far more secure bcrypt algorithm. While MySQL can encrypt/decrypt bcrypt, it's a terrible solution because you're not only adding a potentially large computation load to your database layer, but the unhashed password could be stored in your logs
Under no circumstances should a plain text password hit MySQL, even if at the query level. Otherwise you risk writing the passwords to log (query log, general log, slow query log, etc). Which is horrific. So no, don't even bother...
MD5 and SHA-1 probably aren't recommended anymore due to know attacks. But, they're still generally sufficient for most use cases.
If you're looking for more options, just use PHP's hash functions -- you've got plenty of options there.
I am using a combination. For example SHA1(MD5()) is working fine.

Categories