I was wondering if someone could me some advice please? I was wondering how secure/insecure or otherwise rubbish the following code is for encrypting passwords using Codeigniter?
$safe_password = sha1($password, $config['encryption_key'])
If not secure can people give me some tips to make it more secure using Codeigniter please?
Many thanks :)
sha1 has been know to be vulnerable to collision attacks, try using bcrypt as it's one of the best. If bcrypt doesn't work for you use sha512 and add a salt too.
bcrypt may seem daunting to use but here's an article on why you should use it: http://phpmaster.com/why-you-should-use-bcrypt-to-hash-stored-passwords/
The reason why sha1 is unsecure is because of collision attacks, here is one of the papers where it exposes sha1's security risks: http://www.schneier.com/blog/archives/2005/02/cryptanalysis_o.html
If you would like to use sha512 all you need to do is:
hash('sha512', $password.$salt);
And make sure you always use a salt or else some one can use a rainbow table (database) to see if your hash matches a common password inside the database.
Hashing algorithms such as sha1 and md5 are not suitable for password storing. They are designed to be very efficient. This means that brute forcing is very fast. Even if a hacker obtains a copy of your hashed passwords, it is pretty fast to brute force it. If you use a salt, it makes rainbow tables less effective, but does nothing against brute force. Using a slower algorithm makes brute force ineffective. For instance, the bcrypt algorithm can be made as slow as you wish, and it uses salts internally to protect against rainbow tables. I would go with such an approach or similar if I were you.
From PHP DOC
string sha1 ( string $str [, bool $raw_output = false ] )
If the optional raw_output is set to TRUE, then the sha1 digest is instead returned in raw binary format with a length of 20, otherwise the returned value is a 40-character hexadecimal number.
My Advice use BCRYPT its more secure for easy implementation you can try password_compat
Example
$hash = password_hash($password, PASSWORD_BCRYPT);
No, sha1() is not considered secure as can be read, for example, here:
http://www.php.net/manual/en/faq.passwords.php#faq.passwords.fasthash
Currently, a good choice might be SHA512 using a salt: hash('sha512', 'text+salt')
Better solution is with bcrypt, have a look at this tutorial.
Here is a small library that you can use with Codeigniter https://github.com/waldirbertazzijr/codeigniter-bcrypt
Another related question.
Related
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.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to best store user information and user login and password
How do you use bcrypt for hashing passwords in PHP?
I am used to using the md5() which I know is now outdated and I hear that sha1() is also insecure. So what is exactly the best way to store and retrieve passwords in a database these days with security in mind? I'd be very happy if you can provide a small example.
Thank you!
I would recommend looking at bcrypt, since it can help against brute-force attacks. http://codahale.com/how-to-safely-store-a-password/
You can find example Here
You should really use bcrypt to hash your passwords, it was designed especially for hashing password.
Hash functions for passwords should be slow (need some computing time). Most hash algorithms like SHA-1 and MD5 or even SHA-256 are designed to be fast, but this makes it an easy target for brute force attacks. An off-the-shelf GPU is able to calculate about 8 Giga MD5 hashes per second!
Don't be afraid to use bcrypt! It is not for high security sites only, and using it can be as easy, as using an md5 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.
UPDATE:
Current PHP versions offers the functions password_hash() and password_verify() to handle passwords. Use them like this:
// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_DEFAULT);
// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);
We use crypt with Blowfish:
// Hash our password
$hashed = crypt($plain_text_password, '$2a$08$' . substr(hash('whirlpool', microtime()), rand(0, 105), 22));
// Validate a password
if (crypt($plain_text_password, $hashed) == $hashed)) {
// Valid password
}
The salt prefix $2a$ (read the docs) is what instructs crypt to use Blowfish. And assuming the implementation of crypt(3) in the underlying OS supports it, you get it "for free."
md5\sha1 + unique salt = best way
Don't be paranoid.
You could look up alot of encryption codes or mix them for example like this:
sha1(md5(sha1($pw)));
I find that unnecessary so what I use is SHA512 hash("sha512",$pw);
So currently my code is using a standard sha1 to hash the password for database implementation.
What is or is there a better more securing way to store the password? Maybe MD5 (Yes I am joking)
For example I am using Codeigniter as my framework, What would be the best way to encrypt the passwords?
I would do it this way.
salt = For each user generate a random seed with a random length.
iterations = Select a random number
while(iterations != 0) {
hashed_password = hash_function(password.salt) . salt; iterations-- }
in the password field save them like so:
hashed_password:salt:hash_function:iterations.
And at login use the new password in combination with salt, hash_function and iteration to hash it and compare the result with the hashed_password.
off course you can use multiple hash functions to like sha_x(md5(salt.password).salt).salt or what ever you want but make sure that you save it in some way in order to make the comparison at login.
You should really use bcrypt to hash your passwords, it was designed especially for hashing password.
Hash functions for passwords should be slow (need some computing time). Most hash algorithms like SHA-1 and MD5 or even SHA-256 are designed to be fast, but this makes it an easy target for brute force attacks.
Don't be afraid to use bcrypt! It is not for high security sites only, and using it can be as easy, as using an md5 hash. It's recommended to use a well established library like phpass, and if you want to understand how it works, you can read this article, where i tried to explain the most important points.
This lib is very good: http://www.openwall.com/phpass/
It uses the crypt method with various algorithms and also has it's own based on md5 but with so many iterations and salt that it's "safe".
SHA1 was brocken in 2005
February 15, 2005
SHA-1 Broken
SHA-1 has been broken. Not a reduced-round version. Not a simplified
version. The real thing.
The research team of Xiaoyun Wang, Yiqun Lisa Yin, and Hongbo Yu
(mostly from Shandong University in China) have been quietly
circulating a paper describing their results: collisions in the the
full SHA-1 in 2*69 hash operations, much less than the brute-force
attack of 2*80 operations based on the hash length.
collisions in SHA-0 in 2**39 operations.
collisions in 58-round SHA-1 in 2**33 operations.
Take a look at this comparisoion list.
I am looking to create a commercial website using php and I wanted to make sure the code I have for user hashed password was strong enough to avoid brute force attacks.
Note that my server and it's php version does not support blowfish so I am trying to figure out a decent method of hashing a password.
$pw = "12341234";
$salt = 'randomchars';
$initial = sha1($pw);
$hashed = md5($salt . $initial);
Is there something else I should be considering? any thoughts would be appreciated!
You want http://www.openwall.com/phpass/
I think you are not aware of the fact, that the way you hash passwords does not influence the possibility of cracking the password by brute force attack (eg. when attacker tries to provide thousands of possible passwords). It only makes password safe in case someone sees the value in the database that is used to represent this password.
For Brute Attack you can use google's captcha..
And for code password you can use first md5 and second sha1 because md5 generating 32 characters data sha1 64.. :)
Your snippet seems secure. You want to protect against rainbow table attacks, so the double-encryption is a good idea. The computing power to even generate a list of MD5 hashes of SHA1 plaintext is huge, but it's still no harm to have the salt there to protect against such an attack.
There is no need to reinvent a wheel as there is a crypt function.
// generate MD5-hashed password with salt
$password = crypt('mypassword');
// password contains string(34) "$1$bkZO1nIl$y5bzPPwByq.9tYEb64k4e0"
See examples for different types of hashes including MD5 and SHA256 in the manual: http://php.net/manual/en/function.crypt.php
I this is not enough, there are alternatives:
How do you use bcrypt for hashing passwords in PHP?
Keep in mind that if someone was able to lay his hand on your database, his ability to crack users' passwords will be least of your problems.
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?
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.
Add a salt to each password stored that's not equal for every password
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.
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.
There are a couple of things you should do.
Use SHA instead of MD5. SHA is more cryptographically secure than MD5. The more bits the better!
Use a salt. This makes rainbow table attacks more difficult.
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!
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.
Switch to a different hash mechanism (you can do it incrementally as people log in) and definitely use a (different for each user) salt!
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
}
?>
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 .