Jump to content

Yet another question about salt+hashing


Zephni

Recommended Posts

Just a quick question.

 

I have heard a few people say that they store a specific (maybe random) salt string in the same row as the user that is generated when the user account is created or password is changed. But I thought one of the reasons people use hashing is so if someone managed to get hold of the database they couldn't decipher the password (like a simple md5'd string). But putting the salt string next to the username surely gives the attacker a major push in the right direction?

 

I am not claiming to know anything, I'm just asking because I'm trying to find the best practice (Or at least a good tried and tested one). I like the idea of having a salt in a php config file, because that would mean an attacker would actually have to get your files, and if they had got that far then your pretty much screwed anyway.

Link to comment
Share on other sites

If your salts aren't random, they're not very useful. Ideally, they're unique as well

 

The idea of a salt is to add more entropy to a password (random) and to force two identical passwords to produce different hashes. A static hash does neither.

 

The idea isn't to protect the salt, the idea is to force an attacker to build a unique attack for each hash, and to slow down his hash attempts

 

Read the article in my signature, it explains a lot. I also suggest using the PHPass class they've built. I'm totally for experimenting and learning to do it yourself, but when it comes to security, I'm more that happy to use classes that people in the know have built, and many eyes have gone over. In production code anyways

Link to comment
Share on other sites

I think wordpress allows you to add a general salt (the same one for everybody) on their config page. if you did this you could hash it and the password anyway you want, md5 then sha1 etc.

 

And yes if they get your config file, the order you hash the pw & salt and your db tables you have a sh*t pot full of problems.

Link to comment
Share on other sites

@floridaflatlander

 

Please read the article in my signature, and understand it before trying to give security related advice. Help is appreciated, but when it comes to security, good will can lead to Swiss cheese.

 

A salt shouldn't ever be considered private data, it's there to make every password longer, and unique. The idea of a strong, slow hash is they can get your salts and hashes, but brute-forcing even a single password will take unreasonable amounts of time. The best part about key-stretching, the current common method used to do this, is you can always up the iteration count as brute-forcing gets faster.

Link to comment
Share on other sites

I read your article and I only got to this part before I had to check the date on it:

- "I heard that MD5 has been "broken". Shouldn't we use SHA-1 instead?"

- It is true that MD5 has been broken as it relates to certain attacks (practical). SHA-1 has also been broken in certain other ways (mostly theoretical). However, neither break has anything to do with the uses of these functions for password hashing, especially not as building blocks in a higher-level hashing method. Thus, any possible reasons to move off MD5 or SHA-1 as underlying cryptographic primitives for password hashing "because of the break" are purely "political" rather than technical.  (It may be easier to just phase out MD5 and SHA-1 rather than differentiate their affected vs. unaffected uses.)

 

Go here: http://www.oxid.it/cain.html and read about a free program you can download that let's you attack specifically md5 and sha1 bruteforcing over 10 million attempts a second with a good video card.

 

He's wrong when he thinks the reason to shy away from md5 is political.

