Hacker News new | ask | show | jobs
by encoderer 5477 days ago
thomas, another programmer in the office just asked this question which I haven't a good answer for: Instead of using a known salt stored in, say, a config file, or prepended to the stored hash, why not derive the salt from some substr of the supplied password? His example was, salt would be concat(left3chars, right3chars). And so when the user inputs his password into the system, you just derive the salt using that same consistent algorithm, and supply both that derived salt and the password into the algorithm.

My only answer was "It's always a bad thing to be clever with crypto, just do it by the book" but he asked for more and I couldn't give him a sound debunking (or an authoritative endorsement).

I build systems -- and do it very well -- and all I know about crypto is what I've had to learn to implement other peoples crypto systems.

4 comments

The purpose of a salt is to randomize the password hashes so you can't easily precompute them. A "salt" derived from the password itself isn't random; it's deterministic. Salts don't add much security, but they do defeat precomputation. The scheme your coworker proposed doesn't do that.
I'm not going to lie and say I was already thinking that, but I did have a notion that, in such a scheme, if somebodies passowrd was "1111111" then your salt + password would be the unimpressive 1111111111111.

But if you don't mind a follow-up, wouldn't it still defeat rainbow tables? Why not?

In your scheme, if your password is "apple scrapple", the hash value is always going to be (say) "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15". An attacker can precompute that and just use text search to find everyone with the password "apple scrapple".
They would still need a rainbow suited to the algorithm that is used to create the salt, or to have it large enough to contain the password+salt value within it. Still means that the entire database can be used with the same rainbow table, however.
Generating the salt from the password completely defeats its purpose. Users with the same password will have the same salt, and therefore the same hash. In your example, an attacker could find which users chose the password "password" by running your hashing algorithm with a salt value of "pasord". Your database would be wide open to rainbow table attacks.
Right, so then the idea is that if they get your DB dumb, and see this salt scheme in your code, they can compute a rainbow table using it and now they have cracked all your passwords in the time it would take to brute force one (well, not really, because it's not as if they'd have to brute force the entire keyspace before they got to the one password they're trying to break, but I think I'm onto the right idea about shrinking down the magnitude of the problem)

But what it WOULD do -- which is what to be honest tricked me about the concept -- is that it would still offer protection from a precomputed rainbow table that knew nothing of your sheme to derive salt from the password. (eg, the rainbow tables that are publicly searchable right now)

Effectively you are still using a hash without a salt, it's just that you've created a new, non-standard, hash function.
I like that explanation.
A variation on this is to use a random salt with each password that you store. Your auth process then becomes: 1. check the username 2: if the user exists, prepend the salt stored in the user row to supplied password, check against stored hash.

At the very least, you will make it harder for someone to crack all of your passwords by computing one table with a single salt.

If you are using "salts", you have to make them random for each stored password. But if you are doing this securely, you don't care about this detail, because the bcrypt library took care of it for you.
I might have read your question wrong, but the whole point of this thread is that passwords stored by hashing with a general purpose hashing algorithm can be easily brute-forced nowadays. Salting just turns your password into a different string and has no substantial effect on the brute force attack. (The attacker is already trying all possible strings.)