Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I'm trying to find the best way to secure user passwords in a mysql database (hashing/encryption wise). I was which method was the most secure and hardest to crack. I am not very experience in the realm of encryption/hashing etc. Currently I am using a very unsecure method of doing this sort of encryption:
$encrypted_password = strrev(base64_encode($password));
I know that isn't the best way to do it, but like I said, I'm new. Could anyone point my in the right direction?
Thanks.
Use bcrypt:
Bcrypt is an adaptive password hashing algorithm which uses the Blowfish keying schedule, not a symmetric encryption algorithm.
Read the accepted answer here:
openssl_digest vs hash vs hash_hmac? Difference between SALT & HMAC?
How To Safely Store A Password
Edit: You should take a look at hash_hmac(). I think it's a better approach than just salting.
You can use sha1 and a salt:
$salt = "some random string";
$encrypted_password = sha1($salt.$password);
You add the salt to make it harder to use rainbow tables in case somebody manages to get the encrypted password list.
You could use any one-way hashing method (I just like sha1), but it's always better to salt it before hashing.
use hash_hmac to store encrypted passwords
If you need clear text password, use des/aes/3des
Here is an article from Php.net that talks about "Safe Password Hashing".
From the article:
When hashing passwords, the two most important considerations are the computational expense, and the salt. The more computationally expensive the hashing algorithm, the longer it will take to brute force its output.
There are two functions that are bundled with PHP that can perform hashing using a specified algorithm.
The first hashing function is crypt(), which natively supports several hashing algorithms. When using this function, you are guaranteed that the algorithm you select is available, as PHP contains native implementations of each supported algorithm, in case one or more are not supported by your system.
The second hashing function is hash(), which supports many more algorithms and variants than crypt(), but does not support some algorithms that crypt() does. The Hash extension is bundled with PHP, but can be disabled during compile-time, so it is not guaranteed to be available, while crypt() is, being in the PHP core.
The suggested algorithm to use when hashing passwords is Blowfish, as it is significantly more computationally expensive than MD5 or SHA1, while still being scalable.
You should look at php's hash() function: http://se2.php.net/manual/en/function.hash.php
With this you can use lots of different hash algorithms, I usually go with sha256, and add a salt to it before hashing it.
Passwords should be hashed, not encrypted. That is, you should not be able to decrpyt the password. Instead, you should compare hashes.
User sets password $password = 'hX4)1z'
You get hash of password and store to DB:
$pw = hash_hmac('sha512', 'salt' . $password, $_SERVER['site_key']);
mysql_query('INSERT INTO passwords (pw) VALUES ('$pw');
Customer comes back later. They put in their password, and you compare it:
mysql_query('SELECT pw FROM passwords WHERE user_id = ?'); //$pw = fetch
if ($pw == hash_hmac('sha512', 'salt' . $_REQUEST['password'], $_SERVER['site_key']) {
echo "Logged in";
}
I suggest using SHA2 with a salt to store your password.
To create a SHA2 hash, use this:
$hash = hash("sha512", $password.$salt);
A salt contains some extra characters to add to your password before hashing to prevent rainbow tables (databases of passwords and it's hashes). You can create one using a unique user info (like a user_id) or just create a random one and store it somewhere. Just make sure the salt is long enough.
normally it is better not to encrypt a password, but to hash it.
the difference is that encryption is encoding a string, leaving the possibility to decode it.
hashing is "one-way" - once you "hash" something, you cannot de-hash it. some strings can be hashed into the same result, but good hashing reduces the chance of a collision.
It is best to avoid storing actual passwords, since people tend to use a single common password to multiple websites. this means that you can access their accounts on other websites (or if you are leaked, the hacker can).
it's common to hash the password string together with "salt". This is some random string that it difficult to guess, like &%P)##M##)+!#~!#4320`2##!$0 or something of that sort. Common hash methods are md5/sha1 (or other sha method).
so you would have:
$password = '....';
$enc_pass = sha1( '%^$sd%MDdF)#I#)3asd3223##4*^&(*&##' . $password );
$enc_pass will be stored in the database, and after a login form, the result will be hashed (as above) and compared to the value in the database.
PS: don't forget to have your database column of a size that would contain the entire password ;)
I'd just like to add that storing a hash of the passwords does not automatically make the authentication process secure. What you also should employ is a decent password policy. The reason is, even if you have the most sophisticated hash algorithm of all time, and a user uses the password "password" or "1234", then the algorithm is useless, because the password can be simply guessed.
Don't forget to make a restriction on password strength.
Because password strength is a weakest part of the whole thing.
As long as your users do use weak passwords, no salt nor extra-secure hashing routine would be of any help.
The best hashing algorithm you can use is salted MD5 hashing where you insert some random characters inside the MD5 hashed string for that particular object. But you must remember the positions where you had inserted the random characters. This is required so that you can decrypt the hashing to obtain the original object or string.
$random="abcd";
$hashed=md5(your_string);
$salted_hash=$hashed.$random;
This is the simplest example where I have just concatenated the hashed and salt. but you can insert the salt string somewhere in the middle.
Related
This question already has answers here:
Best way to store password in database [closed]
(8 answers)
Closed 10 years ago.
Yes I know storing passwords in plain text is not advised.Is there a best and easy way to store passwords so that the application remains secure ??
First off, md5 and sha1 have been proven to be vulnerable 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 is sha512. sha512 is a sub-version of SHA2. SHA2 has not yet been proven to be vulnerable 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. It's 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);
A salt is usually a random string that you add at the end of all your passwords when you hash them. Using a salt means if someone 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
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 (just change the work factor), and it uses salts internally to protect against rainbow tables. I would go with such an approach or similar (e.g. scrypt or PBKDF2) if I were you.
Store a unique salt for the user (generated from username + email for example), and store a password. On login, get the salt from database and hash salt + password.Use bcrypt to hash the passwords.
Passwords in the database should be stored encrypted.
One way encryption (hashing) is recommended, such as SHA2, SHA2, WHIRLPOOL, bcrypt
DELETED: MD5 or SHA1. (those are older, vulnerable
In addition to that you can use additional per-user generated random string - 'salt':
$salt = MD5($this->createSalt());
$Password = SHA2($postData['Password'] . $salt);
createSalt() in this case is a function that generates a string from random characters.
EDIT:
or if you want more security, you can even add 2 salts:
$salt1 . $pass . $salt2
Another security measure you can take is user inactivation: after 5 (or any other number) incorrect login attempts user is blocked for x minutes (15 mins lets say).
It should minimize success of brute force attacks.
best to use crypt for password storing in DB
example code :
$crypted_pass = crypt($password);
//$pass_from_login is the user entered password
//$crypted_pass is the encryption
if(crypt($pass_from_login,$crypted_pass)) == $crypted_pass)
{
echo("hello user!")
}
documentation :
http://www.php.net/manual/en/function.crypt.php
You should use one way encryption (which is a way to encrypt a value so that is very hard to revers it). I'm not familiar with MySQL, but a quick search shows that it has a password() function that does exactly this kind of encryption. In the DB you will store the encrypted value and when the user wants to authenticate you take the password he provided, you encrypt it using the same algorithm/function and then you check that the value is the same with the password stored in the database for that user. This assumes that the communication between the browser and your server is secure, namely that you use https.
I know that there are alots of questions about this subject but i really need to ask this.
Today I've been working on encrypting passwords with md5.
So what I've done is.
I got 4 salts. (they changes depending on user values)
from email id and substr then md5 them
from email and id substr other positions
a long string, substr it and then md5 it
another long string, substr it and then md5 it
Then i md5 salt1 and 3 and the password with salt 2 and salt4
After this I have to change the password automatically whenever a user changes his email or his id getting changed.
What do you guys think about this?
Nothing.
MD5 is broken and bad.
Using the mailaddress as salt is a good idea. But using md5 is not. Use instead bcrypt, scrypt or pbkdf2.
Don't invent your own ecryption, unless you really know what you are doing, and trust me, you don't
First, let us define a few terms.
Encryption is when you encode a message so that it cannot be read. Encryption involves a plaintext, a cipher and a key. It is like putting a book (the plaintext) in a locked room (cipher), which can only be opened using a known tool (a key). There are many kinds of encryption, but that is a simple description. Encryption is two-way, meaning that you can encode and decode the message.
Cryptographic hash is when you take any kind of data and generate a fixed size value for it (usually called a hash or a digest). Cryptographic hashes are one-way, which means that you cannot reverse the process.
A salt is a unique string, or a collection of bits, similar to a nonce (a unique number that is only used once). Salts are only used to make it infeasible for a cracker to process a list of hashes. They are not supposed to be used as a secret (i.e. like a cryptographic key). The only reason people usually talk about randomness when it comes to salts is because they want to generate a unique salt (if the randomness is not great enough they may get colliding salts, for instance).
Okay, now to how you should hash a password.
A relatively safe way of hashing a password is to simply tack on a unique hash onto a password, and then save the salt with the password:
$pass = 'this is my password';
$salt = uniqid('', true);
$hash = sha1($pass . $salt);
// INSERT INTO users ('hash', 'salt') VALUES ('$hash', '$salt') WHERE ...
That is an okay way of doing it if your website does not retrieve any sensitive data from its users.
If you deal with sensitive data, or if you just want to make sure that you are doing everything you can to keep stuff safe, then there is a PHP function that does the hashing for you. It is called crypt() (read the documentation to learn how it works). Here is an example of how to hash a password using the function:
$pass = 'this is my password';
$salt = 'unique string';
$hash = crypt($password, '$2y$07$'.$salt.'$');
echo $hash;
That will securely hash a password.
The thing to realize is that the crypt() function is much more secure than anything you can come up with (unless you are a specialist in the area).
In newer versions of PHP (5.5.0+) there is a password hashing API that makes it even simpler to hash a password.
There are also various hashing libraries out there. PHPass is a popular one.
It is bad, because it uses MD5.
MD5 is a very fast operation. It can be executed billion of times per second on graphic cards hardware. It is considered bad practice to use it for any password related things.
Use bcrypt. Use a random salt. Use the upcoming PHP API for hashing, verifying and rehashing passwords. This include file implements it for versions starting with PHP 5.3.7: https://github.com/ircmaxell/password_compat
Well, "MD5 is broken and bad" is a little exagerated. Even if it can be brute-forced with a lot of CPU, it is not "broken" and is still a very useful algorithm for a lot of things involving hashing.
So "MD5 should not be used for password encryption" sounds much better to me.
When using PHP, an easy and safe option is to rely on the password_hash() (which natively generates a random salt) and password_verify() functions.
The advantage is that the encryption algorithm will transparently be updated with each new PHP version (at the moment PASSWORD_DEFAULT is set to bcrypt, but should bcrypt be "broken" it can be set to a newer algorithm), which makes any code using those functions quite resilient.
I personally do not recommend involving of the user id and his email into the hashing of his password.
You can deal with the password by:
Dynamic salt per user based on random string generated on user registration
Prepend one part of the salt and append the other around the password
Double md5: md5(md5($password))
Etc.
a simple way would be to generate a random salt for each user and hash your password like this
public function encodePassword( $raw, $salt ) {
return hash('sha256', $salt.$raw);
}
For high security hash, you can check this link which explain how to implement PBKDF2:
http://crackstation.net/hashing-security.htm#phpsourcecode
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.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Secure hash and salt for PHP passwords
WARNING Don't use MD5 for passwords, use an alternative like bcrypt
For my passwords should I use salt like this (the salt will be unique to each user and not stored directly with the password)...
$salt = sha1(md5("coders gonna code"));
$password = md5($salt.$password);
or would it be okay if I just used:
$password = md5($password);
because if I used salt, even if the user makes up a bad password like password it won't matter because the salt (in this case) would be 145ac26ff093c6e1317f7d5fb4c9fd11c77be975 so the entry for there password would be 145ac26ff093c6e1317f7d5fb4c9fd11c77be975password which according to http://howsecureismypassword.net/ it would take 3 octodecillion years to crack.... so opinions? Or should I be even worse and go
$password = md5($salt.$password.md5($salt));
If the person has gone far enough to get the salt hash, would anything be able to stop then going futher? < More of a statement this last password
To everyone who said I should do it per user... I know, this is just an example.
You should change the salt so that it is specific to each user, not a system wide constant. This will make rainbow table attacks against your password hashes much more inconvenient.
There is a good write up on the evolution of salting in this article by Troy Hunt.
Edit
$salt something unique to each password record, which adds much entropy to it. This is usually a random sequence of bytes, stored with the user account.
Hashing is traditionally done on the concatenation of salt + password.
$passwordHash = hash($salt.$password);
As others have said, don't use MD5 for hashing. It is broken.
Applying additional proprietary algorithms to password or salt prior to hashing is not recommended. Instead, look at an industry strength solution such as PBKDF2, which, in addition to salting, also requires many (typically > 10k) repeated iterations which will further slow down an attacker.
If you adopt OWASP guidelines, the number of hashes performed should be increased regularly (to counteract Moore's Law). The number of hashes should also be persisted per user, meaning you will need to store the triple of hashed password, salt, and number of iterations.
You are using the salt totally incorrectly. Salts should be unpredictable; your salt is the exact opposite of that (fixed). Since a fixed hash is of absolutely no benefit, it also seems that you are counting on the salt not being known by the attacker. This is the definition of security through obscurity, which is another bad practice.
What you should be doing is:
Use an unpredictable string of reasonable length as the salt. Randomly generated 8-character strings from a pool such as lower/upper case letters and digits are fine.
Use a different salt for each user, and change it every time they change their password.
Move from MD5 (which is considered broken) to another hash function better suited to this application. SHA-1 is better because it's not considered broken; bcrypt is the best because it has a configurable load factor.
Don't use MD5 as your hashing algorithm, use something more secure such as SHA256 or even bcrypt.
Definately salt the password, if someone did gain entry to your database they would not be able to reverse the passwords for common hashes or using techniques such as rainbow attacks.
http://michaelwright.me/php-password-storage
http://en.wikipedia.org/wiki/Bcrypt
First of all you should never store md5 directly, which you regognized already.
PHP 5.5 will bring new methods to easily create and verify passwords in 1 line, until then you can use https://github.com/ircmaxell/password_compat (forward-compatible) to generate & verify safe password hashes.
I think salt is understood here incorrectly. The idea of salt is that it should be unique per hash. The reason is that when you create hash some different strings may have the same hash.
In your example you're hashing password too so it won't look like: 145ac26ff093c6e1317f7d5fb4c9fd11c77be975password
P.S. Use bcrypt. It's much more reliable.
Salts are meant to be completely random, and unrelated to the actual password you are storing a hash of.
What you should really do is generate a completely random salt, then do
$password = md5($salt.$password);
and store the user's username, salt and hashed password.
I have a few questions concerning password hashing. I found hash_hmac a pretty good function to hash passwords but a few questions remain.
From another stackoverflow questions someone responded with:
return hash_hmac('sha512', $salt . $user['password'], $this->site_key);
My initial question concerns how hmac uses the key, on wikipedia it seems that the hmac function would prepend the key to every piece of message before hashing it, does the key itself not act as a salt then? Can I then drop the $salt and just use a user specific key instead? hash_hmac('sha512', $user['password'], $this->user_key)
The big question remains the generating of the $salt (or the $user_key from first question). I don't like to store the used salt in the database if I would generate them using rand(). What would then be a good way to generate a user specific salt?
Update
If I would store the salt in the database, is it safe to use:
$user_key = $user['salt'] . $this->site_key;
return hash_hmac('sha512', $user['password'], $user_key);
Use a random per user salt and store it together with the hash in the database. Combine it was a per-site secret that's in your config-file. That way an attacker needs to gain access to both the database and the config-file before he can start to crack passwords.
To hash passwords securely I recommend combining three ingredients:
A good Key-Derivation-Function. It's similar to a plain hash, but it's slow and takes a salt. bcrypt and PBKDF2 are common choices.
A random per user salt. The main purpose of this is that it's different for each user. You store it together with the hash in the database. No problem if the attacker gets it.
A per-site secret. The purpose of this is that getting access to the database is not enough to crack passwords. The attacker needs access to the config file too. And even if he learns the per-site secret the scheme is still as secure as if you had used no secret at all.
Use bcrypt!
The classic text on safely storing passwords:
http://codahale.com/how-to-safely-store-a-password/
Quote from the article:
Salts Will Not Help You
Bonus!
using bcrypt is simpler than finagling your own bs and likely incorrect salting scheme.
DON'T EVER IMPLEMENT YOUR OWN CRYPTOSYSTEM OR SOURCE OF ENTROPY