Php.net themselves also recomment using crypt() instead (see http://se2.php.net/manual/en/faq.passwords.php).

It lets you use several stronger algoritms like the ones mentioned later in your article.

 

I liked the rest of the article but I wanted to bring that part up as well.

 

Link to comment
Share on other sites

My old ATI HD4870 can calculate over a billion/sec with an external cooler. You're not understanding the deeper concepts of the article.

 

MD5 is fine, so long as you stretch it.

 

Brute-force the following hash, I dare you. I'll even provide you the methods, and information about the source an attacker probably wouldn't have.

 

Here's the final hash, along with the salt, in HEX

c06ad9038c1fcd9fc223739a7ecdf35db10e126ba4c5ccd1d1c6dc3c9f78e0fca9a1fb8e8fa000b96399c1d80ba54e4c66470e19c11cf954257cd78f1cf31bc8

 

Here's the code used to derive that hash, minus the actual password used

<?php

$pass = 'TRY TO GUESS ME';
$salt = bin2hex(mcrypt_create_iv(32,MCRYPT_DEV_RANDOM));
$count = 20000;
$length = 32;
$algo = 'md5';

$hash = bin2hex(str_hash_pbkdf2($pass, $salt, $count, $length, $algo));

echo $salt.$hash;

  // PBKDF2 Implementation (described in RFC 2898)
  //
  // @param   string  p   password
  // @param   string  s   salt
  // @param   int     c   iteration count (use 1000 or higher)
  // @param   int     kl  derived key length
  // @param   string  a   hash algorithm
  // @param   int     st  start position of result
  //
  // @return  string  derived key

function str_hash_pbkdf2($p, $s, $c, $kl, $a = 'sha256', $st = 0) {
$kb = $st + $kl; // Key blocks to compute
$dk = ''; // Derived key
// Create key
for ($block = 1; $block <= $kb; $block++) {
	// Initial hash for this block
	$ib = $h = hash_hmac($a, $s . pack('N', $block), $p, true);

	// Perform block iterations
	for ($i = 1; $i < $c; $i++) {
		// XOR each iterate
		$ib ^= ($h = hash_hmac($a, $h, $p, true));
	}

	$dk .= $ib;								// Append iterated block
}

// Return derived key of correct length
return substr($dk, $st, $kl);
}

?>

 

I've used MD5, I've used only alpha-numeric characters, and it's between 4 and 8 characters.

 

The problem with brute-forcing this hash is I've used 20,000 iterations of the MD5 function. No matter how fast it is, you'll have to perform it 20,000 times to get a comparable hash.

 

MD5 isn't the issue, it's how you implement it.

Link to comment
Share on other sites

I still think it's worth shedding light over weaknesses in md5, especially since you just link a long article.

I don't want to install the software to crack it, I'm just going to go with alternatives to md5.

You know, that don't have custom made programs to crack them.

What I mean is, md5 is ok if you iterate the hell out of it.

But there are so much easier ways out there so why?

Link to comment
Share on other sites

"Iterating the hell out of it" is called key-stretching, and it's an amazingly effective. They talk about it in the article.

 

It takes something very portable, like MD5, and makes it much more difficult to brute force. You can increase iteration counts as time goes on.

 

Though, if available, algos like blowfish are better because stretching is a part of the algorithm

Link to comment
Share on other sites

Which is why I suggest crypt() instead.

It already has algorithms that do what your article suggests.

You can use Blowfish with a 22 character salt and 4-31 iterations or SHA-512 (or 256) with a sixteen character salt and 1,000-999,999,999 iterations.

Works just as well with less work.

 

The reason I replied in the thread was that I just thought it was rude of you to knock people down for giving (or trying to give as you wrote to florida) advice when they don't have your flashy signature article.

 

I think you made religion of that one article but there are plenty ways to make secure passwords.

In fact it's not an unbiased article - it's the product description of Openwall's  product - phpass.

I agree it's a good product, I just think people should know there are others too.

With less work.

Link to comment
Share on other sites

Any if the server you're running crypt on doesn't support Blowfish? Until PHP5.3, support for crypt's algos changes from system to system. Hell, why would you use blowfish when there are solutions like scrypt available? Sometimes weaker, but still strong, solutions are accepted due to portability... PHPass has a portable hash option for situations like that.

 

It is just political. MD5 is fine, if you implement it correctly. Rather than try to teach proper implementation, most find it easier to just say "don't use them." You quoted that point, directly from the article. Of course the article is biased towards PHPass. It's not something they're trying to sell, it's something they've made for the community and are giving away. The article helps an average programmer implement it properly. You can easily follow that tutorial, replacing PHPass with your own, home-brewed hash function, and it's still 100% helpful and accurate information. I don't know how you could make it much easier than PHPass anyways.

 

require_once('phpass.php');
$obj = new PasswordHash(8,FALSE);
$hash = $obj->hashPassword($password);
if( $obj->checkPassword($password, $hash) ) {
   echo 'Passwords match';
} else {
   echo 'Passwords dont match';
}

 

I've read a LOT of articles and books on secure storage of information. Some are pure theory, and hard to understand for the average person, some are full of oversimplifications or pure misinformation. The article on PHPass is filled with usable code, and worded to be as simple as possible for someone diving in to the concept of password hashing. Are there others? Sure. Are they as good as the one Openwall provides? Possibly. Feel free to link them, rather than knock the article. It was written by people who know more on the subject than you or I.

 

I'm not knocking people down, I'm knocking their information down. Misinformation in programming generally just leads to errors. Misinformation in security might not be noticed until the data has already been stolen. If you want to post advice about securing a password, make sure it's valid, or it will be pointed out and you will be asked to avoid doing it in the future.

 

Just to talk about numbers. If you were able to calculate 10bil MD5 hashes/sec, an 8 character alpha-numeric hash would only take you:

 

(26+26+10)^8 = 218,340,105,584,896 combinations.

218,000bil / 10bil = ~21,800 second to test all combinations, or only about 6 hours.

 

Now, if I were to stretch MD5 over 20,000 iterations, our numbers have now multiplied by AT LEAST 20,000. You're now talking ~5000 days, or ~13 YEARS to get this hash. Even if a method was introduced that was capable of halving the effort required to break a PBKDF2-stretched hash, you'd still be looking at a hard hash to brute-force.

 

Seriously though, instead of complaining about my devotion to one article, post the ones you keep saying are out there. It will either get praised, or shunned, and we all might learn something.

Link to comment
Share on other sites

What I'm saying is that there are built in alternatives to phpass already.

Crypt() is in PHP since PHP 4, mcrypt(), scrypt() and more all have support to do what PHPass does.

Mcrypt in particular is brilliant and lets you use a number of ciphers, among them Twofish.

 

You look too dogmatic when you say that anyone that doesn't hail Phpass doesn't understand the concept.

So you read books the average person doesn't understand? Great.

You can use Phpass but anyone else can use either one of the options above.

Most ciphers iterate a number of times these days.

 

Your 20,000 iterations took 2 seconds.

What if you had a couple of 100,000 users logging on and off at the same time?

I think most people (or say government organizations) can live with less than 20k iterations.

What if someone decides to perform a DOS attack to register multiple passwords at once?

 

I liked reading the article too, just be aware that it's one provider in a field where there are plenty.

 

You're like the guy who bought a Ford after reading the merchandising from Ford and calling anyone who drives anything else an idiot because of what it says in your Ford material.

Link to comment
Share on other sites

you say that anyone that doesn't hail Phpass doesn't understand the concept.

 

I think you don't understand what xyph wrote.

 

I had never read it, I don't know xyph, and that is not at all the vibe I get from his posts regarding this topic.

 

He hasn't called anyone an idiot, or made out that he's smarter than anyone else here. And when he asked you to back up your claims, you haven't, instead resorting to playing the victim in some imaginary attack.

Link to comment
Share on other sites

jesirose summed up most of what I wanted to say.

 

Until PHP5.3, crypt()'s algos varied from system to system. This is a portability issue, especially for those with shared hosts. If you're programming something that may be used on servers you have no control over, a fall-back like PBKDF2 is great.

 

Please, explain to us why using Twofish is better than using Blowfish for hashing passwords. Ciphers are used for encryption/decryption anyways, so I don't know how those would help.

 

My 20k iterations of MD5 was a proof of concept, not something you should take to the bank. I was explaining using examples that MD5 isn't broken. It's fine to use, and I've implemented it successfully in ~10 lines of code. If I optimized my machine, the 20k hashes would take miliseconds.

 

I never said PHPass was the only solution, just a REALLY good one, with a long article discussing it's implementation for even a novice coder. If any other good solution provided the in-depth article that Openwall has given us, I'd happily advertise it. I haven't seen one as complete or noob-friendly yet, thought.

Link to comment
Share on other sites

As a final note, @El Chupacodra

 

If you want to debate this, using terms like "just be aware that it's one provider in a field where there are plenty." means nothing. Please, back up this claim with the 'plenty,' or even just a couple 'providers.' You have yet to provide an alternative that will work on any given system, nor have you explained how to implement these native PHP functions properly.

 

Also, avoid using analogies, as it's very hard to make one without completely leaving the context of the debate. Ford SELLS a product. PHPass is a class, given free. Openwall does not benefit from me using their class, nor me advertising their class. This is more like a unbiased mechanic saying "I've looked at the parts they've used to build their engine, and I find Ford to be of high quality. You probably won't go wrong with them"

 

Using crypt() compatibly isn't exactly 'easy.' Here's a snippet that checks for compatibility, and falls back when algorithms are unsupported

<?php

$pass = 'hello world';
$iterations = 5000;

if( function_exists('mcrypt_create_iv') ) {
// Check for version, and OS. Use DEV_URANDOM if OS is not win, or if version is > 5.3
$version = explode('.',PHP_VERSION);
if( stripos(PHP_OS,'win') === FALSE || ($version[0] > 5 || ($version[0] == 5 && $version[1] >= 3)) )
	$salt = substr(bin2hex(mcrypt_create_iv(11,MCRYPT_DEV_URANDOM)),0,21);
else
	// Default to system random function
	$salt = substr(bin2hex(mcrypt_create_iv(11,MCRYPT_RAND)),0,21);
} else {
$characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/.';
$size = strlen($characters);
$salt = '';
for( $i = 0; $i < 21; $i++ )
	$salt .= $characters[mt_rand(0,$size-1)];
}

if( CRYPT_BLOWFISH ) {
$iterations_log2 = floor(log($iterations,2));
if( $iterations_log2 > 31 || $iterations_log2 < 4 )
	die('My terrible error handler is letting you know you have too many, or too few iterations for blowfish');
$hash = crypt($pass,'$2a$'.str_pad($iterations_log2,2,0,STR_PAD_LEFT).'$'.$salt);
} elseif( $iterations > 999999999 || $iterations < 1000 ) {
die('My terrible error handler is letting you know you have too many, or too few iterations for SHA');
} elseif( CRYPT_SHA512 ) {
$hash = crypt($pass, '$6$rounds='.$iterations.'$'.$salt);
} elseif( CRYPT_SHA256 ) {
$hash = crypt($pass, '$5$rounds='.$iterations.'$'.$salt);
} else {
// Fall back to PBKDF2 ?
}

echo $hash;

?>

 

Keep in mind, this is only for hashing, and another snippet would have to be used to parse an existing hash for verification. Here's both steps, for Blowfish only, that assumes access to /dev/urandom exists.

 

<?php

$pass = 'hello world';
$iterations = '08';

// For some reason, the 22nd character gets lost in the resulting digest/salt combination,
// but still affects the hash process, so I've dropped it to 21
$salt = substr(bin2hex(mcrypt_create_iv(11,MCRYPT_DEV_URANDOM)),0,21);
echo 'Salt: '.$salt.' ('.strlen($salt).')<br>';

$hash = crypt($pass, '$2a$'.$iterations.'$'.$salt);
echo 'Hash: '.$hash.' ('.strlen($hash).')<br>';

$parts = explode('$',$hash);

echo 'Extracted Salt: '.substr($parts[3],0,21).'<br>';
if( crypt($pass, '$2a$'.$parts[2].'$'.substr($parts[3],0,21)) == $hash)
echo 'Match found';
else
echo 'Match failed';

?>

 

I've come to the personal conclusion that PHPass is both more flexible, and easier to implement than any native functionality PHP offers. Considering both implement strong password hashing techniques, I would recommend PHPass over native functionality.

Link to comment
Share on other sites

For someone who claims superior reading comprehension you really don't see my point.

Or points.

 

Nr 1. I think phpass is good - I just said there are alternatives that are just as good. How am I not backing that up? I listed a few. There are some cases where you need to download a library and some where you don't.

 

Nr 2. I think this part was pretty rude:

@floridaflatlander

 

Please read the article in my signature, and understand it before trying to give security related advice. Help is appreciated, but when it comes to security, good will can lead to Swiss cheese.

 

 

That doesn't strike you as slightly condescending?

Especially considering florida didn't really say anything except mention Wordpress solution (which happens to be phpass nowadays).

 

To answer the free part - Google is also free, and making billions.

There is a commercial interest in Openwall as well even if it is free.

 

You want more developers? RSA and NIST for instance.

How to implement them? They seem to work well for most people regardless of if you choose crypt(), mcrypt(), bcrypt() or phpass().

Including the many servers who still use PHP 5.1 or 5.2.

 

As for Twofish - it was made because they felt Blowfish wasn't strong enough so someone may want that algorithm to start with.

Is it a must? No, just mentioned it's available.

Link to comment
Share on other sites

Google is free the same way ABC is free. It's free to use search. There are plenty of google products that cost money. If I tell a friend to use gmail, I don't get any money for saying it's a good product.

 

I think you should stop putting words in xpyh's textarea (I couldn't resist) because you're starting to look kind of petty about it.

