Jump to content



Photo

Why Can't You Hash a Password Multiple Times

password hashing md5 multiple sha1 sha256 php

  • Please log in to reply
56 replies to this topic

#16 +Xinok

Xinok

    Resident Reresident

  • Joined: 28-May 04
  • Location: Shikaka
  • OS: Windows 7 x64
  • Phone: Galaxy S3 (Wicked)

Posted 18 July 2013 - 01:23

do u even read though?

So you're going to make a rainbow table of 32 character hashes? Seeing as it took 4 years of clustered computing to make the NTLM rainbow tables up to length 12, you're just talking straight out your arse. Yes I agree using salt is the best way to do it, but for the for-seeable future, 32 character or even longer length rainbow tables will not be appearing.

 

It sounds like you don't understand. This is how you would generate a hash table of MD5 hashes:

 

MD5(password) -> password

 

This is how you would generate a hash table of some chain of hash algorithms:

 

MD5(SHA1(SHA1(MD5(SHA1(MD5(password)))))) -> password

 

The point is to store the final hash, not the intermediary hashes.

 

For simplicities take, lets pretend that you only generated an 8-bit salt, creating 256 possible hashes for each password. To generate a hash table for that, you would need to store every possible salt with each password:

 

MD5(SHA1(SHA1(MD5(SHA1(MD5(password + 00000000)))))) -> password

MD5(SHA1(SHA1(MD5(SHA1(MD5(password + 00000001)))))) -> password

MD5(SHA1(SHA1(MD5(SHA1(MD5(password + 00000010)))))) -> password

MD5(SHA1(SHA1(MD5(SHA1(MD5(password + 00000011)))))) -> password

etc.

 

Now if you generate a 128-bit salt for each password, that means 2^128 possible hashes for each password. That's a huge number of hashes to generate for even a single password, beyond the storage capacity of any system in the world, making it infeasible to generate a hash table or rainbow table.

 

Chaining hash algorithms together is useless as long as it means one hash per password, because you can still map each output hash to the input password that generated it.




#17 jkenn99

jkenn99

    Neowinian

  • Joined: 04-October 05
  • Location: British Columbia, Canada

Posted 18 July 2013 - 01:55

The true best-practice is to never ever design your own password storage alg. There are libraries out there for every language that are designed by people with much more security experience than you. For PHP, you should take a look at phpass.



#18 +theblazingangel

theblazingangel

    Software Engineer

  • Tech Issues Solved: 3
  • Joined: 25-March 04
  • Location: England, UK

Posted 18 July 2013 - 05:11

I've had this thought for a while - but always figured there was a reasonable solution to it.
 
I run a CMS system that currently hashes its passwords into MD5 and then into SHA1 passwords - or SHA256, depending on the system.

I've always thought why can't you hash passwords a lot, to make them more secure.
 
For example:

<?php
$password = 'ilovepassword1';
$securepass = sha1(md5(md5(sha1(md5(sha1($password))))));

echo $securepass;
?>
Apart from it being totally stupid, and inefficient - why isn't this a 'proper' solution?
 
Surely to crack it, you'd have to crack every layer- in the example above, 6 layers?
 
 
Would love an answer!
 
 
Tim

Your assumption that such hashes have to be cracked one layer at a time MUST be based on an presumption that an attacker will have no knowledge of your algorithm (your choice of which hash functions are used and how they are chained, etc) and will be unable to determine it. In theory and based on this presumption: In terms of an attacker using lookup tables, when they lookup a hash they would find that the result is a string that's not the password itself but instead the hash from the parent hashing function. They would then need to look that up, and so on until they eventually get to the actual password. There is an inefficiency of having to do multiple lookups, but more crucially for this to actually work in practice, in order to actually be able to perform these lookups, the attacker would require lookup tables that cover the hashes of all possible hashes. Such tables cannot exist because they would require a vast amount of disk space to store. Only two chained hash functions could therefore actually suffice here to block lookup attacks.

You cannot rely upon this presumption though. If we assume that an attacker does somehow know the algorithm, then with a lookup table based attack, the attacker can compile lookup tables based on your specific algorithm prior to then attempting an attack on the stolen hashes. Understand that hashing algorithms are designed to be quick, so throwing in a few extra function calls isn't really going to significantly impact an attacker generating them. Furthermore in relation to brute-force/dictionary based attacks against an offline copy of the hashes, the impact of your algorithm in terms of speed of execution is going to be negligible.

