5 ms·
I certainly get why a slower hash would curb brute force attacks, but when I'm talking about unique salts, slowing down the hash is not the purpose I have in mi
by paulgb 17y ago
I certainly get why a slower hash would curb brute force attacks, but when I'm talking about unique salts, slowing down the hash is not the purpose I have in mind.
If you have a table of 32 million hashed passwords with no salt (or they have the same salt and you know what it is), you can try a bunch of combinations, take the resulting hash, and look it up in the hashed password database. If you try the password "foobar" and any user has the password "foobar", you've found a username/password pair. Because there are 32 million potential matches, your chances are pretty good of eventually finding a bunch of matches by iterating over a bunch of potential passwords.
On the other hand, if you have a table of 32 million hashed passwords and salt combinations, where the salts are unique, you have to check the hash of "foobar" in combination with every user's salt before you can say that no user has the password "foobar". This is 32 million times slower, which is a significant difference regardless of the speed of the hashing algorithm.
If you want to brute force a particular user's password, the unique hash doesn't matter, but if you want to maximize the number of username/password pairs you can get, it seems to me like it would.
- tptacek 17y agoEvery time I bring this up, which is often because it is, apparently, all I ever talk about here, people misconstrue what I'm saying as some kind of argument against "salted" hashes. It is true that not even bothing to randomize your hashes is worse than doing so. But when we're talking about degrees of grave badness, I stop being super interested in the conversation. If, for reasons passing my understanding, you are attached to the idea of using straight SHA1 to hash passwords, iterate SHA1 1000 times. That takes 2 extra lines of code (the opening and closing of the for loop) and significantly improves your security.
- paulgb 17y agoI'm not misconstruing your argument as against salted hashes, but as downplaying the advantages of using a unique salt over an install-specific salt (not sure that's the best term, but I'm referring to the type of salt you might find in a config.py file). Let me put it this way: give me a database of 32 million username/password_hash combinations and the hash(password) function used and I can give you a valid username/password combination fairly quickly. Even if the hash function takes 10 seconds, because chances are one of those 32 million users has used "password" as a password, and it will only take me 10 seconds to compute the hash and find out which ones did. If instead you give me 32 million username/password_hash/salt combinations, and the hash(password, salt) function used, just to list the users who have the password "password" will take 10 years.
- tptacek 17y ago"Salts" have been password-specific since Ken Thompson invented them in the '70s. We're not talking about different approaches: the approach you're talking about is unsafe. The attack you're talking about --- searching for a radically reduced set of passwords --- is so fundamental to password security that you don't need any crypto to do it. Just open 50 concurrent connections to the login page and rip through the user list. At the same time, with the default BCrypt cost factor, just doing the password 'password' takes 1000 hours against a 32MM row data set.
- paulgb 17y ago> "Salts" have been password-specific since Ken Thompson invented them in the '70s. Thanks, that's where my misunderstanding was. I've seen "salt" used (apparently, improperly) in cases where the hash is the same for all passwords. Even the wikipedia article seems to imply that use case. The other part of my misunderstanding was that I was thinking of BCrypt as a deterministic function. Looking at an implementation, it looks like multiple calls to BCrypt::Password.create with the same value can result in different values, unlike how sha1($x) = sha1($x) for any $x.
- DenisM 17y agoI've read your explanation of this problem several times in the past and only now I figured out (I think) the problem you are pointing out. This seems to be substance of your argument, as I understood it: The computational expense of a brute-force attack against a hash is the lesser of (hash length, text length). Well-known hash functions (md5, sha*) are optimized for large blocks of text, which leads to two properties: 1) they are made fast 2) them being fast is not a problem - if the text is long the strength against the brute-force attack is determined by the hash length which is very respectable for sha256 or even sha512. However, the passwords themselves are small - the typical password is 8 characters and assuming 7 bits per character you're looking at search space of 56 bit, at which point it doesn't matter if your hash is 64, 128 or 512 bit because your strength is 56 bit. The search space can be further reduced by accounting fr various password selection biases, for example phonetic bias, tack-number-at-the-end bias, keyboard layout bias and so on. To deal with small search spaces we need algorithmically slow hash functions - their slowness is not a problem because text is small, but it's a benefit against the brute-force attack.
- tptacek 17y agoYes. Think also of it this way: poor user password selection (and here we mean "ugh&8eat" is a weak password) sabotages the complexity of the attack, and adaptive hashing (like SCrypt) fixes that problem algorithmically. Which is how it should work. Users shouldn't have to pick absurd passwords when the computer can do a better job of obscuring their password. (Note: "them being fast", for "them" in SHA1, SHA256, etc, is not even considered a "problem"; it's considered a "huge feature", because these things are protecting individual data packets. It just happens that this primitive by itself is not useful for protecting passwords.)
- deleted 17y ago[deleted]
- frisco 17y agoMy understanding was that hashing a hash was stupid because you've effectively limited your attacker's search space. That is, in the beginning the password or pass phrase can be any length (probably up to 255), but after hashing you've restricted it to a known length composed of known characters. Therefore, you've decimated the overall search space. It seems like iteratively rehashing your hash 1000 times would make things significantly more insecure.
- tptacek 17y agoA SHA1 hash is, what, 160 bits long? That's better than most AES keys. Nobody attacks passwords by directly attacking the SHA1 algorithm.