I've been using PHPass to hash my passwords for a long time. I admit that there's still things I don't fully understand (or ignore) to hash a password properly so today I was reviewing all the info I could find about it.
Reviewing PHPass documents, I've steped into this:
Besides the actual hashing, phpass transparently generates random salts when a new password or passphrase is hashed, and it encodes the hash type, the salt, and the password stretching iteration count into the "hash encoding string" that it returns. When phpass authenticates a password or passphrase against a stored hash, it similarly transparently extracts and uses the hash type identifier, the salt, and the iteration count out of the "hash encoding string". Thus, you do not need to bother with salting and stretching on your own - phpass takes care of these for you.
I've bolded the sentence that bothered me.
I always though that the salt should be somewhat secret, in the sense that it should not be known to the attacker. So if a understood correctly, PHPass stores the salt used in the same hash so it is able to use it when comparing passwords and check if valid.
My questions are
Is this secure? If the hash is compromised, the attacker has the salt used to hash the password... There's something I miss here.
I'm here really free to bother about salting passwords? Can I really rely on PHPass?
A little background
A salt is not meant to be secret, instead, a salt 'works' by by making sure the hash result unique to each used instance. This is done by picking a different random salt value for each computed hash.
The intention of the salt is not compromised when it is known; the attacker still needs to attack each hash separately. Therefore, you can simply store the salt alongside the password.
So, is PHPass secure?
YES! PHPass (according to the best practices) generates a strong random salt for you. It is a well reviewed and good quality library.
Links of interest:
How to securely hash passwords?
How to store salt?
Password Hashing add salt + pepper or is salt enough?
Salt Generation and open source software
The purpose of a salt is not to be a secret. The purpose is to add a unique component to each hash input, so identical passwords will not hash to identical hashes, thereby making the brute-force process more difficult and time consuming since each hash has to be tried individually.
Yes, it would be marginally more secure if the salt was secret, but that's hard to realize in practice, since your application needs the salt as well, so it needs to be stored somewhere where the password is accessible as well. Therefore, in practice, when the attacker gets the password hash, he's typically also able to get the salt anyway.
If I understand correctly, salts are primarily used to thwart precomputed hash/rainbow tables attacks. As long as the hash that is used is generated so that it is reasonably globally unique (not hardcoded in PHPass for example), you're OK.
Related
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.
I remember reading about a scheme where the process of checking a password went like this:
given (hash, salt) in a database,
hash password with salt to check against the hash,
hash password with old hash as salt,
store (new hash, salt a.k.a. old hash) in the database.
I can't find the original source. In any case, I don't understand
what the advantage is of using the old hash as the salt (as opposed to using a random salt),
what the advantage of this scheme is in general (further complicating rainbow table attacks?), and
if there is an advantage, how one would apply the scheme using PHPass, since the salt seems to be managed "within" PHPass...
Intuitively, I think this scheme would do nothing at best, or worsen security at worst (due to a dependency on a past value), but password security is one area where I don't trust my intuition. Please enlighten me.
EDIT:
I'm asking about re-hashing the password on each check. These similar questions do answer the first question—that using a hash as a salt is useless—but not whether it's useful to re-hash on each check:
Using a hash of data as a salt
Using a hash of what you are hashing as a salt?
I am no security expert, but to answer #1 there is no advantage. All it does is complicate things further.
Just use a good randomly generated salt,
Like you said, PHPPass handles it internally, and PHPass is considered an extremely good tool as it has been reviewed by many security experts.
I've been reading a bunch of stuff about security and I'm just now starting to try and play around with the code. I want to use MD5 encryption with a salt. I ran across this nifty PHP script with random salt:
substr(str_shuffle(str_repeat('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',5)),0,10);
It randomly generates some characters as salt, but then I was thinking: How would I go about checking logins? Do I remove the salt, or should I store it in the database?
You shouldn't be using MD5 for password hashing. See How can I store my users' passwords safely?
To answer your original question, the salt is stored alongside the HASHED password in the database. The salt is not meant to be secret if the hashed password is discovered. Its purpose is to prevent attackers from using rainbow tables.
Store it in database. Otherwise you can't compare password provided by user with hashed one.
Some even regenerate hash (with new salt) upon each successful login of given user, although commenters below argue this is not the best idea (see comments)
Okay, so salts are used for both one-way hashes and encryption. They make it harder to reverse the encryption or the hash. I think it's easier to draw the point out with hashes, so I'll write from that point of view, but the principles apply to encryption in general.
Imagine that you're saving passwords. One of your users chooses the word "kiwi" as a password. Because storing passwords in plain-text is stupid, you don't want to do that. You want to hash the password.
But, those pesky hackers out there have compiled huge databases of hash look-up tables. (Check this one out!)
So, how do we foil the hackers? By salting the user's input! The salt is a random string (or set of bits, properly) that is cryptographically combined with the user's input to produce a more secure hash.
For example, if the string to be hashed is still "kiwi" and our salt is "5m3d", a simple salt mechanism might concatenate the two into: "kiwi5m3d". The hackers probably have "kiwi" in their database, but probably don't have "kiwi5m3d". A good salting system will probably perform a much more complicated function than this.
So now the hackers need a new look-up database for each possible salt. Using a random salt means that the hacker will have to do a full-on brute force attack, rather than recycling previous computations or using someone else's look-up table.
You could choose a different salt for everything, or the same salt for all the things on your site. A different salt of each entity necessitates a new brute force attack for each entity, but it can make implementation more difficult because each salt must be saved, rather than having one global salt (which, for data which is already somewhat random, e.g. passwords, should be sufficient).
In the case of encryption, look-up tables are still a possibility, but the data to be encrypted is generally varied enough that they're not feasible. So it becomes a game of playing "guess the password". It's easy to guess "kiwi" and hard to guess "kiwi5m3d".
You will have to save the salt somewhere, because it's the only way to "know" what's been hashed or encrypted. In the case of a hashed, you compare the user's original hash against the salted hash of their input. In the case of encryption, you need the salt to decrypt the data.
Where do you go from here?
First, don't use MD5. I gave you a link to an MD5 look-up database above. The function's increasingly considered to be weak. The sha class of algorithms is a better choice.
Second, make sure you choose a good salt. Longer and randomer is better. Computers are kind of bad at generating random data. This site could be one good choice and has a pretty good break-down of how it generates its random numbers.
Third, consider salt algorithms. Simple concatenation should work, but maybe HMAC (something I don't know much about) would be better.
You would have to store it in the database, otherwise you would not have anything to compare it to. The thing to remember with using a salt, is that the complexity can vary and without knowing what the salt is, the likelihood of it being brute forced hack is dramtically decreased.
Example:
$password = "banana";
$salt = "a12dsfg33B1cD2eF3G"; # Can be any assortment of characters
$password = md5($salt.$password);
Then you would just attach the same salt (would have to match to work) and pass the same function to your login script that combines the salt and the supplied password. You would then check that to the value in your database to authenticate the user.
Do not invent your own password-hashing scheme, however nifty it may look. Having a secure system is hard because you cannot really test for security. What you need is the following:
For each password instance, a random salt of sufficient length is created.
The random salt is stored along the hashed value; you will need it to verify the password afterward.
The password hashing process must be (configurably) slow, with many (many) nested invocation of whatever hash function is internally used.
Preferably, the internal hash function should use operations which are efficient on a PC but slow on a parallel architecture (a GPU).
Such a thing exists, it is called bcrypt and you can get it in PHP with the portable PHP password hashing framework.
I am looking into building a login system and after reading the php manual when you pass a 2 digit salt to the crypt() function it returns a hash string, and the first 2 digits of the string are the salt that you used.
example:
$salt = "kr";
echo crypt("mysecret",$salt); //returns "kreOI.F7eOQMY"
My first thought was, wouldn't this help someone who is trying to reverse your hash?
I looked up salt on wikipedia which said:
For best security, the salt value is kept secret.
So I do not understand why then would the crypt function return all hashes prepended with the salt value used?
Is there a reason for this? Should this be a security concern?
The author of the Wikipedia article is conflating salt with the idea of search space, implying salt is a way to deter brute force attacks. Security is not improved by confusing these ideas; someone who can't recognize and delineate these two issues is not a credible guide.
The purpose of salt is to thwart pre-computed lookup tables (like a Rainbow table). Salt prevents an attacker from trading "space" for "time." Every bit of salt doubles the storage requirements for a table; a two byte salt makes a big (65536 times) difference, but eight bytes would require non-existent "yottabyte" storage devices for lookup tables.
Assuming that the salt cannot be kept secret encourages better key-strengthening and password selection, and this leads to more secure system.
However, recent recommendations from NIST encourage the use of an additional, secret "salt" (I've seen others call this additional secret "pepper"). One additional iteration of the key derivation can be performed using this secret as a salt. Rather than increasing strength against a pre-computed lookup attack, this round protects against live dictionary attacks. In this way, it's more like the large number of iterations in a good key derivation function.
This secret serves no purpose if stored with the hashed password; it must be managed as a secret, and that could be difficult in a large user database.
Brute force attacks are best prevented by key-strengthening (applying the hash function thousands of times), and password selection rules (require longer passwords, reject blacklisted entries, etc.), but a "pepper" provides an additional layer of defense.
I should comment that Crypt is not as bad as Marc B makes it sound, and may in fact be the easiest way to good hashes, as long as you don't rely on its weaker schemes like MD5.
See:
How do you use bcrypt for hashing passwords in PHP?
http://uk.php.net/manual/en/function.crypt.php
http://www.openwall.com/phpass/
Yes, the salt is supposed to be kept secret, but then so is the password hash. It's perfectly acceptable for them to be kept equally secret in the same place. To check a password against the hash, you have to combine the salt with the password and then check it against the hash. So, any user or process with the right to see the password hash should also have the right to see the salt, since the password hash by itself is not useful for checking passwords (unless you're going to brute-force the salt).
The purpose of the salt is so that if two different users have the same password, they'll hash to different things. This also means that dictionary attacks are much more complex because you can't just hash all likely passwords and then check them against a list of user password hashes to find multiple user's passwords. Instead you have to try passwords for an individual salt to find one user's password or try all combinations of likely passwords with multiple salts in order to find hits. But knowledge of the salt, by itself, doesn't mean you can reverse the password hash. It just means that you can do a dictionary attack on the password hash.
If you can find a way to keep the salt more secure than the hash value, it certainly wouldn't be a bad thing, but it's hard to see how this is feasible when any program which needs access to one needs access to both.
The crypt() function is obsolete. It was used to hash passwords for old-style Unix systems, before shadow password support came along. The salt was there to increase the complexity of brute forcing the password. However, since the salt was randomly generated by the password subsystem, it had to be stored in the clear so any future password actions would work. If the salt had been embedded into the password before crypting, there would be no practical way to verify a password - you'd have to try every single possible salt whenever a password check was done - highly impractical. So, the salt was prepended to the crypted password, so you could pull it out again for future use.
crypted password: xxabcdefghijklmn
^^- salt
^^^^^^^^^^^^^^-- crypted pw
if ('xx' + crypt('xx' + password) == 'crypted string') then
password is ok
endif
These days, crypt() is the security equivalent of a cereal box decoder ring. There for historical purposes, and low-security "who cares if it's cracked into" storage. For any modern password usage, you'd be better off with more modern hashes, such as sha1/sha256/md5. And even md5 is considered broken these days, sha1 has cracks around the edges, and (last I checked) sha256 is still secure.
The salt is appended to the has so that you will know which salt to use when you get the password and want to see if it matches the hash. The idea here is to use a different salt for every password so that someone cannot precompute a hash table.
You could also append a second salt to every password (the same for all) and not tell anyone what it is.
PHP crypt inherits this behaviour from the UNIX crypt() function, which was used for generating password hashes in the UNIX passwd file. It's necessary to store the salt somewhere, or you can't verify later that the password is correct. For the passwd file, the simple behaviour was just to prepend the salt (always two characters) to the start of the crypted password, which makes it simple to store it in a single field.
The statement that the salt value should be kept secret is open to misinterpretation. For best practice you should not publish your salts, in the same way that you should not publish your password hashes. Giving an attacker the hashes and salts makes it easy for them to run a brute-force attack without generating suspicious traffic to your system. However, the system should still be secure even if an attacker can see both salt and hashed password.
In fact, there's nowhere you can store the hash that couldn't, in principle, be compromised by a hacker in exactly the same way as the hashed passwords. If the password-checking code can access it, then you have to assume that someone who's compromised the system could get access to it as well.
So I've been reading a lot about encryption in PHP. So much that I am not sure exactly what's a really good method to securely store login information.
However, the following function is what I came up with:
function loginHash($username, $password){
$salt = str_split($password,(strlen($password)/2)+1);
$hash = hash('whirlpool', $username.$salt[0].'centerSalt'.$salt[1]);
return $hash;
}
Am I doing it the right way? It's used for authenticating a password combined with a username, and the ability to compare the generated hash with the one stored in a database to verify a login.
Encrypting != Hashing. They both are generally accepted to be in the category of Cryptography, but when something can be encrypted, it can be decrypted, which is not the case in Hashing. Hashing is just hashing, and that's it.
The salt is indeed not properly constructed. It should be x-bytes read from /dev/urandom with a fopen() call. For example, 16 bytes of salt is what I personally use. This prevents rainbow table attacks effectively.
To make things more secure, use a secret key, too. For example:
$hashedPassword = hash_hmac('whirlpool',$password.$salt,$key);
The $key is simply random data. You could generate a 64 kB file, for instance, that is called "key.bin" in a hidden folder above the document root and use file_get_contents() before the hash process.
Why to use secret keys? If you store the hashes and salts in a database and the key in the filesystem, then this prevents anyone from cracking your hash if they get their hands on your stored hashes and salts. So, an attacker would need to crack into both the database and the filesystem to crack your hashes, but notice that it's pointless for anyone to crack your hashes anymore if they have already cracked your whole application, which implies that your hashing scheme is good.
My advise is to never, never, never write your own encryption and hash functions. Even experts do it wrong all the time, so dont try it yourself.
Ive heared that phpass (Openwall) is a nice hashing framework, i'd suggest you use that.
They use salts in their hashes and have quite some parameters to tweak the hash.
You're not actually using a salt.
Salt is a randomly generated string that is included in the input for your hash function. As such, it will be different every time.
The idea is that you generate a salt when a user stores a password, and that this salt is included in your data storage. When authenticating, you retrieve the salt and the stored hash, you prefix the given password with the stored salt, and hash the two together. Then compare the result with the stored hash.
I think the above code checks the two boxes.
Avoiding rainbow table attacks (via Salts)
Secure Login
using salt solves two problems:
rainbow tables: rainbow tables are just precalculated hashes, stored with the source value. by comparing the hashes, you get the unhashed value (password). by adding salt you got another layer of complexity - the attacker must know the salt for generating a custom hashing table.
difference of hashed values: without salt, the same 2 passwords generate the same 2 hashes. now it's easy to see if two users use the same password (the weak point here is about the same as with the rainbow tables, but still). that may not amount to much, but is still a point of concern.
additionally, you shouldn't use fast algorithms for password hashing. md5 is fast, sha is fast. the slower, the better.
the matsano chargen blog is a good (and funny) resource for hints and pointers regarding security.