Link to comment
Share on other sites

1. You suggested crypt, which I have shown is difficult to implement. PHPass implements it for you, and allows a system to fall back to weaker algos if needed. What other solutions have you suggested? mcrypt() is for encryption, not hashing. scrypt doesn't have a PHP implementation, as far as I know, and was initially brought up by me.

 

2. That's your opinion. It wasn't meant to be rude. As I said, help is appreciated, but security is one of those things where bad advice doesn't always become apparent until it's too late. He's posted twice very recently in security-related threads with bad information.

And yes if they get your config file, the order you hash the pw & salt and your db tables you have a sh*t pot full of problems.

This is exactly why we're talking about this. Hashing is used as a defence in worst-case scenarios, and he's saying in a worst-case scenario, you're screwed. That's bad advice, and has no place in this discussion. The article does a very good job of going over the basics of password hashing, and why it's done. If you have a better article to send him to, please post it. Again, bad security advice is a no-no, and I believe you're better off educating yourself (through reading or asking) than trying to contribute something volatile you have little understanding of. Perhaps it makes me condescending, but I'm still giving good advice.

 

3. Google monetizes off their free service through data collection and advertising. You have to pay money to use Google's Ad service... the one that makes them billions. Please, if you want to continue this discussion, avoid trying to make analogies. They don't work. Please explain how Openwall is going to monetize off of a class that's been released to the public domain? No license whatsoever. Openwall may have commercial interests, but those have nothing to do with PHPass or the article linked. If there is some connection, besides them residing on the same web page, please elaborate. The advertising argument is thin as well. There's plenty of opportunity to push their commercial services in the article, but it's not there.

 

