Live data from Hacker News

One way to fix your rubbish password database

blog.jgc.org

61–70 of 94 posts

Re: One way to fix your rubbish password database

#62
post #59

The variable names in this article are throwing me off. Is there a special significance to the subscripts and superscripts in the variables?

The subscript i denotes that the variable belongs to a single user i. The tick at the top is pronounced 'prime' and is used to differentiate between versions or iterations.

Re: One way to fix your rubbish password database

#63
post #7

Earlier quoted context omitted.

No. I don't believe there's any disadvantage to this. An MD5 hash is a 128 bit random number; it's 16 fully random characters, better than almost any human password.

An MD5 hash is not a random number; it is generated from some text string. It's possible that bcrypt(salt + MD5(text)) opens you up to collision attacks that are not possible with bcrypt(salt + text). It seems unlikely that it would open you up to attacks that are not possible with md5(text) but MD5 is not a random number so I'm not too sure.

The best means of colliding MD5 seems to require one collision block plus some extra "birthday" bits, all of which are controllable by the attacker. [1]

The idea is that you have two messages, m1 and m2, or m1 and m1' if you prefer, and you vary bits in both until you get a collision. You need some area of m1 and m2 that doesn't matter for the application, so that you can change those bits and find a collision. Since all bits of m1 are supplied when entering the password, you have no ability to modify it without getting the user to change his/her password.

If you could collide any arbitrary m1 as it's given to you, then attacks like fake certs with signed MD5 hashes could create the fake cert after submitting it to the CA and getting the signed cert back, rather than before.

Also, the collision process requires knowledge of m1 so you can see the intermediate hash states. If you know m1, the password/passphrase, why are you trying to find a new m1' that hashes to the same value rather than using the pass you already know?

An attack of concern for using MD5 as a password hashing step would be a first preimage attack. [2]

[1] https://www.google.com/search?q=md5+collision+block+birthday... (first link at present is http://www.win.tue.nl/hashclash/SingleBlock/ )

[2] http://en.wikipedia.org/wiki/Preimage_attack

Re: One way to fix your rubbish password database

#64
post #53

Earlier quoted context omitted.

I'm still trying to learn this stuff, but I do not understand fundamentally how bcrypt(salt + MD5(text)) could be worse than bcrypt(salt + text). What if everyone's plaintext password was already a string of characters identical to some MD5(text)? If bcrypt(salt + MD5(text)) could be bad, then doesn't that mean bcrypt(salt + text) could be bad too?

If you compose hash functions, you get the union of possible collisions. Let's say that "foo" and "bar" are two distinct passwords that have the same MD5 hash. Then bcrypt(md5("foo")) == bcrypt(md5("bar")), regardless of how bcrypt("foo") compares to bcrypt("bar"). By pre-hashing with MD5, you have added possible collisions that weren't there previously, and those collisions remain regardless of how many more hashes…

Let's say that "foo" and "bar" are two distinct passwords that have the same MD5 hash.

As a practical matter, we can basically say that never happens. Certainly not for passwords that are user selected and not designed to collide. And since the hash itself is hidden by bcrypt, the attacker won't know md5("foo") even if they were inclined to find a "bar" with the same hash.

Re: One way to fix your rubbish password database

#65
Even if you run a bad codebase that just uses unsalted MD5 and you don't want to add a new crypto algorithm:

Couldn't you just run your whole database through X more rounds of MD5 and do the same in your authentication function?

That way, script kiddies couldn't use precomputed rainbow tables they downloaded somewhere off Bittorrent.

Each additional round will also reduce the speed of a brute force attack while still keeping the changes to the codebase will be pretty small.

Unless there are rainbow tables for a certain number of MD5 iterations, it would be a start...

Re: One way to fix your rubbish password database

#66
post #55
post #53

Earlier quoted context omitted.

If you compose hash functions, you get the union of possible collisions. Let's say that "foo" and "bar" are two distinct passwords that have the same MD5 hash. Then bcrypt(md5("foo")) == bcrypt(md5("bar")), regardless of how bcrypt("foo") compares to bcrypt("bar"). By pre-hashing with MD5, you have added possible collisions that weren't there previously, and those collisions remain regardless of how many more hashes…

We're not pre-hashing with MD5. The MD5 was already there. It's the only source text we have. The proper comparison here isn't MD5+bcrypt vs. just bcrypt — it's MD5+bcrypt vs. just MD5. So any collisions that MD5 causes are immaterial — they'd be there either way. It seems to me that the most obvious problem is that you get two chances at colliding — once with MD5 and once with bcrypt. But bcrypt is not known to be e…

> It seems to me that the most obvious problem is that you get two chances at colliding

Yeah, that's all I'm saying. I was answering a question about being "fundamental worse," and fundamentally, there are now two sources of potential collisions instead of one. In theory, that's twice as insecure! However, the practical effect is unlikely to rise above absolute nil anytime soon.

Re: One way to fix your rubbish password database

#67
post #65

Even if you run a bad codebase that just uses unsalted MD5 and you don't want to add a new crypto algorithm: Couldn't you just run your whole database through X more rounds of MD5 and do the same in your authentication function? That way, script kiddies couldn't use precomputed rainbow tables they downloaded somewhere off Bittorrent. Each additional round will also reduce the speed of a brute force attack while still…

I think the conventional wisdom is that you should not re-invent security. I am slowly learning this, but the give-away seems to be questions that start with "Couldn't you just..."

Re: One way to fix your rubbish password database

#68

I used this strategy years ago (2002) to migrate plaintext passwords in a site with 50k+ users. In fact, I built this into the system so I could do arbitrary migrations between password encodings whenever I felt it was necessary. It works well.

Ruby and Django could do well to have this type of strategy baked in. This way you update your configuration and the passwords are immediately upgraded.

Re: One way to fix your rubbish password database

#69
post #65

Even if you run a bad codebase that just uses unsalted MD5 and you don't want to add a new crypto algorithm: Couldn't you just run your whole database through X more rounds of MD5 and do the same in your authentication function? That way, script kiddies couldn't use precomputed rainbow tables they downloaded somewhere off Bittorrent. Each additional round will also reduce the speed of a brute force attack while still…

I think the conventional wisdom is that you should not re-invent security. I am slowly learning this, but the give-away seems to be questions that start with "Couldn't you just..."

It also was conventional wisdom that banks were too big to fail ;)

Are there any actual arguments against using this as an 'easy' fix to the precomputed rainbow tables scenario? Multiple rounds of a cipher seem to be a relatively common operation in crypto and have helped other old ciphers. One of the more prominent ones would probably be the move from DES to triple DES.

I guess dictionary attacks on GPUs would still be easy enough, even with more iterations, but anything that isn't directly in a dictionary might benefit quite a bit from multiple iterations.

It's not as good as actually using proper crypto rather than hashing algorithms that were designed to be fast, but it seems like an easy to implement low-risk solution.

Re: One way to fix your rubbish password database

#70
post #62
post #59

The variable names in this article are throwing me off. Is there a special significance to the subscripts and superscripts in the variables?

The subscript i denotes that the variable belongs to a single user i. The tick at the top is pronounced 'prime' and is used to differentiate between versions or iterations.

Is that called "prime" by most people? I've always heard it just pronounced "dash", as in "s-dash" or "f-dash".
Post reply on HN