Hashing using crypt in PHP - php

Recently i was reading a book regarding a safe way to store a password in the database. The book started with MD5, SHA1, and CRYPT_BLOWFISH. From what i read i understand that the safer way to store passwords is by using CRYPT along with random salt per user(a value that the user inserts in while registrating, like username for example), without storing the salt in the database.
So, lets say that i generate a salt:
$salt = '$2y$11$';
$salt = $salt.md5($username);
As we know a MD5 hash is a 32 character long string. So 7+32 = 39 character string = SALT
Something like this: $2y$11$243dc6440dfd91e35a773035da362f4e
Then i generate the hash using crypt():
$hash = crypt($password,$salt);
The crypt hash always results in a 60 character string. The result is:
$2y$11$243dc6440dfd91e35a773uY4TBuP14hk.KZq4VvOWV8EhT03Vj8Tu
If a hacker gain access to the database, he/she will see the part $2y$11$ of the 60 character string above.
My question is: Is this info helpful for the hacker (knowing the hashing method and the cost)?
Should I store the hash omitting that part? 243dc6440dfd91e35a773uY4TBuP14hk.KZq4VvOWV8EhT03Vj8Tu
Will this make things worse for the hacker?
Other than these, are there any other suggestions regarding password security AFTER the hacker gains access to the database?

There is a tutorial i wrote about safely storing passwords, it explains why it is not necessary to hide the hash parameters.
If you hide this parameters you actually add a server side secret (an attacker has to guess the algorithm and the cost factor). There are much better ways to add such a secret though, have a look at the last part of the tutorial about encrypting the hash-value with a server side key.

A salt is used to defend against dictionary attacks and rainbow table attacks becasue the resulting hash is different due to the randomly generated salt which was added to the password.
The salt is saved with the hash so that the hash can be regenerated from the password+salt.
So because of this the salt needs to be saved and so what you have done is one possible way of doing this.
The reason this is not helpful to the hacker and won't make things easier is because the whole point of a hashing algorithm is it's resistance to being reversed. Dictionary attacks and rainbow tables work by using known hashes that have been derived from a "word" to a hash. With an added random number in front of the original "word" the hash is completely different and so to create a dictionary or rainbow table with all possible salt values (for a given length salt) would be a huge database and take way too much time for the hacker to crack or even bother attempting.

The system appears to be a 3 part system.
A Salt to prevent Rainbow Table Attacks.
The Salt itself is protected by using some pseudo random data.
The Base Salt and the pseudo random data is mixed and used as the Final Salt.
With the 3 parts above you have a system that is resistant to Rainbow
Table attacks (1).
The System is further resistant to Finding a Rainbow
Table for your Salt. (2).
So if your system is compromised, an
attacker would have to generate a Rainbow Table for each User
Account. This is essentially equivalent to cracking that/each users
password. (3).
Or so Would the theory go.

Related

What is hacking scenario prevented by salts, need more than just 'bruteforce'? [duplicate]

