Salting Algorithm Strength - php

What are the advantages / disadvantages of those 3 methods to create a salt?
$salt = md5($password);
$salt = sha1(md5($password));
$salt = generate_random_number();
Computing hash:
$hash = sha1($salt + $password);

Salts
To answer this question it's important to know for what salts are.
Salts are designed against attacks with pre-calculated tables. For example rainbow tables. Rainbow tables are huge tables with all possible password variations up to a certain length. (Using a clever memory/time tradeoff.)
If the attacker only wants to crack a single password, they don't offer an advantage.
The statement above is not true if
The database doesn't use salts. Then a common rainbow table can be used.
The salt is too short. If the salt is too short, it has the same effect as just having a longer password.
It's a common salt like salt. There are for sure already some rainbow tables with that salt included.
Attackers using rainbow tables usually want to crack as many accounts as possible.
Which of your methods is most secure?
All of your methods except the third are insecure. This is because using any of the other methods allows the attacker to calculate a rainbow-table for your whole database.
Because the salt is dependent on the password. Don't make it dependent on the username either, this would still allow an attacker to create a rainbow table for the 100 most common usernames.
Keep in mind
Use only a cryptographically secure random generator to calculate your salts.
Don't use MD5. It's already considered broken, use at least SHA1.

The first two methods are worthless. The whole point of salting is that the same password does not always result in the same encrypted/hashed string.
If you make the "salt" dependent on just the password, the same password will always result in the same hash. So basically the result is the same as if you'd use a slightly different hash function without any salt.
With the third method two users with the same password will usually get a different salt and the hashed version of the password will look different for both users. It will be hard to tell by the hashes that they both have the same password.

Well strictly speaking you only have one salting method, where you calculate the hash. The first three lines are different ways of generating a salt.
So a salt is there to stop precomputed lookup tables from discovering passwords. It should be a fixed value stored someone that is, preferably, unique to the plain text being hashed.
The most secure would be to use a cryptographically secure random number generator to produce a salt which is then stored along side the password.
If you created a salt which was an MD5 of the password then it would have to stored alongside the hashed and salted password value, which means you have an unsalted hash which is vulnerable to precomputed lookup tables, unless you plan to calculate it every time which is a small performance hit. By taking a SHA hash of an MD5 hash you're reducing the possibility of the plain text values, as there's a finite number of MD5 hash values as they are fixed length. This would mean that a rainbow table lookup might have a greater chance of success than a truly random salt.
So use the random salt please.

A useful way to think of rainbow tables is that they can be built for any one-way (or "trapdoor") function that only has one input. That is, if you use the same function, F, for all your passwords: hash = F(password). F could be MD5 or SHA1 or whatever.
Now lets look at salts. You use a salted function G, hash = G(salt, password). If all passwords in your database use the same salt, you can construct a function G, where G(password) = F("your salt", password), so there is a single input function, and thus you can build a rainbow table.
What if the salt depends on the password? Say the salt = I(password), we can build J(password) = G(I(password), password), a single input function, so rainbow tables can be built.
So, each password needs to have its own salt. This means that in the time it would take an attacker to crack all of your passwords, they can only crack one.

Related

Salt and passwords [duplicate]

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.

Using 512-hash before Bcrypt?

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

Safe Password Storing

Let's say I have thousands of users and I want to make the passwords very secure. Now, I've learned that md5() is not the safest to use, however what I think can be done to be safe is salt it (I know this is nothing new). So for this I was thinking of creating two tables, one called accounts which will have all information associated with accounts and a table column called salt and the second table would be called something like auth and have the fields account_id, password
to start, I create a salt upon registration (generated randomly)
$salt = "#52/sBsO8";
then all the provided information goes to accounts salt being one of them
then after successfully putting the information in database, I create the password that is going to be stored in auth table, this way the password is not the md5 of the password the user enters, rather its the md5 of the salt and the password user enters
so the password in auth is
$password = md5($user_entered_password . $salt);
Test strings:
PHP Code
$password = "123";
$salt = "#52/sBsO8";
echo md5($password) ." / ";
echo md5($password . $salt);
output: 202cb962ac59075b964b07152d234b70 / dfbf0b257c5182af0ae893c2680f4594
The question is: Is this a pretty safe way of dealing with passwords? Because of md5() decrypting websites, there are so many ways to guess the passwords. And the decrypting websites don't actually decrypt the md5() they just have the md5 hashes of millions of strings.
md5 is likely to be the least safe among "popular" hashing algorithms.
Since you're using PHP, a better option would be crypt: http://php.net/manual/en/function.crypt.php
crypt($password, $salt)
For a good comparison of various hashing methods, see Jeff Atwood's post about password hashing
Excerpt about brute forcing benchmarks:
MD5 23070.7 M/s
SHA-1 7973.8 M/s
SHA-256 3110.2 M/s
SHA-512 267.1 M/s
NTLM 44035.3 M/s
DES 185.1 M/s
WPA/WPA2 348.0 k/s
the lower, the better, although DES is too short to be considered nowadays (56bit, thanks #thebod).
EDIT:
Although it isn't listed in the benchmarked methods above, the best hashing method that crypt supports is blowfish, here's an example to use it:
// $salt has to be built with exactly these components:
// '$2a$' . $2DigitsNumberAroundTen . '$' . $TwentyTwoLetters
$salt = '$2a$07$somesillystringforsalt';
crypt( $password, $salt );
Hash functions for passwords should be slow (need some computing time). Most hash algorithms are designed to be fast, but this makes it easier to create rainbow tables for every salt.
The salt should be random, and should be generated separately for every stored password. This salt has to be stored together with the hash, but is not secret (can be plain text). The salt makes dictionary attacks more difficult, and different salts make rainbow tables impracticable.
Ideally, you can adjust the computing time later for new hardware, without breaking existing hashes.
That's why you should use bcrypt to hash your passwords, it was designed especially for hashing password. And don't be afraid to use bcrypt! It is not for high security sites only, and using it can be as easy, as using an md5 hash.
It's recommended to use a well established library like phpass, and if you want to understand how PHP can generate such hashes, you can read this article.
Why do you think that this is more secure? The user types in a password. One assumes that the user is not an idiot and choses something that (s)he only knows. How is that different if that individual typed it in with the salt?
This actually makes it more insecure because if a person gets hold of the table that person has something to work on.
You are better off spending your engergies on ensuring that the computer is secure, your network is secure and teaching your users on sensible and secure passwords.

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.

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