"You want more developers?" When did I ask for developers?

 

I think the issue here is that you're simply defending floridaflatlander while trying to appear that you have information to contribute to the topic.

 

Twofish isn't used for hashing, so it's trivial to bring up in this discussion. I tried to point that out, but I guess it needs reiterating. Again, ciphers (along with the mcrypt set of functions) are used for encryption/decryption, which is much different than hashing.

 

Please, let me know if there's anything I can elaborate on. If you're ready to actually discuss the pro and cons of using PHPass vs other packaged solutions vs implementing native functionality on your own, I'd be happy to give my opinion. As of now, I've shown that MD5 isn't 'broken' in a password-hashing sense, and that implementing crypt manually is more complex than using PHPass. If you disagree, please explain why and please use code or sources to support your decisions.

Link to comment
Share on other sites

...if they get your config file, the order you hash the pw & salt and your tables(salt & hashed passwordsdb) you have ... problems.

 

 

5. ......, instead use sha1(md5($password).$password). It's hard to explain why without getting deep into how hash algos work. There's plenty of info out there if you want to dive deeper.

 

Whats the difference?

Link to comment
Share on other sites

That is still not an ideal way to store a password, but it's better than sha1(md5($password)); and here's why, in simple terms.

 

When you use md5($password) you're always going to get a 128-bit result.

