Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Suppose I'm not able to use bcrypt for legacy reasons. Would a hash of username+password+constant_seed be good enough? What about user_dependent_seed+password+constant_seed? The user_dependent_seed could be a concat of username, account setup date, user id# etc. What hashing algo would you recommend if bcrypt is just not available?


The attraction of bcrypt is that you can tune its work factor to counter increases in computing technology, so that it's very slow to brute-force compared to an MD5/SHA/CRC, all of which are extremely fast to compute. It's counterintuitive, but the idea is that if Joe Blackhat gets your password hash, he's going to spend orders of magnitude more time chewing on it to get a result than if it were hashed with a fast hashing algorithm. Adding more salt to the hash is going to increase its time-to-crack, but swapping SHA1 for bcrypt gets you a future-hardened algorithm that can be adjusted in responses to gains in computing power.


I agree why bcrypt is much, much better. No doubt about that. My question was whether there was something I could do to improve security (even if marginally) on platforms that can't/don't support bcrypt.

> bcrypt gets you a future-hardened algorithm that can be adjusted in responses to gains in computing power.

How would I be able to change the cost factor overtime? I don't store my user's passwords. Should I just re-bcrypt the bcrypted password using a higher cost and in my login_verify code, take that into account? Or is there something else you can do overtime to raise the cost factor?


"How would I be able to change the cost factor overtime?"

One system I built stores the workfactor used to bcrypt the current password un the user table, and allows me to increase the "system workfactor". Every time someone successfully logs in with a lower-than-current-workfactor password hash, it recomputes a new bcrypted hash using the currently known successful login password and updates the users credentials. It means if my user table is ever exposed, all frequently used accounts have up-to-date workfactors for their password hashes, and the "relatively weaker" hashes are for infrequently used (or, in this particualar case, expired subscriptions).


Iterate MD5 several times (i.e. 50 or so). That will introduce a similar "slow" factor (it's not a solution, but a stop gap)

EDIT: I've also recommended using a random salt for each password too, but this is only a layer of security if you're code is not also stolen, then it is simply a slight additional "slow factor"


(I'm not sure why I said MD5... what can I say it was a monday morning :))


If anyone has a comment as to why this is not good advice (it honestly is decent advice if you really insist on not using Bcrypt) then I'd be happy to hear it ;)


Because md5 is stupidly fast, even if you use a thousand cycles. As if that's not bad enough, there are FPGA implementations (http://nsa.unaligned.org/) which are even faster and relatively easy to come by.


Yes, MD5 was a mistake :) I was tweaking our cluster's MD5 implementation so it was stuck in my mind. Just sub in "hash function".

You could up the iteration however much is needed (say, 1000, 10,000).

It's poor security countermeasure, but it was a specific scenario :) The general idea is to combine salting and iteration to produce a poor mans slow hash.

(which works great for software you're distributing for use on random shared architecture a la wordpress - just to give an example)

Use Bcrypt where you can.


> Just sub in "hash function".

That's the crux of the problem. Hashes that are good for fingerprinting files (MD5, SHA-n) aren't good for keeping passwords secure, because they need to be fast. Your idea seems fine, but you're forgetting the "first rule of implementing crypto primitives": don't do it! (http://www.letsyouandhimfight.com/2010/07/14/cl-bcrypt-a-fir...)


Nonsense. I am well aware of the problem with hash functions.

First off; it is not a primitive, but a protocol, it is still a bad idea to design those yourself. But they are not; they are getting the advice of an expert.

Secondly; this is in a specific scenario where you are left only with the fast digests (shockingly, this is still a common situation). Introducing an "artificial" slow factor is accepted practice.

Thirdly; this is definitely not my idea. The iteration suggestion was from tptacek who months ago answered a similar question to this with something along the lines of "if you must insist on using fast hashing for gods sake iterate it a number of times" (I can't find the quote off hand, it was some time ago, but I entirely agree). The rotating random salt is an old old idea.

It's very easy to recite the mantra "always use bcrypt, follow the first rule of crypto, digests are evil", but it's even harder to use that knowledge in practice, I find. :)


One way hash schemes are absolutely primitives. See http://en.wikipedia.org/wiki/Cryptographic_primitive for clarification.

You can introduce slowing factors like seed values and iterations (bcrypt uses both) but they're a bad idea if you're doing it yourself. For example, your initial estimate of 50 iterations is at least a couple of orders of magnitude out. How many is safe? 10,000? 100,000?

BTW, I'd be interested to know exactly what this mythical situation is where you're handling user accounts, but don't have access to one of the existing bycrypt implementations (C, Ruby, Python, PHP) and can't compile your own.


It's not really a primitive, but I'll concede the point. Similarly the one about 50 iterations, that was somewhat silly (there is a reason I have that number in mind, but I won't bore with details).

However. Mythical situation? Try a good portion of shared PHP hosting; why do you think the most popular software in the world (i.e. stuff like Wordpress) still supports MD5/Sha hashing?

I realise this is not a problem you may have come across before; but don't imagine it does not exist :)


So use PHP-ass: http://www.openwall.com/phpass/. It's integrated into Wordpress and does all of that stuff, including falling back to md5 if you have a really crappy host.

But really - it's just another reason not to use PHP, and not to have a crappy webhost. You could probably say much the same things about backups, app security, bad UI or design. But for most people, don't do that is apparently not a good enough answer.

Update: Just looking into how Django stores passwords, and it does much the same thing (although it falls back to SHA-1, rather than MD5). There was a push to use bcrypt a while back, but it got marked wontfix, due to "backwards compatibility issues". Sigh.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: