Password Hashing, BCrypt to SHA1/MD5 - php

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.

Related

Convert sha512 to md5

Use SHA512 as encryption in Multicraft panel (which you can change the settings for MD5), but I need to use an older version of the same database. This old version did not have the option to encrypt with SHA512, but only with MD5. Thus, all passwords are invalid with MD5.
It's possible convert all SHA512 passwords in MySQL database to MD5?
SHA512 and MD5 are hashes, not encryption algorithms. By design, they are not reversible.
The only way to convert these values is to wait for each user to log in, validate their password against the existing SHA512 hash, and rehash¹ their input with MD5. This is the reverse of how password hashes are updated to more secure standards.
But please, please, don't do this. MD5 is hopelessly broken. You would be doing your users a huge disservice to revert from SHA512 to MD5. Find a way to use the newer version of your software.
¹As noted by zaph in a comment, "rehashing" is an oversimplification, and depending on how your panel is actually implemented it might be using insecure password storage today.
To provide reasonable security each password must also have a unique random salt (which protects against things like rainbow tables) and each hash must be iterated enough times to make brute forcing impractical. As computers get more powerful the number of iterations must be increased. Today it is common to iterate tens or hundreds of thousands of times.
Cryptography is shockingly difficult to get right. Instead of trying to follow all the best practices manually, use libraries and functions that operate at the right level of abstraction and have been audited for security. An algorithm like bcrypt (via PHP's built-in password_hash function, where it is currently the default algorithm) would be a good choice.
Short answer: No.
Long answer:
By design, both MD5 and SHA512 are one-way hashes. In order to convert SHA512 to MD5, you would need to know both the original password for every password your are trying to convert, and also the salt that was used to encrypt them. You almost certainly wouldn't know every password for every one of your users.
One-way hashes work by actually casting the same algorithm every time a user logs in. The user types in their password, the algorithm is applied to it, and if it perfectly matches the copy in the database that has already been hashed, then the user is logged in. You can't use any sort of algorithm to work out what the original password was, only to compare if the output of applying a specific password would be to a password that is already encrypted.
MD5 is also a far weaker hashing algorithm than SHA512. Converting to MD5 would make your password far less secure, and this would be something that you probably wouldn't want to do. Instead, you should be looking at a way to incorporate the new database system.

PHP - MD5, SHA, Hashing security

I'm the developer of a new website built in PHP and I'm wondering what exactly is the best
thing to use for hashing. I've looked at md5 and sha1 but is there anything more secure.
I'm sorry if this is a nooby question but I'm new to PHP Security and I'm trying to make my
site as secure as possible. Also what is a salt?
Thanks,
Waseem
First off md5 and sha1 have been proven to be vunrable to collision attacks and can be rainbow
tabled easily (When they see if you hash is the same in their database of common passwords).
There are currently two things that are secure enough for passwords, that you can use.
The first being sha512. sha512 is a sub-version of SHA2. SHA2 has not yet been proven to be
vunrable to collision attacks and sha512 will generate a 512 bit hash. Here is an example of
how to use sha512:
<?php
hash('sha512',$password);
The other option is called bcrypt. bcrypt is famous for its secure hashes. Its
probably the most secure one out there and most customizable one too.
Before you want to start using bcrypt you need to check if your sever has it enabled, Enter
this code:
<?php
if (defined("CRYPT_BLOWFISH") && CRYPT_BLOWFISH) {
echo "CRYPT_BLOWFISH is enabled!";
}else {
echo "CRYPT_BLOWFISH is not available";
}
If it returns that it is enabled then the next step is easy, All you need to do to bcrypt a
password is (Note for more customizability you need to see this How do you use bcrypt for hashing passwords in PHP?):
crypt($password, $salt);
Now to answer your second question. A salt is usally a random string that you add at the end of
all you passwords when you hash them. Using a salt means if some one gets your database
they can not check the hashes for common passwords. Checking the database is called using a rainbow table. You should always use a salt when hashing!!
Here are my proofs for the SHA1 and MD5 collision attack vulnerabilities:
http://www.schneier.com/blog/archives/2012/10/when_will_we_se.html, http://eprint.iacr.org/2010/413.pdf, http://people.csail.mit.edu/yiqun/SHA1AttackProceedingVersion.pdf, http://conf.isi.qut.edu.au/auscert/proceedings/2006/gauravaram06collision.pdf and Understanding sha-1 collision weakness
The whole purpose of the salt is to slow down an attacker from comparing a list of pre-generated hashes against the target hash.
Instead of needing to pre-compute one "hashed" value for each plaintext password, an attacker needs to precompute 16384 "hashed" values for each plaintext password (2^7 * 2^7).
That kinda pales today but was pretty big when the crypt function was first developed - the computational power to pre-compute that many passwords times the number of plaintext password you suspect (dictionary) was pretty high.
Not so much today which is why we have things like shadow passwords, other core password functions besides crypt and every sysad wanting you to pick a password that would not show up in a dictionary.
If the hashes you want to generate are for passwords this is a well accepted method of implementing it.
http://www.openwall.com/phpass/
If you're planning to do this for passwords, then do not use MD5 or SHA1. They are known to be weak and insecure, even with salt.
If you're using them for other purposes (eg providing a hash of a file to confirm its authenticity, or a random hash database column to provide a pseudo-random sort order) then they are fine (up to a point), but not for passwords or anything else that you would consider needing to be kept secure.
The current best-practice algorithm for password hasing is BCrypt, with suitable salting.
And the best way to implement BCrypt password hashing in PHP is to use PHP's new password API. This API will be featured as a set of built-in functions in the next version of PHP, v5.5, due for release in the next few months. The good news is that they have also released a backward-compatibility version for users of current versions of PHP (5.3 and 5.4), so even though PHP 5.5 isn't released yet, you can start using the new API immediately.
You can download the compatibility library from here: https://github.com/ircmaxell/password_compat
Also: You asked what "salt" is. Since I've mentioned it a couple of times in this answer, I should address that part of the question too.
Salt is basically an additional string added to the password when hashing it, in order to make it harder to crack.
For example, an attacker may know in advance what the hashed value is for a given password string, or even a whole lot of given password strings. If he can get hold of your hashed data and you haven't used a salt, then he can just compare your hashes against his list of known passwords, and if any of your users are using an easy to guess password, they'll be cracked in seconds, regardless of what hashing method was used.
However, if you've added a secret extra string to the password when you hash it, then the hashed value won't match the standard hash for the original password, thus making it harder for the attacker to find the value.
The good news is that if you're using the API I mentioned above, then you don't need to worry too much about the details of this, as the API handles the salting for you.
Hope that helps.

Using 512-hash before Bcrypt?

I want to use Bcrypt for the password encryption in my systems. But all the examples are something like this:
$password = $_POST['password'];
$salt = substr(str_replace('+', '.', base64_encode(sha1(microtime(true), true))), 0, 22);
$hash = crypt($password, '$2a$12$'.$salt);
This looks pretty safe to me, but I was wondering, in each example, nobody hashes the password before using Bcrypt.
Due to the unique salt, Rainbow tables shouldn't be able to crack all the passwords at once. But in case the hacker takes one record and creates a rainbow table with the salt of that particular record, he should be able to crack a weak password.
So if someone takes a weak password (let's say 'foo'), it would be safer to hash it first with SHA-512 before using Bcrypt. Am I right? Or is this just looking safer?
Actually the answer has to be no, it doesn't make the hash significant stronger in a cryptographically sense. As you probably know, bcrypt (although the function to use is named crypt) is a hash function itself, not an encryption function.
In bcrypt you pass a cost factor, which defines, how many iterations will be done (normally hundreds of them). That slows down calculation of the hash, what makes brute force attacks impracticable. Using SHA-512 before, will only add one iteration more.
What you said about the salt is correct, but of course if you have to build a rainbow table for each password, you will simply brute force until you have found a match, no need to build the whole rainbow table.
If the attacker has control over database and code, an additional SHA-512 will help nothing at all (only a single iteration more). If he has only the database without code (SQL-Injection), then he will recognize the bcrypt hash. He can now brute force with bcrypt, but because of the SHA-512 there aren't any weak passwords. It's like the SHA-512 hash would be the password to crack, so a dictionary is of no use. This is security by obscurity, but will be effective as long as the code is not known. You can get the same effect easier, by adding a fix hard coded salt (key), before using bcrypt with the unique salt.
crypt() is a one-way string hash, not an encryption mechanism. To use an SHA-512 hash, you have to use the hash() function. Bcrypt requires a PHP extension. For storing passwords, why do you want to make them reversible, rather than just hashing them? That's less secure -- if someone gets your key and DB, they have all the passwords, but a table of SHA512 hashes is pretty useless.
Hashing first won't help. A bad password is one that is deemed more probable by an attacker and placed earlier in his list of passwords to try.
Bcrypt incorporates salt to eliminate pre-computed lookup tables (a Rainbow Table is one example). Why would an attacker build a rainbow table for a single record? No, when attacking a salted password, an attacker simply works through his ordered list of most likely passwords, repeating the hash algorithm to see if it matches.
How far he can work through that list depends on how long the hash algorithm takes to execute. Bcrypt controls that with the "cost" factor—12 in your example (which is okay, but probably the minimum I'd use). An extra SHA-512 round doesn't add anything to that. You are already performing 4096 expensive bcrypt iterations. Adding 1 cheap SHA-512 iteration is negligible.
If you choose the first password on the list, it will be broken in a fraction of a second. If you pick the billionth password, the attacker won't break it for a few decades.
bcrypt already uses salt, and what it's doing internally is quite a bit stronger than SHA512. Adding an iteration of SHA512 (and/or an extra layer of salt) on top of bcrypt will not give you a significantly stronger result. If the two functions interact in the wrong way, combining them in this way may in fact give you a hash function that is weaker.

How long should my password salt be, and is SHA-256 good enough?

I'm in the process of creating a gaming community site that I'm aiming to release to the public soon. Currently, I'm working on passwords and logins. I've only used MD5 before, but I've read about password safety and heard that salting is currently the way to go.
Here's my plan: Every user has their own unique salt of 12 random characters (#/¤& etc), stored in the users table. The salt is hashed (using SHA-256) along with the password on registration, and re-hashed on login.
How does this sound to you? Anything I can improve? Should I go for SHA-512 and a longer salt, or is this enough?
Your suggestion of 12 bytes should be an adequate length for a salt. That would require a dictionary attack to prepare 296 databases of hashed passwords. Someday this might be a trivial operation for a cracker, but we're still a ways off from that.
SHA256 is recommended by NIST as having adequate hashing strength for passwords, at least for now.
If you want to explore even stronger methods of password security, look into key-strengthening techniques like PBKDF2, or adaptive hashing with Bcrypt. But these have no direct support in SQL. You'd have to do the hashing in application code and then post the hash digest to your database.
It may seem like security overkill for a gaming site, but it's a good practice to do it. Because many users (inadvisably) use the same password for their gaming login as they do for their banking login! You don't want to be responsible for an authentication breach that leads indirectly to major losses.
Update:
Don't use hashing or HMAC. Use bcrypt or scrypt. See http://codahale.com/how-to-safely-store-a-password/
Original:
Don't simply hash. Use HMAC. (And avoid doing your own hashing or crypto if there is a library available, since libraries benefit from expert input.)
References:
http://rdist.root.org/2009/10/29/stop-using-unsafe-keyed-hashes-use-hmac/
http://us2.php.net/manual/en/function.hash-hmac.php
It's probably sufficient for your use case.
However, it could be improved by:
Increase the size of the salt
The salt should be not be limited to a small subset of characters
Iterate the hashing, say 1000 times (key strengthening)
Have a look at phpass.
I've noticed a lot of confusion about how to do password hashing properly, especially on stackoverflow. And I've seen some REALLY BAD recommendations. So I've written a page that should clear everything up. There's a bit more to it than using a simple hash.
More info and source code: How to do password hashing properly
Feel free to share this link whenever someone has a question about password hashing. This is my first post on stackoverflow so sorry if I'm not doing it right
If you are really concerned, I would look at using the whirlpool hashing function instead of one of the SHA variants. Whirlpool has proven to be an incredibly strong hashing method, and has no history of collisions or any other weaknesses (that I know of, at least).
You can use whirlpool by employing the hash function of PHP. (Note, however, that hash() requires PHP 5.1.2 or greater.)
Your current approach is enough.

Encrypting Passwords

What is the fastest, yet secure way to encrypt passwords (in PHP preferably), and for whichever method you choose, is it portable?
In other words, if I later migrate my website to a different server, will my passwords continue to work?
The method I am using now, as I was told, is dependent on the exact versions of the libraries installed on the server.
If you are choosing an encryption method for your login system then speed is not your friend, Jeff had a to-and-frow with Thomas Ptacek about passwords and the conclusion was that you should use the slowest, most secure encryption method you can afford to.
From Thomas Ptacek's blog:
Speed is exactly what you don’t want in a password hash function.
Modern password schemes are attacked with incremental password crackers.
Incremental crackers don’t precalculate all possible cracked passwords. They consider each password hash individually, and they feed their dictionary through the password hash function the same way your PHP login page would. Rainbow table crackers like Ophcrack use space to attack passwords; incremental crackers like John the Ripper, Crack, and LC5 work with time: statistics and compute.
The password attack game is scored in time taken to crack password X. With rainbow tables, that time depends on how big your table needs to be and how fast you can search it. With incremental crackers, the time depends on how fast you can make the password hash function run.
The better you can optimize your password hash function, the faster your password hash function gets, the weaker your scheme is. MD5 and SHA1, even conventional block ciphers like DES, are designed to be fast. MD5, SHA1, and DES are weak password hashes. On modern CPUs, raw crypto building blocks like DES and MD5 can be bitsliced, vectorized, and parallelized to make password searches lightning fast. Game-over FPGA implementations cost only hundreds of dollars.
I'm with Peter. Developer don't seem to understand passwords. We all pick (and I'm guilty of this too) MD5 or SHA1 because they are fast. Thinking about it ('cuz someone recently pointed it out to me) that doesn't make any sense. We should be picking a hashing algorithm that's stupid slow. I mean, on the scale of things, a busy site will hash passwords what? every 1/2 minute? Who cares if it take 0.8 seconds vs 0.03 seconds server wise? But that extra slowness is huge to prevent all types of common brute-forcish attacks.
From my reading, bcrypt is specifically designed for secure password hashing. It's based on blowfish, and there are many implementation.
For PHP, check out PHP Pass
For anyone doing .NET, check out BCrypt.NET
It should be pointed out that you don't want to encrypt the password, you want to hash it.
Encrypted passwords can be decrypted, letting someone see the password. Hashing is a one-way operation so the user's original password is (cryptographically) gone.
As for which algorithm you should choose - use the currently accepted standard one:
SHA-256
And when you hash the user's password, be sure to also hash in some other junk with it. e.g.:
password: password1
salt: PasswordSaltDesignedForThisQuestion
Append the salt to the user's password:
String s = HashStringSHA256("password1PasswordSaltDesignedForThisQuestion");
Whatever you do, don't write your own encryption algorithm. Doing this will almost guarantee (unless you're a cryptographer) that there will be a flaw in the algorithm that will make it trivial to crack.
I'm not necessarily looking for the fastest but a nice balance, some of the server that this code is being developed for are fairly slow, the script that hashes and stores the password is taking 5-6 seconds to run, and I've narrowed it down to the hashing (if I comment the hashing out it runs, in 1-2 seconds).
It doesn't have to be the MOST secure, I'm not codding for a bank (right now) but I certainly WILL NOT store the passwords as plain-text.
Consider to use bcrypt it is used in many modern frameworks like laravel.
Use this function when inserting in database
Password_harsh($password,PASSWORD_DEFAULT);
And when selecting from the database you compare the password you are inserting with the one in the database using the function
if(password_verify($password,$databasePassword)){
}else{
echo "password not correct";
}
This will harsh the password in a secure format
password_hash ( string $password , int $algo [, array $options ] ). (PHP 5 >= 5.5.0, PHP 7)
password_hash() creates a new password hash using a strong one-way hashing algorithm. password_hash() is compatible with crypt(). Therefore, password hashes created by crypt() can be used with password_hash().

Categories