When you use sha1(md5($password)), you're always going to generate a sha1 digest based on a 128-bit input.

 

When you use sha1(md5($password).$password), the digest will be generated based on 128bit+however long the password is. This means the number of possible values that sha1 will hash increases.

 

By limiting the amount of values you can put into your sha1() function, you're increasing the chance that a collision will happen. Collisions are generally a bad thing, as it means two different passwords product the same hash, thus two different passwords could work for the same user.

 

Let me know if there's anything I can elaborate on.

Link to comment
Share on other sites

Google is free the same way ABC is free. It's free to use search. There are plenty of google products that cost money. If I tell a friend to use gmail, I don't get any money for saying it's a good product.

 

Without realizing it you're close to my point - you can monetize a free product through branding etc.

 

I think you should stop putting words in xpyh's textarea (I couldn't resist) because you're starting to look kind of petty about it.

I quoted his post verbatim - how is that putting words in his anything.

 

 

1. You suggested crypt, which I have shown is difficult to implement. PHPass implements it for you, and allows a system to fall back to weaker algos if needed. What other solutions have you suggested? mcrypt() is for encryption, not hashing. scrypt doesn't have a PHP implementation, as far as I know, and was initially brought up by me.

For most people any of the previously provided functions (or hash()) would be sufficient. And no, scrypt() is not a php-function.

 