I'm having some trouble understanding the purpose of a salt to a password. It's my understanding that the primary use is to hamper a rainbow table attack. However, the methods I've seen to implement this don't seem to really make the problem harder.
I've seen many tutorials suggesting that the salt be used as the following:
$hash = md5($salt.$password)
The reasoning being that the hash now maps not to the original password, but a combination of the password and the salt. But say $salt=foo and $password=bar and $hash=3858f62230ac3c915f300c664312c63f. Now somebody with a rainbow table could reverse the hash and come up with the input "foobar". They could then try all combinations of passwords (f, fo, foo, ... oobar, obar, bar, ar, ar). It might take a few more milliseconds to get the password, but not much else.
The other use I've seen is on my linux system. In the /etc/shadow the hashed passwords are actually stored with the salt. For example, a salt of "foo" and password of "bar" would hash to this: $1$foo$te5SBM.7C25fFDu6bIRbX1. If a hacker somehow were able to get his hands on this file, I don't see what purpose the salt serves, since the reverse hash of te5SBM.7C25fFDu6bIRbX is known to contain "foo".
Thanks for any light anybody can shed on this.
EDIT: Thanks for the help. To summarize what I understand, the salt makes the hashed password more complex, thus making it much less likely to exist in a precomputed rainbow table. What I misunderstood before was that I was assuming a rainbow table existed for ALL hashes.
A public salt will not make dictionary attacks harder when cracking a single password. As you've pointed out, the attacker has access to both the hashed password and the salt, so when running the dictionary attack, she can simply use the known salt when attempting to crack the password.
A public salt does two things: makes it more time-consuming to crack a large list of passwords, and makes it infeasible to use a rainbow table.
To understand the first one, imagine a single password file that contains hundreds of usernames and passwords. Without a salt, I could compute "md5(attempt[0])", and then scan through the file to see if that hash shows up anywhere. If salts are present, then I have to compute "md5(salt[a] . attempt[0])", compare against entry A, then "md5(salt[b] . attempt[0])", compare against entry B, etc. Now I have n times as much work to do, where n is the number of usernames and passwords contained in the file.
To understand the second one, you have to understand what a rainbow table is. A rainbow table is a large list of pre-computed hashes for commonly-used passwords. Imagine again the password file without salts. All I have to do is go through each line of the file, pull out the hashed password, and look it up in the rainbow table. I never have to compute a single hash. If the look-up is considerably faster than the hash function (which it probably is), this will considerably speed up cracking the file.
But if the password file is salted, then the rainbow table would have to contain "salt . password" pre-hashed. If the salt is sufficiently random, this is very unlikely. I'll probably have things like "hello" and "foobar" and "qwerty" in my list of commonly-used, pre-hashed passwords (the rainbow table), but I'm not going to have things like "jX95psDZhello" or "LPgB0sdgxfoobar" or "dZVUABJtqwerty" pre-computed. That would make the rainbow table prohibitively large.
So, the salt reduces the attacker back to one-computation-per-row-per-attempt, which, when coupled with a sufficiently long, sufficiently random password, is (generally speaking) uncrackable.
The other answers don't seem to address your misunderstandings of the topic, so here goes:
Two different uses of salt
I've seen many tutorials suggesting that the salt be used as the following:
$hash = md5($salt.$password)
[...]
The other use I've seen is on my linux system. In the /etc/shadow the hashed passwords are actually stored with the salt.
You always have to store the salt with the password, because in order to validate what the user entered against your password database, you have to combine the input with the salt, hash it and compare it to the stored hash.
Security of the hash
Now somebody with a rainbow table could reverse the hash and come up with the input "foobar".
[...]
since the reverse hash of te5SBM.7C25fFDu6bIRbX is known to contain "foo".
It is not possible to reverse the hash as such (in theory, at least). The hash of "foo" and the hash of "saltfoo" have nothing in common. Changing even one bit in the input of a cryptographic hash function should completely change the output.
This means you cannot build a rainbow table with the common passwords and then later "update" it with some salt. You have to take the salt into account from the beginning.
This is the whole reason for why you need a rainbow table in the first place. Because you cannot get to the password from the hash, you precompute all the hashes of the most likely used passwords and then compare your hashes with their hashes.
Quality of the salt
But say $salt=foo
"foo" would be an extremely poor choice of salt. Normally you would use a random value, encoded in ASCII.
Also, each password has it's own salt, different (hopefully) from all other salts on the system. This means, that the attacker has to attack each password individually instead of having the hope that one of the hashes matches one of the values in her database.
The attack
If a hacker somehow were able to get his hands on this file, I don't see what purpose the salt serves,
A rainbow table attack always needs /etc/passwd (or whatever password database is used), or else how would you compare the hashes in the rainbow table to the hashes of the actual passwords?
As for the purpose: let's say the attacker wants to build a rainbow table for 100,000 commonly used english words and typical passwords (think "secret"). Without salt she would have to precompute 100,000 hashes. Even with the traditional UNIX salt of 2 characters (each is one of 64 choices: [a–zA–Z0–9./]) she would have to compute and store 4,096,000,000 hashes... quite an improvement.
The idea with the salt is to make it much harder to guess with brute-force than a normal character-based password. Rainbow tables are often built with a special character set in mind, and don't always include all possible combinations (though they can).
So a good salt value would be a random 128-bit or longer integer. This is what makes rainbow-table attacks fail. By using a different salt value for each stored password, you also ensure that a rainbow table built for one particular salt value (as could be the case if you're a popular system with a single salt value) does not give you access to all passwords at once.
Yet another great question, with many very thoughtful answers -- +1 to SO!
One small point that I haven't seen mentioned explicitly is that, by adding a random salt to each password, you're virtually guaranteeing that two users who happened to choose the same password will produce different hashes.
Why is this important?
Imagine the password database at a large software company in the northwest US. Suppose it contains 30,000 entries, of which 500 have the password bluescreen. Suppose further that a hacker manages to obtain this password, say by reading it in an email from the user to the IT department. If the passwords are unsalted, the hacker can find the hashed value in the database, then simply pattern-match it to gain access to the other 499 accounts.
Salting the passwords ensures that each of the 500 accounts has a unique (salt+password), generating a different hash for each of them, and thereby reducing the breach to a single account. And let's hope, against all probability, that any user naive enough to write a plaintext password in an email message doesn't have access to the undocumented API for the next OS.
I was searching for a good method to apply salts and found this excelent article with sample code:
http://crackstation.net/hashing-security.htm
The author recomends using random salts per user, so that gaining access to a salt won't render the entire list of hashes as easy to crack.
To Store a Password:
Generate a long random salt using a CSPRNG.
Prepend the salt to the password and hash it with a standard
cryptographic hash function such as SHA256.
Save both the salt and the hash in the user's database record.
To Validate a Password :
Retrieve the user's salt and hash from the database.
Prepend the salt to the given password and hash it using the same hash function.
Compare the hash of the given password with the hash from the database. If they
match, the password is correct. Otherwise, the password is incorrect.
The reason a salt can make a rainbow-table attack fail is that for n-bits of salt, the rainbow table has to be 2^n times larger than the table size without the salt.
Your example of using 'foo' as a salt could make the rainbow-table 16 million times larger.
Given Carl's example of a 128-bit salt, this makes the table 2^128 times larger - now that's big - or put another way, how long before someone has portable storage that big?
Most methods of breaking hash based encryption rely on brute force attacks. A rainbow attack is essentially a more efficient dictionary attack, it's designed to use the low cost of digital storage to enable creation of a map of a substantial subset of possible passwords to hashes, and facilitate the reverse mapping. This sort of attack works because many passwords tend to be either fairly short or use one of a few patterns of word based formats.
Such attacks are ineffective in the case where passwords contain many more characters and do not conform to common word based formats. A user with a strong password to start with won't be vulnerable to this style of attack. Unfortunately, many people do not pick good passwords. But there's a compromise, you can improve a user's password by adding random junk to it. So now, instead of "hunter2" their password could become effectively "hunter2908!fld2R75{R7/;508PEzoz^U430", which is a much stronger password. However, because you now have to store this additional password component this reduces the effectiveness of the stronger composite password. As it turns out, there's still a net benefit to such a scheme since now each password, even the weak ones, are no longer vulnerable to the same pre-computed hash / rainbow table. Instead, each password hash entry is vulnerable only to a unique hash table.
Say you have a site which has weak password strength requirements. If you use no password salt at all your hashes are vulnerable to pre-computed hash tables, someone with access to your hashes would thus have access to the passwords for a large percentage of your users (however many used vulnerable passwords, which would be a substantial percentage). If you use a constant password salt then pre-computed hash tables are no longer valuable, so someone would have to spend the time to compute a custom hash table for that salt, they could do so incrementally though, computing tables which cover ever greater permutations of the problem space. The most vulnerable passwords (e.g. simple word based passwords, very short alphanumeric passwords) would be cracked in hours or days, less vulnerable passwords would be cracked after a few weeks or months. As time goes on an attacker would gain access to passwords for an ever growing percentage of your users. If you use a unique salt for every password then it would take days or months to gain access to each one of those vulnerable passwords.
As you can see, when you step up from no salt to a constant salt to a unique salt you impose a several orders of magnitude increase in effort to crack vulnerable passwords at each step. Without a salt the weakest of your users' passwords are trivially accessible, with a constant salt those weak passwords are accessible to a determined attacker, with a unique salt the cost of accessing passwords is raised so high that only the most determined attacker could gain access to a tiny subset of vulnerable passwords, and then only at great expense.
Which is precisely the situation to be in. You can never fully protect users from poor password choice, but you can raise the cost of compromising your users' passwords to a level that makes compromising even one user's password prohibitively expensive.
One purpose of salting is to defeat precomputed hash tables. If someone has a list of millions of pre-computed hashes, they aren't going to be able to look up $1$foo$te5SBM.7C25fFDu6bIRbX1 in their table even though they know the hash and the salt. They'll still have to brute force it.
Another purpose, as Carl S mentions is to make brute forcing a list of hashes more expensive. (give them all different salts)
Both of these objectives are still accomplished even if the salts are public.
As far as I know, the salt is intended to make dictionary attacks harder.
It's a known fact that many people will use common words for passwords instead of seemingly random strings.
So, a hacker could use this to his advantage instead of using just brute force. He will not look for passwords like aaa, aab, aac... but instead use words and common passwords (like lord of the rings names! ;) )
So if my password is Legolas a hacker could try that and guess it with a "few" tries. However if we salt the password and it becomes fooLegolas the hash will be different, so the dictionary attack will be unsuccessful.
Hope that helps!
I assume that you are using PHP --- md5() function, and $ preceded variables --- then, you can try looking this article Shadow Password HOWTO Specially the 11th paragraph.
Also, you are afraid of using message digest algorithms, you can try real cipher algorithms, such as the ones provided by the mcrypt module, or more stronger message digest algorithms, such as the ones that provide the mhash module (sha1, sha256, and others).
I think that stronger message digest algorithm are a must. It's known that MD5 and SHA1 are having collision problems.

