2

I have been looking at upgrading the password hashing security of one of my applications as I have been reading up about brute force attacks being considerably faster then they used to. Currently I am using sha1(md5($password)) and I see the benefits of using bcrypt + salt. My question is, Would it be any more secure if I were to do the following:

Scenario 1:

$password -> sha1 -> bcrypt -> sha1
// This would enable me to keep all existing passwords and just 
// regenerate all the hashes without waiting for the user to re login

Scenario 2:

$password -> bcrypt -> sha1
// I would have to add an extra column for the new hash until every
// user has logged in but the hash will still be sha1.

Would any of these two increase the security of the hash at all? I am no cryptographic master, far from it, I would just like a simple explanation as to if it would work, if not, and why.

Thanks

EDIT

After a little more reading, it seems that bcrypt is favoured because of its slowness in that i makes the cpu/gpu work longer before the hash is generated.

In the case of sha1 vs bcrypt, sha1 is roughly 300000 times faster then bcrypt. Which begs the question, if bcrypts advantage is slowness, surely a recursive hashing function which uses sha1 300000 times would be as secure as bcrypt?

I made this function as an example:

function bsha1($data, $salt) {

$hash = $data;

for ($i = 0; $i < 300000; ++$i) {

$hash = sha1($hash . $salt);

}

Provide it with a salt and itll return a sha1 hash where every iteration is a hashed hash and salt. This takes approximately the same ammount of time as bcrypt. Would this be as secure?

jww
  • 97,681
  • 90
  • 411
  • 885
Ozzy
  • 10,285
  • 26
  • 94
  • 138
  • Better off seeding and salting a password before eg: `md5(md5(uniqueid/seed).my5(password).md5(now()).md5(seed))` at the end of the day all in your suggestions you're just chain encrypting. and sha1 is easily broken tbh (as is md5 i'm only using it as an example) implemeting a randomness on password generation is the best I do it using the signup date + a seed key for each user + unique userid chain them all together in multiple passes then one master pass. its still chaining encryptiong but for example "password" becomes "1230982348762password89134598712390874" so the length increases – Dave Apr 30 '13 at 11:12
  • 1
    @Dave: Please do not suggest to roll your own. Rolling your own leaves you alone. Instead take what has is considered working by the community, that will not leave you alone in case research finds out that some parts are flawed or even broken. – M8R-1jmw5r Apr 30 '13 at 11:26
  • 1
    Its not exactly rolling your own its basically doing exactly as robert has suggested. Also FYI the example above is exactly how its done in vbulletin. – Dave Apr 30 '13 at 11:27
  • @Dave: Yes, and for that we love to process vbulletin dumps - it's so damn fast thanks to MD5 to get results. – M8R-1jmw5r Apr 30 '13 at 11:43
  • as said in the initial post md5 was purely for example less for me to type – Dave Apr 30 '13 at 11:44
  • @Ozzy: After your edit: And no again, rolling your own is *not* a good idea. Even you now understood that stretching / expanding the hashing is a way to go, you don't need to do it your own, because this exists already so take that what works. Also this is not as secure because it takes longer. You better invest that runtime on more cycles than less cycles by using the compiled binary code that exists in PHP. Also you need to think about how to put a random salt in there as it is crucial to have one salt per each hash something your `bsha1()` mock does not take care of. – M8R-1jmw5r Apr 30 '13 at 11:46
  • @Dave: But that does not explain why Vbulleting is lazy to adopt to security standards. Even Wordpress did when they realized years ago that they made a mistake by choosing [Phpass](http://www.openwall.com/phpass/). What are you trying to defend? The worse? – M8R-1jmw5r Apr 30 '13 at 11:48
  • I'm defending the process of salting and seeding which is exactly what I described. and is exactly what is described below and voted up! – Dave Apr 30 '13 at 11:50
  • @Dave length of the password is irrelevant, since the password is derived from the original password, its still easy to crack. and robert's answer is sort of crap, frankly. salt + SHA hash is not secure in the day and age of gpus and custom hashing ASICs, thanks to bitcoin. – Peter Elliott Apr 30 '13 at 11:50
  • wrong. Brute forces work by testing passwords a b c d aa bb cc etc etc so the longer the input chain the longer it takes to crack the password Just for example goto http://www.passwordmeter.com/ type in password. Then try it again at passwordpassword. Lengthening the password increases the amount of time before a bruteforcer will hit that combination. Couple that with random seeds and salts unknown to anyone and not general words so someone can use password and still be fairly safe if you're salting and seeding in `:~@P}{!"£^*&£$^` etc – Dave Apr 30 '13 at 11:54
  • @Ozzy your second example is what PBKDF2 is doing at it's core... so rather than writing your own you should use it, or stick to your original plan of using bcrypt. Why do you want to write your own hashing scheme, instead of using something existing? – Peter Elliott Apr 30 '13 at 11:54
  • 1
    @Ozzy - One cannot say, that SHA-1 is x-times faster than BCrypt, because BCrypt hash a cost factor, that determines the necessary time. This cost factor is the important point. What you do with iterating is similar, but BCrypt does it better. For example it reuses the salt and the original password in each iteration, and it is built in a way to use more memory, to make it harder to brute force with GPU's. – martinstoeckli Apr 30 '13 at 12:01
  • @Dave: The only proof you give us is that the "Passwordmeter" is not aware of wordlists and permutations usage in nowadays brute-force attacks. As you didn't suggest to take at least a password of 34 pseudo-random characters (and why not from the Unicode range?) I must say I do not think you really fight for the better. It sounds a bit that you are trying to defend the worse. Why with such an important topic? – M8R-1jmw5r Apr 30 '13 at 12:11
  • @Dave misread your comment, thought it was refering to final output, sorry about that – Peter Elliott Apr 30 '13 at 12:13
  • your missing the point again @M8R-1jmw5r i'm using EXAMPLES which means do not follow strictly as gospel but use as guidelines you CAN use unicode characters if you want as your seed/salt characters it can be anything you like, you CAN use any length of passwords before you do the actual encryption. For example in the system I'm working on at the moment the pre-encryption input password is padded upto 500 characters long! Dictionary and word lists are useless as we're seeding and salting with random strings with input lengths that long i could just single pass md5 and it wouldn't brute force! – Dave Apr 30 '13 at 12:38
  • Don't believe me? Try it and see. Hell use John the ripper or even the gpugp based md5 crackers. – Dave Apr 30 '13 at 12:39
  • @Dave - There is one flaw in your concept. We hash passwords to protect already stolen password databases. If the attacker knows those hashes, but has no control over the server (SQL-injection), then your method works, because you are using a salt, and a form of pepper (a secret known to the server). If the attacker has control over the server, then he knows the secret as well, and only the necessary time to calculate the hash will protect the passwords. Using MD5 or any SHA-* functions is ways too fast, nowadays one can calculate about 8 Giga MD5 hashes per second with common hardware! – martinstoeckli Apr 30 '13 at 13:09
  • But the same can apply to almost any encryption pattern if enough information and enough cycles are applied everything is vulnerable look at distributed.net for example The issue isn't so much secure hashing (though obviously thats important) but its making it computationally difficult enough to reduce the probability of matching the hash through trial and error to make it in efficient/not worth it. Generally someone brute forcing 100 passwords will take the first 10 rather than wait months for the odd additional 1. If it takes 10 minutes to get 10 but another 3 months for 1 more – Dave Apr 30 '13 at 13:15
  • 1
    @Dave - In your example you used MD5 5 times (yes i know it's only an example, but a good one...). With this algorithm we could calculate over 1 Giga hashes per second, that means a whole english dictionary in a fraction of a milli second... With BCrypt you couldn't do that, a senseful value is 1 hash per milli second, so why not use it(?), it's even easier to apply. – martinstoeckli Apr 30 '13 at 13:25
  • Indeed and bcrypt would be the better option (although its only blowfish based afterall) but the underlying principals would still apply be it mcrypt,bcrypt,md5 whatever still append salts and seeds (peppers you called them) and if you ensure they use non alphbetic characters your exponentially increasing your keyspace from say 92? alphanumeric chars to a full possible combination. Your increasing your key space entropy so to speak. – Dave Apr 30 '13 at 13:28
  • @Dave - Yes, as long as the pepper or the secret is not known, it can really protect weak passwords. I tried to sum it up in a [tutorial](http://www.martinstoeckli.ch/hash/en/index.php). – martinstoeckli Apr 30 '13 at 13:37
  • The ideal way would be to generate the pepper based off hardware information in the server (there's quite alot of industrial stuff works off this secureid etc) Thing to remember is users are stupid they'll always go for the most simple password possible. So just straight encryption of that will never be safe. Appending to that input string with known or / random then saved strings increases the complexity ^ times. – Dave Apr 30 '13 at 13:48
  • @martinstoeckli i like that little site explains it much better than I've been doing :) – Dave Apr 30 '13 at 14:10
  • @Dave: Why don't you read what the author of jtr has written long time ago about password hashing? Don't listen to me, listen to those who author the programs you like. The best suggestion *I* can give you is that you should stop defending the worse. – M8R-1jmw5r Apr 30 '13 at 14:25
  • @M8R-1jmw5r the best suggestion I can give you is that you read before you comment as you've clearly been talking without reading what I've been writing in the first place. – Dave Apr 30 '13 at 14:31
  • Also see Openwall's [PHP password hashing framework](http://www.openwall.com/phpass/) (PHPass). Its portable and hardened against a number of common attacks on user passwords. The guy who wrote the framework (SolarDesigner) is the same guy who wrote [John The Ripper](http://www.openwall.com/john/) and sits as a judge in the [Password Hashing Competition](http://password-hashing.net/). So he knows a thing or two about attacks on passwords. – jww Oct 12 '14 at 01:55

4 Answers4

12

You best upgrade to password_hash().

As it is likely you are not using PHP 5.5 yet (I assume maybe you are already for testing purposes at this time), you can use the PHP userland implementation of password_hash() also written by Ircmaxell for PHP 5.3+.

To upgrade the password hashes on login, you fetch the hash from the database and test first against the new hashing. If it returns FALSE, you test against the old hashing. If that returns TRUE, you re-hash the password with the new new hashing and store it back into the database.

Combining or chaining multiple hashes after each other - and I fear I read that in your question - is a total stupidity you should never consider. Hash algorithms are not compatible to each other and using a hash on a hash that way is doing it wrong: sha1(md5($password)) and the like effectively reduce the output space which makes it easier to attack - something you want prevent in the future.

So take the new password hashing API that there is in PHP and sleep well.

M8R-1jmw5r
  • 4,896
  • 2
  • 18
  • 26
  • 1
    In this special case you could even test the beginning of the hash-value with '$2y$', so you would now immediately if the hash was generated with BCrypt. – martinstoeckli Apr 30 '13 at 12:03
  • @martinstoeckli: I'm pretty sure the password_hash API does this already for you, so yes and no :) – M8R-1jmw5r Apr 30 '13 at 12:04
  • I don't totally agree with the "reducing output space" reasoning, but otherwise this is absolutely the best answer. – Peter Elliott Apr 30 '13 at 12:16
  • 1
    @PeterElliott: Brute-forcing SHA against MD5 plains works. The more SHA, the better, e.g. SHA2, SHA3. SHA* has always more output bits than MD5 provides as input bits. That effectively reduces the output bits as well, because there is now a limited set of input values compared to the theoretically unrestricted input set the hash has been originally designed for. – M8R-1jmw5r Apr 30 '13 at 12:25
  • @M8R-1jmw5r - Only hash-values created with `crypt()` (used internally by the API) contain this "header". If you called `sha1()` directly, the API has no chance to recognize the used algorithm. That's why i wrote "In this special case", the old hash-value does not contain the header, but the OP knows what algorithm was used. – martinstoeckli Apr 30 '13 at 12:54
0

neither scenario gives you much of a security margin over just bcrypt. That said, bcrypt is absolutely the way to go as far as a hashing algorithm that will resist brute forcing, as with a sufficiently high cost factor, it will take a much longer time to hash than any SHA-based hashing scheme.

Saying all that, Scenario 1 may be the way to go, as you are able to secure your db now instead of piecemeal as users log in. Despite what M8R-1jmw5r says in his/her answer, combining hashing algorithms doesn't give you any extra security, but it also won't really impact your security negatively.

Peter Elliott
  • 3,273
  • 16
  • 30
-2

You can use any standard hashing algorithm, but being standard hashing function they can be backtracked and there is a potential security risk.

You better go with any hash functions but combine it with salt with your personal keys. here is link

http://www.php.net/manual/en/faq.passwords.php#faq.passwords.fasthash

BK004
  • 382
  • 2
  • 10
  • No, you better use a hashing function that is dedicated to password hashing. – M8R-1jmw5r Apr 30 '13 at 11:28
  • yeah right but salt will add some extra security @ M8R-1jmw5r – BK004 Apr 30 '13 at 11:30
  • There is no extra in security. Whenever you pick on the topic (which you should do from time to time), you then need to come to the state of the art, not drop behing. Security is a process, and part of it is staying up-to-date. Better suggest an API that is dedicated to password hashing in PHP, even if it is the one that worked properly already with PHP 3/4. And that is ages ago. – M8R-1jmw5r Apr 30 '13 at 11:32
  • http://www.php.net/manual/en/faq.passwords.php#faq.passwords.fasthash @ M8R-1jmw5r – BK004 May 02 '13 at 06:39
-3

Short answer is yes it would help. However the long answer is no because SHA-1 and MD5 are just weak hashing algorithms now. It would be better for you to just go with SHA-2 algorithms or even wait a little longer and go directly to SHA-3.

The problem is in the hashing function. Three layers will definitely stop someone, but honestly most of the time one layer is enough to get most people to not even bother. If someone is very intent on getting in I would use SHA-2 at the very least other wise you should be fine with what you have.

EDIT::

Ok so to clarify the above. Using SHA1 with Bcrypt is not necesarilly the best way to go. I would use SHA-2 algorithms with bcrypt instead, this would give you more security than using the SHA-1. Also by layers I mean the Bcrypt is one Hash pass the SHA-1 is one Hash pass the second SHA-1 is another Hash pass. I really don't understand why this is wrong? Sorry for the difference in semantics about the layers.

EDIT2::

$Password -> Bcrypt -> SHA-2 or Bcrypt(SHA-2($Password)) Where SHA-2 is one of the SHA-2 family of hashing algorithms.

Code to be more clear than Bcrypt with SHA-2 instead of SHA-1.

Nomad101
  • 1,688
  • 11
  • 16
  • 1
    bcrypt is not a "weak hashing function", and recommending someone use SHA2 over it in a password hashing scheme is a bad idea – Peter Elliott Apr 30 '13 at 11:16
  • @PeterElliott MD5 and SHA-1 are most definitely weak hashing algorithms. which is why they were dropped from being used on the standards for SHA-2 and now going to be SHA-3. So how exactly am I wrong? Also why on earth would using SHA-2 be a bad idea? Do you know of anyone with a supercomputer that can crack the hash? I however, have a computer that is capable of cracking both MD5 and SHA-1. – Nomad101 Apr 30 '13 at 11:18
  • @Nomad101: You are wrong because this is not the known way on how to do password hashing nowadays. Also I wonder if you really understood what the OP asks for so the answer might be misleadingly saying that *"hashing a hash would help"*. I bet you do not think so, however your answer can be read as such. – M8R-1jmw5r Apr 30 '13 at 11:28
  • @M8R-1jmw5r I am confused as to why, He asked for a secure way to do password hashing. A SHA-2 HASH would be perfectly suited for doing that. Also in terms of performance there is little to no difference. So what exactly would be wrong with using SHA-2, considering I have used it in websites before? – Nomad101 Apr 30 '13 at 11:30
  • Also adding layers to the Hash is never a bad thing. Nor do I say that it is, All that I am saying is to change SHA-1 and MD5 with SHA-2. What exactly is wrong wit that? – Nomad101 Apr 30 '13 at 11:32
  • @Nomad101: If you say so, then I say that this is not enough. See as well http://php.net/faq.passwords – M8R-1jmw5r Apr 30 '13 at 11:33
  • @M8R-1jmw5r if you can brute force a SHA-2 512 bit or 256bit hash we are all in a lot of trouble seeing as it is currently the standard enforced throughout our government for sensitive information. Also I never said to touch Bcrypt. So using Bcrypt along with an SHA-2 hash is not enough? what are you trying to secure? and you are trying to say that SHA-1 with Bcrypt is more secure? I am actually trying to figure out where I went wrong here. – Nomad101 Apr 30 '13 at 11:36
  • 1
    @Nomad101: What do you mean by using the term *Layer* in your answer? I could not find any clear reference to it in the domain of cryptographic hashing into which the SHA-* family of hashes fall into. And as you might know, you can bruteforce any hash, the expense is interesting here. You are suggesting hashing algorithms which are designed to work *fast*. This is the opposite of what you try to achieve for password hashing. – M8R-1jmw5r Apr 30 '13 at 11:39
  • 1
    SHA-2 is too fast to be used in a password hashing scheme, as things like bitcoin (which revolves around brute forcing SHA256, essentially) means a lot of research is being poured into doing SHA256 as fast as possible. Hashing algorithms aren't really designed to make passwords secure the way bcrypt is, and it's pretty clear you have no idea how they are supposed to work. – Peter Elliott Apr 30 '13 at 11:41
  • I dont get what you mean by that I never said to not do Bcrypt? I actually continually say to use it? Also are you really trying to tell me that SHA-1 is safer than SHA-2? The OP said that he was using this: sha1(md5($password)) Then was going to use this: $password -> bcrypt -> sha1 All I was suggesting was to change SHA-1 with SHA-2. that is litterally it. – Nomad101 Apr 30 '13 at 11:43
  • @PeterElliott To be honest that was uncalled for seeing as you keep saying I am telling people one thing when I am not. Salting with SHA-2 is more secure and a overall better hash than SHA-1 would produce. So what you say makes absolutely no sense. I never said to not use Bcrypt, nor have I said anything but to use it. So I have literally no idea what you are talking about. – Nomad101 Apr 30 '13 at 11:55
  • @Nomad101: Thanks for your edit, but you can not define *Layers* by saying that you mean by *Layer* this is a *Layer*. Why don't you use the correct terms, I think you mean hash? And why do you ride the pony to combine bcrypt with another hash? What should give this? Does it make it better? I'm pretty sure it makes things worse, that is why I ask. – M8R-1jmw5r Apr 30 '13 at 11:57
  • "if you can brute force a SHA-2 512 bit or 256bit hash we are all in a lot of trouble seeing as it is currently the standard enforced throughout our government for sensitive information." implies you have no idea how SHA256/SHA512 are actually used vs used in a password hashing context. your answer up until your edit reads like "just use SHA2 and you'll be fine", and it still sort of reads that way – Peter Elliott Apr 30 '13 at 12:01
  • I specifically didn't want to change the original to show more information about what this was about. Also "I would use SHA-2 algorithms with bcrypt instead" Direct quote from the edit I am not really sure how much more clear I could possibly get. – Nomad101 Apr 30 '13 at 12:04
  • @Nomad101: Please add example code so it is better visible what you actually mean. – M8R-1jmw5r Apr 30 '13 at 12:47