2. That's your opinion. It wasn't meant to be rude. As I said, help is appreciated, but security is one of those things where bad advice doesn't always become apparent until it's too late. He's posted twice very recently in security-related threads with bad information.

And yes if they get your config file, the order you hash the pw & salt and your db tables you have a sh*t pot full of problems.

This is exactly why we're talking about this. Hashing is used as a defence in worst-case scenarios, and he's saying in a worst-case scenario, you're screwed. That's bad advice, and has no place in this discussion. The article does a very good job of going over the basics of password hashing, and why it's done. If you have a better article to send him to, please post it. Again, bad security advice is a no-no, and I believe you're better off educating yourself (through reading or asking) than trying to contribute something volatile you have little understanding of. Perhaps it makes me condescending, but I'm still giving good advice.

It's not a bad article but carrying it around doesn't mean you are the only one who gets to post. If nothing else we got a good discussion going.

You should be above belittling someone for it.

 

3. Google monetizes off their free service through data collection and advertising. You have to pay money to use Google's Ad service... the one that makes them billions. Please, if you want to continue this discussion, avoid trying to make analogies. They don't work.

They work fine and have since way before Jesus Christ.

Please explain how Openwall is going to monetize off of a class that's been released to the public domain? No license whatsoever.

You think they aren't making any profit from branding?

We even touched on Google's way of doing it a second ago.

Openwall may have commercial interests, but those have nothing to do with PHPass or the article linked. If there is some connection, besides them residing on the same web page, please elaborate. The advertising argument is thin as well. There's plenty of opportunity to push their commercial services in the article, but it's not there.

Yes. Even if it was just bragging rights it's in their interest to strenghten their brand. And there is monetary interest here. Not that it matters since my point wasn't that phpass is bad because it's not.

"You want more developers?" When did I ask for developers?

What did you mean then when you asked for more examples?

 

I think the issue here is that you're simply defending floridaflatlander while trying to appear that you have information to contribute to the topic.

 

Twofish isn't used for hashing, so it's trivial to bring up in this discussion. I tried to point that out, but I guess it needs reiterating. Again, ciphers (along with the mcrypt set of functions) are used for encryption/decryption, which is much different than hashing.

 

Please, let me know if there's anything I can elaborate on. If you're ready to actually discuss the pro and cons of using PHPass vs other packaged solutions vs implementing native functionality on your own, I'd be happy to give my opinion. As of now, I've shown that MD5 isn't 'broken' in a password-hashing sense, and that implementing crypt manually is more complex than using PHPass. If you disagree, please explain why and please use code or sources to support your decisions.

You probably won't get this but I still think people can use one of the above mentioned ways to hash their passwords.

Even the encryption ones. I still say it's not about proving who is best or cracking each others passwords. I. Just. Said. There. Are. More. Ways. To. Skin. A. Cat.

Link to comment
Share on other sites

I quoted his post verbatim - how is that putting words in his anything.

 

you say that anyone that doesn't hail Phpass doesn't understand the concept.

[...]

you read books the average person doesn't understand? Great.

You're like the guy who bought a Ford after reading the merchandising from Ford and calling anyone who drives anything else an idiot

For someone who claims superior reading comprehension

 

 

You also keep saying he's being rude, belittling, etc. The only thing he said to floridaflatlander was to read the article and understand it. That is in no way rude. He didn't say "You're an idiot because you haven't read this". He didn't say "You should get off the boards, moron". He said that this person does not understand security, and unless floridaflatlander's job is security, this is not an insult.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.