Should I store my salt along with my hashed password in the database?

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.

md5 hashing using password as salt?

md5($password.md5($password))
is this good enough for password hashing? I am not asking for comparing this to something like bcrypt.
if it is not secure, tell me why.
The reason to use a different salt for each user's password is so that an attacker can't take a list of all the hashed passwords and see if any of them match the hash of something easy like "password" or "12345". If you were to use the password itself as salt, then an attacker could calculate md5("12345".md5("12345")) and see if it matched any entries.
As I understand it, there are four levels of hashing you can use on a password table:
None - store the password as plain text. If someone gets a copy of your database, they have access to all accounts. Plain text is bad, 'mkay?
Hash the password - store the hash of the password, and throw away the real password. If someone gets a copy of your database, they can't see any passwords, only hashes. However, if any users have used weak passwords, then their hashes will appear in rainbow tables. For example, if a user has the password "password", then an md5 hash stored in the database would be "5f4dcc3b5aa765d61d8327deb882cf99". If I look up that hash in a rainbow table like the one at gromweb.com, it spits out "password".
Use a salt value - choose a large random string like a GUID and store it in your configuration file. Append that string to every password before calculating a hash. Now the rainbow table is far less likely to work because it probably won't have an entry for "password59fJepLkm6Gu5dDV" or "picard59fJepLkm6Gu5dDV". Although precalculated rainbow tables are not as effective anymore, you can still be susceptible if the attacker knows your salt value. The attacker can calculate the hash of a weak password plus your salt and see if any user in your database uses that weak password. If you've got several thousand users, then each hash calculation lets the attacker make several thousand comparisons. How you actually use the salt may depend on the encryption algorithm you're using. For simplicity, just imagine it as appending the salt and the password together.
Use a distinct salt value - now you take something distinct like the user name, e-mail address, or even user id, and combine that with the password and the large random string from your configuration file before you calculate the hash. Now an attacker who knows your salt still has to recalculate the hash for every user to see if they have used a weak password like "password".
For more details, check out the Coding Horror post, "You're probably storing passwords incorrectly".
Although it seems quite enough to me, it will be in danger in case if someone precomputed a rainbow table based on the same algorithm (what is quite possible).
So, I'd rather use an email for the salt which seems pretty secure yet usable. Paranoids may add some constant site-wide salt.
People often makes too big deal out of password salt (in theory), while in their applications they allow simple passwords and transfer them in plain text over insecure HTTP in practice.
Every freakin' day I see questions regarding salt or hash.
And not a single one regarding password complexity. While
The only your concern should be password complexity.
Why? Let me show you.
extraordinary good salt + weak password = breakable in seconds
It is always assumed that salt is known to attacker. So, by using some dictionary of most used passwords and adding [whatever extra-random-super-long] salt to them, a weak password can be discovered in seconds. Same goes for brute-forcing short passwords.
just sensible salt + strong password = unbreakable
Quite unique salt makes precomputed tables useless and good password makes both dictionary and brute-force attacks good for nothing.
It doesn't do much against dictionary attacks, only twice as hard to compute a dictionary versus a single md5, and md5 is pretty cheap these days.
MD5 is not secure in itself because it is partially broken (collisions) and is too small of a digest anyway. If one doesn't want to use a proper password derivation function à la bcrypt, scrypt or PBKDF2 you should at least use SHA-256 for new designs (and have a plan to migrate to SHA-3 when it will be out, so be sure to store the scheme you used to hash the password with the result, so both scheme can coexist as you use the new hashing procedure when people change passwords).
If you intend to sell your program using MD5 in any capacity can be a show stopper for most government sales (e.g. in the US algorithms used must be FIPS 140-2 approved and many other countries got the same kind of requirements).
The reason why random password salt is recommended for hashing password, so that an attacker who knows the password hash can't compare it to rainbow table of pre-calculated hashed from dictionary.
If you're using password as salt, attacker can pre-calculate hashes of $word.md5($word) first from their dictionary
With your solution you pretty much defeats the purpose of using a salt against precomputed dictionary attacks.
With a precomputed dictionary, as the name implies, someone has already created a table of hashes (the computed md5 result) for particular words, ahead of time.
Consider this table hashtable (with imaginary hashes, just for illustration purposes)
word | hash
------------
foo | 54a64
bar | 3dhc5
baz | efef3
Testing these values against your table, could be as simple as:
SELECT h.word
FROM hashtable h, yourtable y
WHERE y.password = MD5( CONCAT( h.word, h.hash ) );
With a match, you'ld have the password.
However, if you did NOT hash the password, before concatenating it again with the password and hashing it once more, it would be more difficult to attack it with a pre-computed dictionary. Because then the password would be for instance md5( 'testtest' ) which makes the precomputed table worthless, if the precomputed table has only taken into account single instances of the word.
You can easily see that it gets even more difficult if you did not use the password as a salt, but used another random string as salt. And it gets even more difficult still, when you create unique salts for every passwords. Of course, if you create unique salts per password, you'd have to save the salt in a separate column along with the passwords in a database row.
So my advice would be:
md5( 'uniquesalt' . 'password' );
Or actually, don't use md5 at all, but use the far better sha1, sha256 (or higher) hashing algorithms.

Why does PHP crypt() prepend the salt to the hash?

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.

Is my authentication encryption any good?

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.

Categories