Xinox and Asik also raised some excellent additional points earlier.
 

It's more secure against dictionary attacks and rainbow tables, anyone that tells you otherwise is a grade A ****ing idiot.
It makes it weaker to collisions though.
 
People that go on about 'oh double hashing doesn't improve security' really need to have their ability to talk taken away.
Here's a quick example; If a hashing mechanism outputs a 32 character code from any input, and for A you run it once and B you run it twice:
A can be found in a lookup table expecially if it's less than 13 characters. A can also be found using a dictionary or brute-force attack.
B will not be found in a lookup table because it's 32 characters. If someone can provide even a 16 character rainbow table for MD5 (which is known to be broken) please, do. B will not be found in a dictionary attack _AT ALL_ and is incredibly unlikely to be found via a bruteforce attack UNLESS a collision is found. If a collision is found, they have an alternative string that hashes to give the correct MD5 hash, they can't they crack that string to get the original data used for the first MD5 though.
 
The real problems are, if someone has access to your site and database whereby they can read off all the hashed passwords, they can change any password to login to any account so don't need to crack the password at all, if however they want to get something else like a bank account or email account and the person has used the same password for both sites, that's what they'd be cracking the password for.

Again, you're also simply presuming the attacker does not know the algorithm.

I don't know why you think that chaining is somehow "weaker to collisions". Chaining multiple instances of the same hash function simply transforms one hash to another. Why would the final hash we settle on be weaker in terms of collisions than the first hash. If we chain different hash functions such as md5 and sha1 together, then as Xinox pointed out, entropy and therefore security is reduced to that of the weakest function. Furthermore I believe (and I'm by no means an expert) that 'second preimage' resistance would also be reduced to that of the weakest algorithm, and chaining would make no difference compared to simply using that weakest function on its own.

Also, in regards to the "real problem" as you put it, you can't just blindly state that an attacker with access to a set of password hashes is guaranteed to have write access to the database and is therefore only going to crack a password in order to access accounts on other services. That's crap. An attacker may have simply gained access to a backup of a database not the actual live database itself, or may have found a flaw in a web application through which they have gained read-only access. Also, even if they did have the ability to switch a hash on a user record and therefore login to the account, it doesn't mean that that is the best option for the attacker, it might be more advantageous on certain services to gain access to accounts without the account owners being aware that a malicious entity also has access.
 

I'd think devising a way to randomly rehash passwords at random time intervals may be more beneficial in providing security than devising a way to layer or chain things together.
I'm not a crypto expert but I love learning how the DSS, console, and cellular technologies encrypt and secure their 1's and 0's. From watching these industry leaders it seems real-time internet connected scenarios where the wheel (encryption) can be reinvented/changed at will, or several wheels (encryption keys) working in a phase-shift-keying routine seems more successful than layering or chaining encryptions off one another. Key in encryption is not to rely anything on anything else.. I hope I am making sense here. Sony lasted like 4 years just obfuscating static random numbers before the 3.55 signing bug was discovered. Microsoft lasted like 6 before someone figured out their processor favored 'ok' results when you just blanked the key half-way through its check. If theres a will theres a way, just hope by the time its figured out it the encryption is pointless.

Since hashing is non-reversible, the only time you could perform an operation on a user's password would be when they provide it in the login form, so there's a limit to the ability to "randomly" do something with it. Also, "rehashing" passwords would make absolutely zero difference. The same string will always result in the same exact hash every time it goes through the algorithm. I'm sure you knew that though really... What I expect you're really suggesting is the concept of forcing users to change their passwords every so often, which from a security perspective may have a little merit to it, but wouldn't go down well with users. Really it's salting and good choice of hash function that are the crucial things here.

I disagree with your simple notion that the key to encryption is to not rely one thing on another; in cryptography this seems to me to be prevalent. Most if not all crypto relies on the discreet logarithm problem for instance. HTTPS relies on both public-key (asymmetric) and symmetric crypto. I could go on, but I'm just nit-picking :p
 

It doesn't matter how many hash functions you chain together, the fact remains that, in the end, the same password will always produce the same hash. Therefore, you can produce a table for it. The most secure way to protect against hash/rainbow table attacks is to include a random salt so that the same password will produce a different hash each and every time. Doing it any other way is only putting the security of your users at risk.

I think you might have missed that what he wrote has to be based on a presumption of the attacker not knowing the algorithm.
 

Genius, so the solution to security is to append 1111111111111111 to all passwords before hashing. Since the password is now 32 characters it won't be found in a rainbow table :/

You've completely misunderstood what he was talking about.
 

Hashing is multiple times can work most of the time but using salt is a more common practice (in my experience). With that you can use different techniques to use the salt (http://www.neowin.ne...r-salt-storage/)
 
Some more good info http://crackstation....ng-security.htm

I made some comments in the thread you linked to relating to your "different techniques to use the salt"!
 

do u even read though?
So you're going to make a rainbow table of 32 character hashes? Seeing as it took 4 years of clustered computing to make the NTLM rainbow tables up to length 12, you're just talking straight out your arse. Yes I agree using salt is the best way to do it, but for the for-seeable future, 32 character or even longer length rainbow tables will not be appearing.

Lots of misunderstanding going on here, you and Xinox are arguing from two completely different perspectives!

#19 The_Decryptor

The_Decryptor

    STEAL THE DECLARATION OF INDEPENDENCE

  • Tech Issues Solved: 4
  • Joined: 28-September 02
  • Location: Sol System
  • OS: iSymbian 9.2 SP24.8 Mars Bar

Posted 18 July 2013 - 05:24

I don't see the multiple hashes making it less secure, but it doesn't really make it more secure either since while you're running multiple iterations of the hash function, they're "fast hashes", so you're not increasing the cost by a large extent. Something like bcrypt follows a similar design (where it iterates over the input multiple times), but it does it to increase the computational complexity of the entire hash computation (That is, it's designed to take a certain amount of time per hash, not a certain amount of iterations)

Regarding salts, instead of using just one salt for all accounts (I've seen that suggested/used before), use a random salt per user (like their username). Even without something like bcrypt that would defeat rainbow tables in the case where the attacker is trying multiple accounts (While if the attacker is just targeting one account, like an admin, it won't help at all, that's where bcrypt comes in)

#20 n_K

n_K

    Neowinian Senior

  • Tech Issues Solved: 3
  • Joined: 19-March 06
  • Location: here.
  • OS: FreeDOS
  • Phone: Nokia 3315

Posted 18 July 2013 - 11:59

So for anyone that says that double or triple or n+ hashing doesn't make it secure, put your money where your mouth is;

342a404105b959b98bf4c52af0732e6b

MD5 hash of an MD5 hash of a simple password.

And if in 7 days you can't produce either the original MD5 nor the original text, we'll just assume like previously predicted; you're wrong.



#21 +Phouchg

Phouchg

    Resident Misanthrope

  • Tech Issues Solved: 9
  • Joined: 28-March 11
  • Location: Neowin Detainment Camp

Posted 18 July 2013 - 12:18

How about you take your childish contests elsewhere and just understand that one plaintext produces one hash no matter how many times you hash it. Or one shirt stays one shirt now matter how many times you wash it.

 

I take a dictionary, I hash every entry from aaa to zzz (for example) of it:

MD5('aaa') = 47bce5c74f589f4867dbd57e9ca9f808

MD5('zzz') = f3abb86bd34cf4d52698f14c0da1dc60

 

Then I hash every result once more, because you've just told me that's what you did (or I might have found it myself because I'd got read access to your source code):

MD5('47bce5c74f589f4867dbd57e9ca9f808') = d4fbb7d8d5603db43ac2094f5955787c

MD5('f3abb86bd34cf4d52698f14c0da1dc60') = 689505e20843a46d0f9afaaf837dcb2b

 

And I come to know that:

MD5(MD5('aaa')) = d4fbb7d8d5603db43ac2094f5955787c

 

It works that way, not backwards. It's not even crypto 101, it's elementary school. Seriously, are you trolling us all?



#22 n_K

n_K

    Neowinian Senior

  • Tech Issues Solved: 3
  • Joined: 19-March 06
  • Location: here.
  • OS: FreeDOS
  • Phone: Nokia 3315

Posted 18 July 2013 - 12:38



How about you take your childish contests elsewhere and just understand that one plaintext produces one hash no matter how many times you hash it. Or one shirt stays one shirt now matter how many times you wash it.

 

I take a dictionary, I hash every entry from aaa to zzz (for example) of it:

MD5('aaa') = 47bce5c74f589f4867dbd57e9ca9f808

MD5('zzz') = f3abb86bd34cf4d52698f14c0da1dc60

 

Then I hash every result once more, because you've just told me that's what you did (or I might have found it myself because I'd got read access to your source code):

MD5('47bce5c74f589f4867dbd57e9ca9f808') = d4fbb7d8d5603db43ac2094f5955787c

MD5('f3abb86bd34cf4d52698f14c0da1dc60') = 689505e20843a46d0f9afaaf837dcb2b

 

And I come to know that:

MD5(MD5('aaa')) = d4fbb7d8d5603db43ac2094f5955787c

 

It works that way, not backwards. It's not even crypto 101, it's elementary school. Seriously, are you trolling us all?

Why don't you learn to ****ing read?

Using a salt means the salt is known, include salt in the cracking system.

Salts do not slow down cracking or stop dictionary/bruteforce attacks from working, all they do is stop rainbow tables.

An md5 hash of an md5 hash also stops rainbow table attacks because THERE ARE NO RAINBOW TABLES OF THE MD5 HASHES, WILL YOU PLEASE RE-READ UNTIL YOU FINALLY UNDERSTAND?

tldr; MD5'ing an MD5 stops rainbow table attacks like salting does, neither method stops or slows down dictionary/bruteforce attacks.



#23 +Phouchg

Phouchg

    Resident Misanthrope

  • Tech Issues Solved: 9
  • Joined: 28-March 11
  • Location: Neowin Detainment Camp

Posted 18 July 2013 - 12:53

Sure, with certain certainty, no one has computed such rainbow tables for me, but it's increasingly possible to do and when it's done, your method is fscked, which is unacceptable. I don't even need rainbow tables of MD5 hashes. I don't care of intermediary MD5 values just as I don't care of the number of rounds MD5 internally does. I mash the password any number of times and feed only the final value to the reduction function.

 

Instead we settle for the proven best method - proper salt, which instead makes rainbow tables *not even worth considering* rather than a increasingly feasible option.

 

Perhaps it'd also help if you'd turn down the rage dial a little.



#24 Mike

Mike

    Neowinian Senior

  • Joined: 11-August 02

Posted 18 July 2013 - 13:36

An md5 hash of an md5 hash also stops rainbow table attacks because THERE ARE NO RAINBOW TABLES OF THE MD5 HASHES, WILL YOU PLEASE RE-READ UNTIL YOU FINALLY UNDERSTAND?

 

You do realise that the md5 hashes have a small number of characters and a fixed length. The original MD5 (the hash of the password) is trivial to find because you know its exact length and what characters are in it!



#25 threetonesun

threetonesun

    Neowinian Senior

  • Tech Issues Solved: 1
  • Joined: 26-February 02

Posted 18 July 2013 - 13:49

You do realise that the md5 hashes have a small number of characters and a fixed length. The original MD5 (the hash of the password) is trivial to find because you know its exact length and what characters are in it!

 

Right, sha1(md5(password)) is... well, it's silly.

 

Adding salt prevents the generation of rainbow tables, adding iterations prevents (or at least, makes less feasible) brute force attacks. Both of these ideas have been used in modern encryption algorithms, there's not a good reason to try and cobble together something using md5 hashes.

 

The real concern is, if someone gets access to your entire database, what information to they now have? That's what often gets overlooked by sites.



#26 n_K

n_K

    Neowinian Senior

  • Tech Issues Solved: 3
  • Joined: 19-March 06
  • Location: here.
  • OS: FreeDOS
  • Phone: Nokia 3315

Posted 18 July 2013 - 15:26

You do realise that the md5 hashes have a small number of characters and a fixed length. The original MD5 (the hash of the password) is trivial to find because you know its exact length and what characters are in it!

Yeah, 32 characters long and it contains 36 possible letters per character, that's 6.334028666×10⁴⁹ combinations.

Assuming you can check 1 million hashes per second, that's 6.334028666×10⁴³ seconds or 1.055671444×10⁴² minutes or 1.759452407×10⁴⁰ hours or 7.331051697×10³⁸ days or 2.008507314×10³⁶ years, etc. to check every possible combination.

So, the double MD5 is still up on the other page if anyone's able to prove that double hashing is weak.



#27 OP Tjcrazy

Tjcrazy

    Your Average Neowin Guy.

  • Joined: 02-May 09
  • Location: The Cotswolds, United Kingdom

Posted 18 July 2013 - 17:52

Wow guys - seems like there are lots of mixed opinions on this one!

 

I've never looked into Salting passwords before, so start implementing salts now.

 

From what I understand, a Salt is a 'unique' phrase appended onto the end of a password, e.g.

sha1($password+$salt)

So what if I still multiple hashed that?

(md5(sha1($password+$salt))

Or what if I added a different salt everytime?

md5(sha1($password+$salt)+$salt2)


#28 ZakO

ZakO

    Neowinian

  • Tech Issues Solved: 2
  • Joined: 21-September 07
  • Location: Finland

Posted 18 July 2013 - 19:25

Wow guys - seems like there are lots of mixed opinions on this one!

 

I've never looked into Salting passwords before, so start implementing salts now.

 

From what I understand, a Salt is a 'unique' phrase appended onto the end of a password, e.g.

sha1($password+$salt)

So what if I still multiple hashed that?

(md5(sha1($password+$salt))

Or what if I added a different salt everytime?

md5(sha1($password+$salt)+$salt2)

 

To be honest you're better off just using an algorithm that implements a salt, key stretching and adjustable iterations at its core (e.g. bcrypt or scrypt).

 

Using a salt, sha1($password . $salt), will prevent people looking up the hashes in any existing rainbow tables, but if your server has been compromised the attacker will probably obtain your salt(s) too, meaning they can still brute force most of the passwords. A single modern GPU can generate 3 billion SHA1 hashes per second, in less than a week you could brute force all 8-character passwords (character set: 0-9A-Za-z!$%&*+,-.:;^_`~<>?@) unless you use a different salt per-password, multiple hashing won't prevent this either. 

 

BCrypt on the other hand is arbitrarily slow, giving you a compromise between security and speed (you can adjust the iteration count). Even a modern GPU (or CPU) will only be able to calculate around 20 hashes per second making brute-forcing non-dictionary words effectively useless, unless the attacker has unlimited funds. 

 

SHA1 (and other quick hashing algorithms) are good for verifying data integrity, but less than ideal for storing passwords. The relative calculation speed of SHA1/MD5 make them a perfect target for brute forcing.



#29 +theblazingangel

theblazingangel

    Software Engineer

  • Tech Issues Solved: 3
  • Joined: 25-March 04
  • Location: England, UK

Posted 18 July 2013 - 19:39

Your assumption that such hashes have to be cracked one layer at a time MUST be based on an presumption that an attacker will have no knowledge of your algorithm (your choice of which hash functions are used and how they are chained, etc) and will be unable to determine it. In theory and based on this presumption: In terms of an attacker using lookup tables, when they lookup a hash they would find that the result is a string that's not the password itself but instead the hash from the parent hashing function. They would then need to look that up, and so on until they eventually get to the actual password. There is an inefficiency of having to do multiple lookups, but more crucially for this to actually work in practice, in order to actually be able to perform these lookups, the attacker would require lookup tables that cover the hashes of all possible hashes. Such tables cannot exist because they would require a vast amount of disk space to store. Only two chained hash functions could therefore actually suffice here to block lookup attacks.

You cannot rely upon this presumption though. If we assume that an attacker does somehow know the algorithm, then with a lookup table based attack, the attacker can compile lookup tables based on your specific algorithm prior to then attempting an attack on the stolen hashes. Understand that hashing algorithms are designed to be quick, so throwing in a few extra function calls isn't really going to significantly impact an attacker generating them. Furthermore in relation to brute-force/dictionary based attacks against an offline copy of the hashes, the impact of your algorithm in terms of speed of execution is going to be negligible.

Xinox and Asik also raised some excellent additional points earlier.

Just want to correct myself on a point I made here in regards to hashes of hashes in lookup tables and iterative lookups. MD5 produces a 128-bit output so there are 2^128 (3.40282366920938463463374607431768211456 × 10^38) possible permutations, which would obviously require a vast amount of storage. However obviously you don't actually need a lookup table containing ever single possible hash of a hash. Underlying an attack you've got a much smaller set of password guesses and you'd only need hashes derived from these. So if for example you have one million possible passwords in your lookup table, and you're attacking a set of hashed passwords that have been put through three chained executions of md5() i.e. md5(md5(md5(password))), then for each password guess entry you'd also need to include in the lookup table the result of md5(md5(guess)) and md5(md5(md5(guess))) in order to do the complete iterative lookup, i.e. just three million entries. This requires far less disk space than I was originally considering and therefore makes an iterative lookup approach much more viable.

Though obviously as originally described, the attacker will most likely know your algorithm and so could instead create new lookup tables specific to it, trading some degree of processing time for a lower storage requirement.
 

I don't see the multiple hashes making it less secure, but it doesn't really make it more secure either since while you're running multiple iterations of the hash function, they're "fast hashes", so you're not increasing the cost by a large extent. Something like bcrypt follows a similar design (where it iterates over the input multiple times), but it does it to increase the computational complexity of the entire hash computation (That is, it's designed to take a certain amount of time per hash, not a certain amount of iterations)

Precisely, there is merit to the basic principle of iterative hashing because it increases the time required to perform an attack. However as you mention, hashing functions are designed to be fast and so chaining a few together is going to make little difference. PBKDF2 and bcrypt perform iterative hashing in a similar fashion, however, the algorithm is designed to be significantly slower, thousands of iterations are usually done, and the algorithm by which hashing is chained has been designed by experts in the field of cryptography. Use of one of these two hashing functions can have a significant impact on an attacker.
 

Regarding salts, instead of using just one salt for all accounts (I've seen that suggested/used before), use a random salt per user (like their username). Even without something like bcrypt that would defeat rainbow tables in the case where the attacker is trying multiple accounts (While if the attacker is just targeting one account, like an admin, it won't help at all, that's where bcrypt comes in)

Per-user salts is indeed the right way to use them. A single salt for all users invalidates basic lookup/rainbow tables requiring an attacker to generate a new set that incorporates the salt within the computation, with which hashes for all users can then be attacked. A per-user salt requires an attacker to generate new lookup/rainbow tables for each user individually, which further increases time and data storage requirements. Furthermore per-user salts help ensure that all hashes are unique, therefore if two users shared the same password the attacker would be unaware of this. Similarly if performing a brute-force/dictionary attack on an offline copy of hashes, each computation of a guess will only be valid for a single user record with per-user salts, which is particularly significant when combined with PBKDF2/bcrypt.

To be clear, salting does NOT "defeat" rainbow tables in any case, it simply requires new ones be generated that incorporate the salt in the computation.

Using usernames for salts isn't a great idea. Usernames are reused and may be publicly known, reducing lookup-table storage requirements for an attacker and allowing them to pre-compute lookup tables in advance of breaching a database. With random salts, which an attacker should presumably only gain access to at the same time as the hashes, i.e. upon breaching the database, lookup-tables must be generated at that point and passwords cracked before the breach is discovered and passwords changed. Using the username as a salt isn't terrible, but its not as good as a proper random salt.

I disagree with the "good rule of thumb" in the article some people are pointing to that suggests that salts should be as long as the output of the hash function. As they describe under the heading 'short salt', with a very short salt an attacker may have no problem generating lookup/rainbow tables covering all possible permutations of the salt, which I agree with, however recommending a salt length of 128bits in the case of md5 is just ridiculous in my opinion. It should be assumed of course that salts are available to the attacker.
 

So for anyone that says that double or triple or n+ hashing doesn't make it secure, put your money where your mouth is;
342a404105b959b98bf4c52af0732e6b
MD5 hash of an MD5 hash of a simple password.
And if in 7 days you can't produce either the original MD5 nor the original text, we'll just assume like previously predicted; you're wrong.

I personally do follow your train of thought, you are assuming that an attacker would have to lookup the hash in a table that contains all hashes of hashes, repeating this as many times as necessary (depending on how many times hashing functions were chained), eventually ending up at the first hash, at which point they would be trying to lookup the actual password that resulted in that first hash. You are also assuming that the lookup table needs to include all possible hashes of hashes and therefore arguing that this would be impossible because the lookup tables would be too vast to exist. However, you are completely misunderstanding how someone would go about attacking such a hashed password, as others are trying to explain to you. An attacker, knowing your hashing method - two chained executions of md5() - would simply generate a new lookup table of password guesses in which would be stored the resulting hash from your hashing mechanism against each possible password. The attacker would then lookup your hashes in this new lookup table.

To be really clear, let's say that an attacker wants to have 'hello' as an option in their lookup table and they are attacking a set of hashed passwords that have been hashed with two chained executions of md5(), i.e. md5(md5(password)). md5('hello') = 5d41402abc4b2a76b9719d911017c592 and md5(md5('hello')) = 69a329523ce1ec88bf63061863d9cb14. Based on your logic the attacker would use a lookup table based on single executions of md5() which would need to include the following entries:

5d41402abc4b2a76b9719d911017c592 -> hello
69a329523ce1ec88bf63061863d9cb14 -> 5d41402abc4b2a76b9719d911017c592

In actuality the attacker would build a new lookup table based on md5(md5(password) which does not need any hashes of hashes:

69a329523ce1ec88bf63061863d9cb14 -> hello

Furthermore I've explained at the top of this post why you don't actually need ALL hashes of hashes but just a subset.
 

Why don't you learn to ****ing read?
Using a salt means the salt is known, include salt in the cracking system.
Salts do not slow down cracking or stop dictionary/bruteforce attacks from working, all they do is stop rainbow tables.
An md5 hash of an md5 hash also stops rainbow table attacks because THERE ARE NO RAINBOW TABLES OF THE MD5 HASHES, WILL YOU PLEASE RE-READ UNTIL YOU FINALLY UNDERSTAND?
tldr; MD5'ing an MD5 stops rainbow table attacks like salting does, neither method stops or slows down dictionary/bruteforce attacks.

Salting does NOT stop lookup/rainbow tables, it simply requires new ones be generated that incorporate the salt in the computation.
Chained hashing also does NOT stop lookup/rainbow table type attacks, it simply requires that new tables be generated where hashes are computed using the same algorithm as used on the hashes to be attacked. Tables containing hashes of hashes are not necessary.
 

Perhaps it'd also help if you'd turn down the rage dial a little.

Agreed!
 

You do realise that the md5 hashes have a small number of characters and a fixed length. The original MD5 (the hash of the password) is trivial to find because you know its exact length and what characters are in it!

Err, no.
 

Right, sha1(md5(password)) is... well, it's silly.
 
Adding salt prevents the generation of rainbow tables, adding iterations prevents (or at least, makes less feasible) brute force attacks. Both of these ideas have been used in modern encryption algorithms, there's not a good reason to try and cobble together something using md5 hashes.
 
The real concern is, if someone gets access to your entire database, what information to they now have? That's what often gets overlooked by sites.

Again, salting does NOT stop lookup/rainbow tables, it simply requires new ones be generated that incorporate the salt in the computation.
Adding iterations does NOT prevent brute force attacks, it only slows them down to some degree.
 

Yeah, 32 characters long and it contains 36 possible letters per character, that's 6.334028666×10⁴⁹ combinations.
Assuming you can check 1 million hashes per second, that's 6.334028666×10⁴³ seconds or 1.055671444×10⁴² minutes or 1.759452407×10⁴⁰ hours or 7.331051697×10³⁸ days or 2.008507314×10³⁶ years, etc. to check every possible combination.
So, the double MD5 is still up on the other page if anyone's able to prove that double hashing is weak.

I don't know where you're getting 36 characters from. An MD5 hash is hexadecimal, i.e. it consists of characters 0-9 and a-f, in other words 16 possible characters. That's 16^32 = 3.40282366920938463463374607431768211456 × 10^38 possible permutations. I'm not going to bother going into the rest of it, check the first thing I wrote in this post for an explanation of why you don't need to iterate through all hashes of hashes.
 

Wow guys - seems like there are lots of mixed opinions on this one!

I've never looked into Salting passwords before, so start implementing salts now.

From what I understand, a Salt is a 'unique' phrase appended onto the end of a password, e.g.

sha1($password+$salt)
So what if I still multiple hashed that?
(md5(sha1($password+$salt))
Or what if I added a different salt everytime?
md5(sha1($password+$salt)+$salt2)

Replace the word 'phrase' with 'string', and it doesn't have to be appended, you can prepend it or even chop it and the password up and mash them together in some way. You should always assume that an attacker has access to your code though, so doing something fancy i.e. mashing the two together in some way is pointless. Just append/prepend it, your choice as to which.

Both of your suggested hash-chaining options are useless, they offer no real benefit whatsoever over simply adding a single salt to a single use of a hash function. Multiple salts make no difference, you need to assume the attacker has them along with the hash after all.

My advice:
  • Stop trying to come up with odd hashing algorithms like this, they're not going to help you at all.
  • Stop using md5/sha1, at least use sha256 or preferably in some cases PBKDF2/bcrypt.
  • Do use a salt and use a different one for each user.


#30 threetonesun

threetonesun

    Neowinian Senior

  • Tech Issues Solved: 1
  • Joined: 26-February 02

Posted 18 July 2013 - 19:49

Assuming you can check 1 million hashes per second

 

On what, a commodore 64? Your example is a little behind the times here.